diff --git a/CMakeLists.txt b/CMakeLists.txt index b53c6f6b71f..3e1c8fec02a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,7 @@ option(WITH_PYTHON_MODULE "Enable building as a python module which runs without option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ON) option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON) option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON) -option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" OFF) +option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" ON) option(WITH_BULLET "Enable Bullet (Physics Engine)" ON) option(WITH_GAMEENGINE "Enable Game Engine" ON) option(WITH_PLAYER "Build Player" OFF) @@ -190,8 +190,8 @@ option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON) option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON) option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON) option(WITH_MOD_REMESH "Enable Remesh Modifier" ON) -option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF) -mark_as_advanced(WITH_MOD_CLOTH_ELTOPO) +# option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF) # this is now only available in a branch +# mark_as_advanced(WITH_MOD_CLOTH_ELTOPO) option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF) # Image format support @@ -234,17 +234,13 @@ option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON) if(UNIX AND NOT APPLE) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) + option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF) endif() option(WITH_PYTHON_INSTALL "Copy system python into the blender install folder" ON) option(WITH_PYTHON_INSTALL_NUMPY "Copy system numpy into the blender install folder" ON) set(PYTHON_NUMPY_PATH "" CACHE PATH "Python to python site-packages or dist-packages containing 'numpy' module") mark_as_advanced(PYTHON_NUMPY_PATH) -if(MINGW) - option(WITH_MINGW64 "Use the 64-bit version of MinGW" OFF) - mark_as_advanced(WITH_MINGW64) -endif() - # Cycles option(WITH_CYCLES "Enable cycles Render Engine" ON) option(WITH_CYCLES_TEST "Build cycles test application" OFF) @@ -270,6 +266,9 @@ mark_as_advanced(WITH_ASSERT_ABORT) if(APPLE) + cmake_minimum_required(VERSION 2.8.8) + cmake_policy(VERSION 2.8.8) + if(NOT CMAKE_OSX_ARCHITECTURES) set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING "Choose the architecture you want to build Blender for: i386, x86_64 or ppc" @@ -289,18 +288,14 @@ if(APPLE) set(OSX_SYSTEM unsupported) endif() message(STATUS "Detected system-version: " ${OSX_SYSTEM}) - - if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our minimum target, if you have higher sdk, weak linking happens - endif() if(${CMAKE_GENERATOR} MATCHES "Xcode") - ##### workaround for actual official cmake incompatibility with xcode 4.3 ##### + ##### cmake incompatibility with xcode 4.3 and higher ##### if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var - message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip") + message(FATAL_ERROR "Xcode 4.3 and higher must be used with cmake 2.8-8 or higher") endif() - ### end workaround for actual official cmake incompatibility with xcode 4.3 ### + ### end cmake incompatibility with xcode 4.3 and higher ### if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3) # Xcode 4 defaults to the Apple LLVM Compiler. @@ -315,7 +310,28 @@ if(APPLE) endif() message(STATUS "Detected Xcode-version: " ${XCODE_VERSION}) + + if(${XCODE_VERSION} VERSION_LESS 4.3) + set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE) # use guaranteed existing sdk + else() + # note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed + # absolute pathes are more foolproof here ! + set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform) + set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk + set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE) + endif() + if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our min. target, if you use higher sdk, weak linking happens + endif() + + if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode") + # force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + add_definitions ("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() + option(WITH_COCOA "Use Cocoa framework instead of deprecated Carbon" ON) option(USE_QTKIT "Use QtKit instead of Carbon quicktime (needed for having partial quicktime for 64bit)" OFF) option(WITH_LIBS10.5 "Use 10.5 libs (needed for 64bit builds)" OFF) @@ -336,12 +352,20 @@ if(NOT WITH_GAMEENGINE AND WITH_PLAYER) message(FATAL_ERROR "WITH_PLAYER requires WITH_GAMEENGINE") endif() -if(NOT WITH_AUDASPACE AND (WITH_OPENAL OR WITH_SDL OR WITH_JACK OR WITH_GAMEENGINE)) - message(FATAL_ERROR "WITH_OPENAL/WITH_SDL/WITH_JACK/WITH_CODEC_FFMPEG/WITH_GAMEENGINE require WITH_AUDASPACE") +if(NOT WITH_AUDASPACE) + if(WITH_OPENAL) + message(FATAL_ERROR "WITH_OPENAL requires WITH_AUDASPACE") + endif() + if(WITH_JACK) + message(FATAL_ERROR "WITH_JACK requires WITH_AUDASPACE") + endif() + if(WITH_GAMEENGINE) + message(FATAL_ERROR "WITH_GAMEENGINE requires WITH_AUDASPACE") + endif() endif() if(NOT WITH_SDL AND WITH_GHOST_SDL) - message(FATAL_ERROR "WITH_GHOST_SDL requires WITH_SDL to be ON") + message(FATAL_ERROR "WITH_GHOST_SDL requires WITH_SDL") endif() if(WITH_IMAGE_REDCODE AND ((NOT WITH_IMAGE_OPENJPEG) OR (NOT WITH_CODEC_FFMPEG))) @@ -358,10 +382,6 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL) endif() -if(NOT WITH_FFTW3 AND WITH_MOD_OCEANSIM) - message(FATAL_ERROR "WITH_MOD_OCEANSIM requires WITH_FFTW3 to be ON") -endif() - # may as well build python module without a UI if(WITH_PYTHON_MODULE) set(WITH_HEADLESS ON) @@ -372,8 +392,8 @@ if(WITH_CYCLES) set(WITH_OPENIMAGEIO ON) endif() -# auto enable boost for cycles and booleans -if(WITH_CYCLES OR WITH_MOD_BOOLEAN) +# auto enable boost for cycles, booleans, audaspace or i18n +if(WITH_CYCLES OR WITH_MOD_BOOLEAN OR WITH_AUDASPACE OR WITH_INTERNATIONAL) set(WITH_BOOST ON) endif() @@ -461,14 +481,14 @@ set(PLATFORM_LINKFLAGS_DEBUG "") # For alternate Python locations the commandline can be used to override detected/default cache settings, e.g: # On Unix: # cmake ../blender \ -# -D PYTHON_VERSION=3.2 \ -# -D PYTHON_INCLUDE_DIR=/opt/py32/include/python3.2d \ -# -D PYTHON_LIBRARY=/opt/py32/lib/libpython3.2d.so +# -D PYTHON_VERSION=3.3 \ +# -D PYTHON_INCLUDE_DIR=/opt/py33/include/python3.3d \ +# -D PYTHON_LIBRARY=/opt/py33/lib/libpython3.3d.so # # On Macs: # cmake ../blender \ -# -D PYTHON_INCLUDE_DIR=/System/Library/Frameworks/Python.framework/Versions/3.2/include/python3.2 \ -# -D PYTHON_LIBPATH=/System/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/config \ +# -D PYTHON_INCLUDE_DIR=/System/Library/Frameworks/Python.framework/Versions/3.3/include/python3.3 \ +# -D PYTHON_LIBPATH=/System/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/config \ # -G Xcode # # When changing any of this remember to update the notes in doc/build_systems/cmake.txt @@ -477,50 +497,52 @@ set(PLATFORM_LINKFLAGS_DEBUG "") #Platform specifics if(UNIX AND NOT APPLE) - - # set lib directory if it exists - if(CMAKE_SYSTEM_NAME MATCHES "Linux") - if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/linux64) - else() - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/linux) + macro(find_package_wrapper) + STRING(TOUPPER ${ARGV0} _NAME_UPPER) + 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() - - if(NOT EXISTS ${LIBDIR}) - unset(LIBDIR) + find_package(${ARGV}) + if(${WITH_STATIC_LIBS}) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_cmake_find_library_suffixes_back}) + unset(_cmake_find_library_suffixes_back) endif() - endif() + endmacro() - find_package(JPEG REQUIRED) - find_package(PNG REQUIRED) - find_package(ZLIB REQUIRED) - find_package(Freetype REQUIRED) + find_package_wrapper(JPEG REQUIRED) + find_package_wrapper(PNG REQUIRED) + find_package_wrapper(ZLIB REQUIRED) + find_package_wrapper(Freetype REQUIRED) if(WITH_PYTHON) - # No way to set py32. remove for now. + # No way to set py33. remove for now. # find_package(PythonLibs) # Use our own instead, since wothout py is such a rare case, # require this package + # XXX Linking errors with debian static python :/ +# find_package_wrapper(PythonLibsUnix REQUIRED) find_package(PythonLibsUnix REQUIRED) endif() - if(WITH_IMAGE_OPENEXR) - find_package(OpenEXR) # our own module + find_package_wrapper(OpenEXR) # our own module if(NOT OPENEXR_FOUND) set(WITH_IMAGE_OPENEXR OFF) endif() endif() if(WITH_IMAGE_OPENJPEG) - find_package(OpenJPEG) + find_package_wrapper(OpenJPEG) if(NOT OPENJPEG_FOUND) set(WITH_IMAGE_OPENJPEG OFF) endif() endif() if(WITH_IMAGE_TIFF) + # XXX Linking errors with debian static tiff :/ +# find_package_wrapper(TIFF) find_package(TIFF) if(NOT TIFF_FOUND) set(WITH_IMAGE_TIFF OFF) @@ -529,14 +551,14 @@ if(UNIX AND NOT APPLE) # Audio IO if(WITH_OPENAL) - find_package(OpenAL) + find_package_wrapper(OpenAL) if(NOT OPENAL_FOUND) set(WITH_OPENAL OFF) endif() endif() if(WITH_SDL) - find_package(SDL) + find_package_wrapper(SDL) mark_as_advanced( SDLMAIN_LIBRARY SDL_INCLUDE_DIR @@ -550,7 +572,7 @@ if(UNIX AND NOT APPLE) endif() if(WITH_JACK) - find_package(Jack) + find_package_wrapper(Jack) if(NOT JACK_FOUND) set(WITH_JACK OFF) endif() @@ -558,22 +580,15 @@ if(UNIX AND NOT APPLE) # Codecs if(WITH_CODEC_SNDFILE) - find_package(SndFile) + find_package_wrapper(SndFile) if(NOT SNDFILE_FOUND) set(WITH_CODEC_SNDFILE OFF) endif() endif() if(WITH_CODEC_FFMPEG) - # use lib dir if available and nothing else specified - if(LIBDIR AND NOT FFMPEG) - set(FFMPEG ${LIBDIR}/ffmpeg CACHE PATH "FFMPEG Directory") - # XXX, some distros might need 'theoraenc theoradec' too - set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale dirac_encoder mp3lame ogg orc-0.4 schroedinger-1.0 theora vorbis vorbisenc vpx x264 xvidcore faad asound CACHE STRING "FFMPEG Libraries") - else() - set(FFMPEG /usr CACHE PATH "FFMPEG Directory") - set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries") - endif() + set(FFMPEG /usr CACHE PATH "FFMPEG Directory") + set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries") mark_as_advanced(FFMPEG) @@ -589,54 +604,32 @@ if(UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS") endif() - if(WITH_INTERNATIONAL) - find_library(INTL_LIBRARY - NAMES intl - PATHS - /sw/lib - ) - - find_library(ICONV_LIBRARY - NAMES iconv - PATHS - /sw/lib - ) - mark_as_advanced( - ICONV_LIBRARY - INTL_LIBRARY - ) - - if(INTL_LIBRARY AND ICONV_LIBRARY) - set(GETTEXT_LIBRARIES ${INTL_LIBRARY} ${ICONV_LIBRARY}) - endif() - endif() - if(WITH_FFTW3) - find_package(Fftw3) + find_package_wrapper(Fftw3) if(NOT FFTW3_FOUND) set(WITH_FFTW3 OFF) endif() endif() if(WITH_OPENCOLLADA) - find_package(OpenCOLLADA) + find_package_wrapper(OpenCOLLADA) if(OPENCOLLADA_FOUND) - find_package(XML2) - find_package(PCRE) + find_package_wrapper(XML2) + find_package_wrapper(PCRE) else() set(WITH_OPENCOLLADA OFF) endif() endif() if(WITH_MEM_JEMALLOC) - find_package(JeMalloc) + find_package_wrapper(JeMalloc) if(NOT JEMALLOC_FOUND) set(WITH_MEM_JEMALLOC OFF) endif() endif() if (WITH_INPUT_NDOF) - find_package(Spacenav) + find_package_wrapper(Spacenav) if(NOT SPACENAV_FOUND) set(WITH_INPUT_NDOF OFF) endif() @@ -651,14 +644,23 @@ if(UNIX AND NOT APPLE) if(WITH_BOOST) # uses in build instructions to override include and library variables if(NOT BOOST_CUSTOM) - # use lib dir if available and nothing else specified - if(LIBDIR AND NOT BOOST_ROOT) - set(BOOST_ROOT ${LIBDIR}/boost) + # XXX No more lib dir, is this multithread stuff still needed? + if(${WITH_STATIC_LIBS}) + set(Boost_USE_STATIC_LIBS ON) + endif() + if(NOT BOOST_ROOT) set(Boost_USE_MULTITHREADED OFF) else() set(Boost_USE_MULTITHREADED ON) endif() - find_package(Boost 1.34 COMPONENTS filesystem regex system thread) + set(__boost_packages filesystem regex system thread date_time) + if (WITH_INTERNATIONAL) + list(APPEND __boost_packages locale) + endif() + find_package(Boost 1.34 COMPONENTS ${__boost_packages}) + if(Boost_USE_STATIC_LIBS AND Boost_USE_ICU) + find_package(IcuLinux) + endif() mark_as_advanced(Boost_DIR) # why doesnt boost do this? endif() @@ -669,12 +671,7 @@ if(UNIX AND NOT APPLE) endif() if(WITH_OPENIMAGEIO) - # use lib dir if available and nothing else specified - if(LIBDIR AND NOT OPENIMAGEIO_ROOT_DIR) - set(OPENIMAGEIO_ROOT_DIR ${LIBDIR}/oiio) - endif() - - find_package(OpenImageIO) + find_package_wrapper(OpenImageIO) set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${ZLIB_LIBRARIES} ${BOOST_LIBRARIES}) set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere @@ -694,12 +691,7 @@ if(UNIX AND NOT APPLE) endif() if(WITH_OPENCOLORIO) - # use lib dir if available and nothing else specified - if(LIBDIR AND NOT OPENCOLORIO_ROOT_DIR) - set(OPENCOLORIO_ROOT_DIR ${LIBDIR}/ocio) - endif() - - find_package(OpenColorIO) + find_package_wrapper(OpenColorIO) set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES}) set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere @@ -711,14 +703,23 @@ if(UNIX AND NOT APPLE) endif() endif() + # XXX Maybe most of this section should go into an llvm module? if(WITH_LLVM) - set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") - set(LLVM_VERSION "3.0" CACHE STRING "Version of LLVM to use") + # Set llvm version if not specified + if(NOT LLVM_VERSION) + set(LLVM_VERSION "3.0") + endif() set(LLVM_STATIC YES) if(LLVM_DIRECTORY) - set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config") + FIND_PROGRAM(LLVM_CONFIG llvm-config-${LLVM_VERSION} HINTS ${LLVM_DIRECTORY}/bin NO_CMAKE_PATH) + if(NOT LLVM_CONFIG) + FIND_PROGRAM(LLVM_CONFIG llvm-config HINTS ${LLVM_DIRECTORY}/bin NO_CMAKE_PATH) + endif() else() - set(LLVM_CONFIG llvm-config) + FIND_PROGRAM(LLVM_CONFIG llvm-config-${LLVM_VERSION}) + if(NOT LLVM_CONFIG) + FIND_PROGRAM(LLVM_CONFIG llvm-config) + endif() endif() execute_process(COMMAND ${LLVM_CONFIG} --version OUTPUT_VARIABLE LLVM_VERSION @@ -730,11 +731,13 @@ if(UNIX AND NOT APPLE) OUTPUT_VARIABLE LLVM_LIB_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) find_library(LLVM_LIBRARY - NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get + NAMES LLVMAnalysis # first of a whole bunch of libs to get PATHS ${LLVM_LIB_DIR}) message(STATUS "LLVM version = ${LLVM_VERSION}") message(STATUS "LLVM dir = ${LLVM_DIRECTORY}") message(STATUS "LLVM lib dir = ${LLVM_LIB_DIR}") + set(LLVM_VERSION ${LLVM_VERSION} CACHE STRING "Version of LLVM to use") + set(LLVM_DIRECTORY ${LLVM_DIRECTORY} CACHE PATH "Path to the LLVM installation") if(LLVM_LIBRARY AND LLVM_DIRECTORY AND LLVM_LIB_DIR) if(LLVM_STATIC) @@ -746,10 +749,12 @@ if(UNIX AND NOT APPLE) OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY}) endif() - message(STATUS "LLVM library = ${LLVM_LIBRARY}") else() message(FATAL_ERROR "LLVM not found.") endif() + + # Fix for conflict with Mesa llvmpipe + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/source/creator/blender.map") endif() if(WITH_CYCLES_OSL) @@ -812,7 +817,7 @@ if(UNIX AND NOT APPLE) endif() endif() - set(PLATFORM_LINKFLAGS "-pthread") + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -pthread") # lfs on glibc, all compilers should use add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) @@ -857,10 +862,18 @@ elseif(WIN32) if(CMAKE_COMPILER_IS_GNUCC) set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32) - + INCLUDE (CheckCSourceCompiles) # Setup 64bit and 64bit windows systems + CHECK_C_SOURCE_COMPILES(" + #ifndef __MINGW64__ + #error + #endif + main(){} + " + WITH_MINGW64) + if(WITH_MINGW64) - message("Set 64 bit compiler for MinGW.") + message("Compiling for 64 bit with MinGW-w64.") set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64) endif() else() @@ -875,13 +888,6 @@ elseif(WIN32) add_definitions(-DWIN32) - if(WITH_INTERNATIONAL) - set(ICONV ${LIBDIR}/iconv) - set(ICONV_INCLUDE_DIRS ${ICONV}/include) - set(ICONV_LIBRARIES iconv) - set(ICONV_LIBPATH ${ICONV}/lib) - endif() - set(JPEG "${LIBDIR}/jpeg") set(JPEG_INCLUDE_DIR "${JPEG}/include") set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined @@ -923,28 +929,22 @@ elseif(WIN32) if(WITH_CYCLES_OSL) set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") - message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") - find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) - # WARNING! depends on correct order of OSL libs linking list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER) set(OSL_FOUND TRUE) - message(STATUS "OSL includes = ${OSL_INCLUDES}") - message(STATUS "OSL library = ${OSL_LIBRARIES}") - message(STATUS "OSL compiler = ${OSL_COMPILER}") else() message(STATUS "OSL not found") endif() endif() if(MSVC) - set(PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid) + set(PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid psapi) add_definitions(/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /D_CONSOLE /D_LIB) @@ -974,13 +974,6 @@ elseif(WIN32) set(CXX_WARNINGS "${_WARNINGS}") unset(_WARNINGS) - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - set(GETTEXT_LIBRARIES gnu_gettext) - endif() - if(WITH_MOD_CLOTH_ELTOPO) set(LAPACK ${LIBDIR}/lapack) # set(LAPACK_INCLUDE_DIR ${LAPACK}/include) @@ -1072,6 +1065,7 @@ elseif(WIN32) if(WITH_IMAGE_OPENEXR) set_lib_path(OPENEXR "openexr") set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) + set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR) set(OPENEXR_LIBPATH ${OPENEXR}/lib) set(OPENEXR_LIBRARIES ${OPENEXR_LIBPATH}/Iex.lib @@ -1080,12 +1074,6 @@ elseif(WIN32) ${OPENEXR_LIBPATH}/Imath.lib ${OPENEXR_LIBPATH}/IlmThread.lib ) - set(OPENEXR_INCLUDE_DIRS - ${OPENEXR_INCLUDE_DIR} - ${OPENEXR_INCLUDE_DIR}/IlmImf - ${OPENEXR_INCLUDE_DIR}/Iex - ${OPENEXR_INCLUDE_DIR}/Imath - ) endif() if(WITH_IMAGE_TIFF) @@ -1103,9 +1091,17 @@ elseif(WIN32) if(WITH_PYTHON) # normally cached but not since we include them with blender - set(PYTHON_VERSION 3.2) # CACHE STRING) + if(MSVC10) + set(PYTHON_VERSION 3.2) # CACHE STRING) + else() + set(PYTHON_VERSION 3.3) # CACHE STRING) + endif() + set_lib_path(PYTHON "python") - set(PYTHON_LIBRARY ${PYTHON}/lib/python32.lib) #CACHE FILEPATH + STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) + 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 set(PYTHON_INCLUDE_DIR ${LIBDIR}/python/include/python${PYTHON_VERSION}) @@ -1133,17 +1129,28 @@ elseif(WIN32) debug libboost_date_time-${BOOST_DEBUG_POSTFIX} debug libboost_filesystem-${BOOST_DEBUG_POSTFIX} debug libboost_regex-${BOOST_DEBUG_POSTFIX} debug libboost_system-${BOOST_DEBUG_POSTFIX} debug libboost_thread-${BOOST_DEBUG_POSTFIX}) + if(WITH_INTERNATIONAL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized libboost_locale-${BOOST_POSTFIX} + debug libboost_locale-${BOOST_DEBUG_POSTFIX}) + endif(WITH_INTERNATIONAL) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB") endif() if(WITH_OPENIMAGEIO) set(OPENIMAGEIO ${LIBDIR}/openimageio) set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) - set(OPENIMAGEIO_LIBRARIES OpenImageIO) + set(OPENIMAGEIO_LIBRARIES optimized OpenImageIO debug OpenImageIO_d) set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib) - set(OPENIMAGEIO_DEFINITIONS) + set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0") endif() + if(WITH_LLVM) + set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + file(GLOB LLVM_LIBRARY ${LLVM_DIRECTORY}/lib/*.lib) + set(LLVM_STATIC YES) + endif() + if(WITH_OPENCOLORIO) set(OPENCOLORIO ${LIBDIR}/opencolorio) set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) @@ -1152,6 +1159,7 @@ elseif(WIN32) set(OPENCOLORIO_DEFINITIONS) endif() + set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib") # MSVC only, Mingw doesnt need @@ -1186,16 +1194,8 @@ elseif(WIN32) add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) - add_definitions(-DFREE_WINDOWS) - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - set(GETTEXT_LIBRARIES intl) - endif() - set(PNG "${LIBDIR}/png") set(PNG_INCLUDE_DIR "${PNG}/include") set(PNG_LIBPATH ${PNG}/lib) # not cmake defined @@ -1215,7 +1215,7 @@ elseif(WIN32) #comes with own pthread library if(NOT WITH_MINGW64) set(PTHREADS ${LIBDIR}/pthreads) - set(PTHREADS_INCLUDE_DIRS ${PTHREADS}/include) + #set(PTHREADS_INCLUDE_DIRS ${PTHREADS}/include) set(PTHREADS_LIBPATH ${PTHREADS}/lib) set(PTHREADS_LIBRARIES pthreadGC2) endif() @@ -1263,6 +1263,7 @@ elseif(WIN32) if(WITH_IMAGE_OPENEXR) set(OPENEXR ${LIBDIR}/openexr) + set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR) set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex) set(OPENEXR_LIBPATH ${OPENEXR}/lib) @@ -1287,9 +1288,9 @@ elseif(WIN32) if(WITH_PYTHON) # normally cached but not since we include them with blender - set(PYTHON_VERSION 3.2) # CACHE STRING) + set(PYTHON_VERSION 3.3) # CACHE STRING) set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH) - set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python32mw.lib") # CACHE FILEPATH) + set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python33mw.lib") # CACHE FILEPATH) # uncached vars set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") @@ -1313,6 +1314,11 @@ elseif(WIN32) debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX} boost_regex-${BOOST_DEBUG_POSTFIX} boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX}) + if(WITH_INTERNATIONAL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized boost_locale-${BOOST_POSTFIX} + debug boost_locale-${BOOST_DEBUG_POSTFIX}) + endif() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ") endif() @@ -1325,6 +1331,34 @@ elseif(WIN32) set(OPENIMAGEIO_DEFINITIONS) endif() + if(WITH_LLVM) + set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + set(LLVM_LIB_DIR ${LLVM_DIRECTORY}/lib) + #Explicitly set llvm lib order. + #---- WARNING ON GCC ORDER OF LIBS IS IMPORTANT, DO NOT CHANGE! --------- + set(LLVM_LIBRARY LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMAnalysis LLVMArchive + LLVMAsmParser LLVMAsmPrinter + LLVMBitReader LLVMBitWriter + LLVMDebugInfo LLVMExecutionEngine + LLVMInstCombine LLVMInstrumentation + LLVMInterpreter LLVMJIT + LLVMLinker LLVMMC + LLVMMCDisassembler LLVMMCJIT + LLVMMCParser LLVMObject + LLVMRuntimeDyld + LLVMSupport + LLVMTableGen LLVMTarget + LLVMTransformUtils LLVMVectorize + LLVMX86AsmParser LLVMX86AsmPrinter + LLVMX86CodeGen LLVMX86Desc + LLVMX86Disassembler LLVMX86Info + LLVMX86Utils LLVMipa + LLVMipo LLVMCore) + #imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc + set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -limagehlp") + set(LLVM_STATIC YES) + endif() + if(WITH_OPENCOLORIO) set(OPENCOLORIO ${LIBDIR}/opencolorio) set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) @@ -1347,16 +1381,6 @@ elseif(APPLE) set(WITH_LIBS10.5 ON CACHE BOOL "Use 10.5 libs" FORCE) # valid also for 10.6/10.7 endif() - if(${XCODE_VERSION} VERSION_LESS 4.3) - set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE) # use guaranteed existing sdk - else() - # note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed - # absolute pathes are more foolproof here ! - set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform) - set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk - set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE) - endif() - if(WITH_LIBS10.5) set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-9.x.universal) else() @@ -1379,10 +1403,13 @@ elseif(APPLE) endif() if(WITH_JACK) - set(JACK /usr) - set(JACK_INCLUDE_DIRS ${JACK}/include/jack) - set(JACK_LIBRARIES jack) - set(JACK_LIBPATH ${JACK}/lib) + find_library(JACK_FRAMEWORK + NAMES jackmp + ) + set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) + if(NOT JACK_FRAMEWORK) + set(WITH_JACK OFF) + endif() endif() if(WITH_CODEC_SNDFILE) @@ -1394,13 +1421,13 @@ elseif(APPLE) if(WITH_PYTHON) if(NOT WITH_PYTHON_MODULE) - # we use precompiled libraries for py 3.2 and up by default + # we use precompiled libraries for py 3.3 and up by default # normally cached but not since we include them with blender - set(PYTHON_VERSION 3.2) - set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") + set(PYTHON_VERSION 3.3) + set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}m") # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet - set(PYTHON_LIBRARY python${PYTHON_VERSION}) + set(PYTHON_LIBRARY python${PYTHON_VERSION}m) set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}") # set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled else() @@ -1420,13 +1447,6 @@ elseif(APPLE) set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") endif() - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS "${GETTEXT}/include") - set(GETTEXT_LIBRARIES intl iconv) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - endif() - if(WITH_FFTW3) set(FFTW3 ${LIBDIR}/fftw3) set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) @@ -1493,10 +1513,10 @@ elseif(APPLE) if(WITH_INPUT_NDOF) # This thread it *should* work and check the framework - campbell # http://www.cmake.org/pipermail/cmake/2005-December/007740.html - find_library(3D_CONNEXION_CLIENT_LIBRARY + find_library(3DCONNEXION_CLIENT_FRAMEWORK NAMES 3DconnexionClient ) - if(NOT 3D_CONNEXION_CLIENT_LIBRARY) + if(NOT 3DCONNEXION_CLIENT_FRAMEWORK) set(WITH_INPUT_NDOF OFF) endif() @@ -1505,6 +1525,10 @@ elseif(APPLE) endif() endif() + if(WITH_JACK) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework jackmp") + endif() + else() set(PLATFORM_CFLAGS "-pipe -funsigned-char") set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") @@ -1567,7 +1591,11 @@ elseif(APPLE) if(WITH_BOOST) set(BOOST ${LIBDIR}/boost) set(BOOST_INCLUDE_DIR ${BOOST}/include) - set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt) + set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt boost_wave-mt) + if (WITH_INTERNATIONAL) + list(APPEND BOOST_LIBRARIES boost_locale-mt) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale needs it ! + endif() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS) endif() @@ -1592,7 +1620,7 @@ elseif(APPLE) set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") set(LLVM_VERSION "3.1" CACHE STRING "Version of LLVM to use") set(LLVM_STATIC YES) - if(LLVM_DIRECTORY) + if(EXISTS "${LLVM_DIRECTORY}/bin/llvm-config") set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config") else() set(LLVM_CONFIG llvm-config) @@ -1607,11 +1635,8 @@ elseif(APPLE) OUTPUT_VARIABLE LLVM_LIB_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) find_library(LLVM_LIBRARY - NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get + NAMES LLVMAnalysis # first of a whole bunch of libs to get PATHS ${LLVM_LIB_DIR}) - message(STATUS "LLVM version = ${LLVM_VERSION}") - message(STATUS "LLVM dir = ${LLVM_DIRECTORY}") - message(STATUS "LLVM lib dir = ${LLVM_LIB_DIR}") if(LLVM_LIBRARY AND LLVM_DIRECTORY AND LLVM_LIB_DIR) if(LLVM_STATIC) @@ -1623,7 +1648,6 @@ elseif(APPLE) OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY}) endif() - message(STATUS "LLVM library = ${LLVM_LIBRARY}") else() message(FATAL_ERROR "LLVM not found.") endif() @@ -1632,8 +1656,6 @@ elseif(APPLE) if(WITH_CYCLES_OSL) set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") - message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") - find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) @@ -1644,9 +1666,6 @@ elseif(APPLE) if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER) set(OSL_FOUND TRUE) - message(STATUS "OSL includes = ${OSL_INCLUDES}") - message(STATUS "OSL library = ${OSL_LIBRARIES}") - message(STATUS "OSL compiler = ${OSL_COMPILER}") else() message(STATUS "OSL not found") endif() @@ -1678,6 +1697,10 @@ if(APPLE OR WIN32) endif() endif() +if(NOT WITH_FFTW3 AND WITH_MOD_OCEANSIM) + message(FATAL_ERROR "WITH_MOD_OCEANSIM requires WITH_FFTW3 to be ON") +endif() + if(WITH_CYCLES) if(NOT WITH_OPENIMAGEIO) message(FATAL_ERROR "Cycles reqires WITH_OPENIMAGEIO, the library may not have been found. Configure OIIO or disable WITH_CYCLES") @@ -1693,6 +1716,11 @@ if(WITH_CYCLES) endif() endif() +if(WITH_INTERNATIONAL) + if(NOT WITH_BOOST) + message(FATAL_ERROR "Internationalization reqires WITH_BOOST, the library may not have been found. Configure BOOST or disable WITH_INTERNATIONAL") + endif() +endif() # See TEST_SSE_SUPPORT() for how this is defined. @@ -1842,7 +1870,7 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero) # gcc 4.2 gives annoying warnings on every file with this - if ("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER "4.2") + if (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3") ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized) endif() @@ -1862,7 +1890,7 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero) # gcc 4.2 gives annoying warnings on every file with this - if ("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER "4.2") + if (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3") ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized) endif() @@ -1935,12 +1963,13 @@ if(WITH_PYTHON) if(WITH_PYTHON_INSTALL AND WITH_PYTHON_INSTALL_NUMPY) # set but invalid - if(NOT ${PYTHON_NUMPY_PATH} STREQUAL "") - if(NOT EXISTS "${PYTHON_NUMPY_PATH}/numpy") - message(WARNING "PYTHON_NUMPY_PATH is invalid, numpy not found in '${PYTHON_NUMPY_PATH}' " - "WITH_PYTHON_INSTALL_NUMPY option will be ignored when installing python") - set(WITH_PYTHON_INSTALL_NUMPY OFF) - endif() + # -- disabled until we make numpy bundled with blender - campbell + if((NOT ${PYTHON_NUMPY_PATH} STREQUAL "") AND (NOT ${PYTHON_NUMPY_PATH} MATCHES NOTFOUND)) +# if(NOT EXISTS "${PYTHON_NUMPY_PATH}/numpy") +# message(WARNING "PYTHON_NUMPY_PATH is invalid, numpy not found in '${PYTHON_NUMPY_PATH}' " +# "WITH_PYTHON_INSTALL_NUMPY option will be ignored when installing python") +# set(WITH_PYTHON_INSTALL_NUMPY OFF) +# endif() # not set, so initialize else() string(REPLACE "." ";" _PY_VER_SPLIT "${PYTHON_VERSION}") diff --git a/GNUmakefile b/GNUmakefile index f8207787cbe..c1b67c86ed2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -173,14 +173,15 @@ help: @echo " * test_style_osl_qtc - checks OpenShadingLanguage conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" @echo "" @echo "Static Source Code Checking (not associated with building blender)" - @echo " * check_cppcheck - run blender source through cppcheck (C & C++)" - @echo " * check_clang_array - run blender source through clang array checking script (C & C++)" - @echo " * check_splint - run blenders source through splint (C only)" - @echo " * check_sparse - run blenders source through sparse (C only)" - @echo " * check_smatch - run blenders source through smatch (C only)" - @echo " * check_spelling_c - check for spelling errors (OSL only)" - @echo " * check_spelling_osl - check for spelling errors (C/C++ only)" - @echo " * check_spelling_py - check for spelling errors (Python only)" + @echo " * check_cppcheck - run blender source through cppcheck (C & C++)" + @echo " * check_clang_array - run blender source through clang array checking script (C & C++)" + @echo " * check_splint - run blenders source through splint (C only)" + @echo " * check_sparse - run blenders source through sparse (C only)" + @echo " * check_smatch - run blenders source through smatch (C only)" + @echo " * check_spelling_c - check for spelling errors (OSL only)" + @echo " * check_spelling_c_qtc - same as check_spelling_c but outputs QtCreator tasks format" + @echo " * check_spelling_osl - check for spelling errors (C/C++ only)" + @echo " * check_spelling_py - check for spelling errors (Python only)" @echo "" @echo "Utilities (not associated with building blender)" @echo " * tbz - create a compressed svn export 'blender_archive.tar.bz2'" @@ -240,13 +241,13 @@ test_style_c_qtc: test_style_osl: # run our own checks on C/C++ style - PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/osl + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/shaders test_style_osl_qtc: # run our own checks on C/C++ style USE_QTC_TASK=1 \ - PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/osl > \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/shaders > \ test_style.tasks @echo "written: test_style.tasks" @@ -270,32 +271,44 @@ project_eclipse: check_cppcheck: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py check_clang_array: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_clang_array.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_clang_array.py check_splint: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py check_sparse: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py check_smatch: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py check_spelling_py: - cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/release/scripts + cd $(BUILD_DIR) ; \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/release/scripts check_spelling_c: - cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/source + cd $(BUILD_DIR) ; \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/source + +check_spelling_c_qtc: + cd $(BUILD_DIR) ; USE_QTC_TASK=1 \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/source > \ + $(BLENDER_DIR)/check_spelling_c.tasks check_spelling_osl: - cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/intern/cycles/kernel/osl + cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/intern/cycles/kernel/shaders # ----------------------------------------------------------------------------- # Utilities diff --git a/SConstruct b/SConstruct index 064ae0bc0b5..c2bae0459ca 100644 --- a/SConstruct +++ b/SConstruct @@ -306,6 +306,15 @@ if env['OURPLATFORM']=='darwin': else: env.Append(LINKFLAGS=['-Xlinker','-weak_framework','-Xlinker','Jackmp']) + if env['WITH_BF_CYCLES_OSL'] == 1: + OSX_OSL_LIBPATH = Dir(env.subst(env['BF_OSL_LIBPATH'])).abspath + # we need 2 variants of passing the oslexec with the force_load option, string and list type atm + env.Append(LINKFLAGS=['-L'+OSX_OSL_LIBPATH,'-loslcomp','-force_load '+ OSX_OSL_LIBPATH +'/liboslexec.a','-loslquery']) + env.Append(BF_PROGRAM_LINKFLAGS=['-Xlinker','-force_load','-Xlinker',OSX_OSL_LIBPATH +'/liboslexec.a']) + + # Trying to get rid of eventually clashes, we export some explicite as local symbols + env.Append(LINKFLAGS=['-Xlinker','-unexported_symbols_list','-Xlinker','./source/creator/osx_locals.map']) + if env['WITH_BF_OPENMP'] == 1: if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): env['CCFLAGS'].append('/openmp') @@ -422,16 +431,22 @@ if not quickie and do_clean: # with _any_ library but since we used a fixed python version this tends to # be most problematic. if env['WITH_BF_PYTHON']: - py_h = os.path.join(Dir(env.subst('${BF_PYTHON_INC}')).abspath, "Python.h") + found_python_h = found_pyconfig_h = False + for bf_python_inc in env.subst('${BF_PYTHON_INC}').split(): + py_h = os.path.join(Dir(bf_python_inc).abspath, "Python.h") + if os.path.exists(py_h): + found_python_h = True + py_h = os.path.join(Dir(bf_python_inc).abspath, "pyconfig.h") + if os.path.exists(py_h): + found_pyconfig_h = True - if not os.path.exists(py_h): - print("\nMissing: \"" + env.subst('${BF_PYTHON_INC}') + os.sep + "Python.h\",\n" + if not (found_python_h and found_pyconfig_h): + print("\nMissing: Python.h and/or pyconfig.h in\"" + env.subst('${BF_PYTHON_INC}') + "\",\n" " Set 'BF_PYTHON_INC' to point " - "to a valid python include path.\n Containing " - "Python.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"") + "to valid python include path(s).\n Containing " + "Python.h and pyconfig.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"") Exit() - del py_h if not os.path.isdir ( B.root_build_dir): @@ -571,11 +586,11 @@ B.init_lib_dict() Export('env') -BuildDir(B.root_build_dir+'/source', 'source', duplicate=0) +VariantDir(B.root_build_dir+'/source', 'source', duplicate=0) SConscript(B.root_build_dir+'/source/SConscript') -BuildDir(B.root_build_dir+'/intern', 'intern', duplicate=0) +VariantDir(B.root_build_dir+'/intern', 'intern', duplicate=0) SConscript(B.root_build_dir+'/intern/SConscript') -BuildDir(B.root_build_dir+'/extern', 'extern', duplicate=0) +VariantDir(B.root_build_dir+'/extern', 'extern', duplicate=0) SConscript(B.root_build_dir+'/extern/SConscript') # now that we have read all SConscripts, we know what @@ -685,6 +700,8 @@ if env['OURPLATFORM']!='darwin': source.remove('kernel.cpp') source.remove('CMakeLists.txt') source.remove('svm') + source.remove('closure') + source.remove('shaders') source.remove('osl') source=['intern/cycles/kernel/'+s for s in source] source.append('intern/cycles/util/util_color.h') @@ -700,6 +717,14 @@ if env['OURPLATFORM']!='darwin': if '__pycache__' in source: source.remove('__pycache__') source=['intern/cycles/kernel/svm/'+s for s in source] scriptinstall.append(env.Install(dir=dir,source=source)) + # closure + dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'kernel', 'closure') + source=os.listdir('intern/cycles/kernel/closure') + if '.svn' in source: source.remove('.svn') + if '_svn' in source: source.remove('_svn') + if '__pycache__' in source: source.remove('__pycache__') + source=['intern/cycles/kernel/closure/'+s for s in source] + scriptinstall.append(env.Install(dir=dir,source=source)) # licenses dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'license') @@ -719,6 +744,22 @@ if env['OURPLATFORM']!='darwin': cubin_file = os.path.join(kernel_build_dir, "kernel_%s.cubin" % arch) scriptinstall.append(env.Install(dir=dir,source=cubin_file)) + # osl shaders + if env['WITH_BF_CYCLES_OSL']: + dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'shader') + + osl_source_dir = Dir('./intern/cycles/kernel/shaders').srcnode().path + oso_build_dir = os.path.join(B.root_build_dir, 'intern/cycles/kernel/shaders') + + headers='node_color.h node_fresnel.h node_texture.h oslutil.h stdosl.h'.split() + source=['intern/cycles/kernel/shaders/'+s for s in headers] + scriptinstall.append(env.Install(dir=dir,source=source)) + + for f in os.listdir(osl_source_dir): + if f.endswith('.osl'): + oso_file = os.path.join(oso_build_dir, f.replace('.osl', '.oso')) + scriptinstall.append(env.Install(dir=dir,source=oso_file)) + if env['WITH_BF_OCIO']: colormanagement = os.path.join('release', 'datafiles', 'colormanagement') @@ -819,10 +860,6 @@ else: if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): dllsources = [] - if not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'): - # For MinGW and linuxcross static linking will be used - dllsources += ['${LCGDIR}/gettext/lib/gnu_gettext.dll'] - dllsources += ['${BF_ZLIB_LIBPATH}/zlib.dll'] # Used when linking to libtiff was dynamic # keep it here until compilation on all platform would be ok @@ -868,9 +905,6 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb.dll') dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb64.dll') - if env['WITH_BF_OIIO'] and env['OURPLATFORM'] != 'win32-mingw': - dllsources.append('${LCGDIR}/openimageio/bin/OpenImageIO.dll') - if env['WITH_BF_OCIO']: if not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'): dllsources.append('${LCGDIR}/opencolorio/bin/OpenColorIO.dll') diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh new file mode 100755 index 00000000000..072e999d827 --- /dev/null +++ b/build_files/build_environment/install_deps.sh @@ -0,0 +1,1875 @@ +#!/bin/bash + +# Parse command line! +ARGS=$( \ +getopt \ +-o s:i:t:h \ +--long source:,install:,threads:,help,with-all,with-osl,all-static,force-all,force-python,\ +force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-ffmpeg,\ +skip-python,skip-boost,skip-ocio,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg \ +-- "$@" \ +) + +DISTRO="" +SRC="$HOME/src/blender-deps" +INST="/opt/lib" +CWD=$PWD + +# Do not install some optional, potentially conflicting libs by default... +WITH_ALL=false + +# Do not yet enable osl, use --with-osl (or --with-all) option to try it. +WITH_OSL=false + +# Try to link everything statically. Use this to produce portable versions of blender. +ALL_STATIC=false + +THREADS=`cat /proc/cpuinfo | grep cores | uniq | sed -e "s/.*: *\(.*\)/\\1/"` +if [ -z "$THREADS" ]; then + THREADS=1 +fi + +COMMON_INFO="\"Source code of dependencies needed to be compiled will be downloaded and extracted into '\$SRC'. +Built libs of dependencies needed to be compiled will be installed into '\$INST'. +Please edit \\\$SRC and/or \\\$INST variables at the beginning of this script, +or use --source/--install options, if you want to use other paths! + +Number of threads for building: \$THREADS (automatically detected, use --threads= to override it). +Full install: \$WITH_ALL (use --with-all option to enable it). +Building OSL: \$WITH_OSL (use --with-osl option to enable it). +All static linking: \$ALL_STATIC (use --all-static option to enable it). + +Use --help to show all available options!\"" + +ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: + -h, --help + Show this message and exit. + + -s , --source= + Use a specific path where to store downloaded libraries sources (defaults to '\$SRC'). + + -i , --install= + Use a specific path where to install built libraries (defaults to '\$INST'). + + -t n, --threads=n + Use a specific number of threads when building the libraries (auto-detected as '\$THREADS'). + + --with-all + By default, a number of optional and not-so-often needed libraries are not installed. + This option will try to install them, at the cost of potential conflicts (depending on + how your package system is set…). + Note this option also implies all other (more specific) --with-foo options below. + + --with-osl + Try to install or build the OpenShadingLanguage libraries (and their dependencies). + Still experimental! + + --all-static + Build libraries as statically as possible, to create static builds of Blender. + + --force-all + Force the rebuild of all built libraries. + + --force-python + Force the rebuild of Python. + + --force-boost + Force the rebuild of Boost. + + --force-ocio + Force the rebuild of OpenColorIO. + + --force-oiio + Force the rebuild of OpenImageIO. + + --force-llvm + Force the rebuild of LLVM. + + --force-osl + Force the rebuild of OpenShadingLanguage. + + --force-ffmpeg + Force the rebuild of FFMpeg. + + Note about the --force-foo options: + * They obviously only have an effect if those libraries are built by this script + (i.e. if there is no available and satisfactory package)! + * If the “force-rebuilt” library is a dependency of others, it will force the rebuild + of those libraries too (e.g. --force-boost will also rebuild oiio and osl...). + * Do not forget --with-osl if you built it and still want it! + + --skip-python + Unconditionally skip Python installation/building. + + --skip-boost + Unconditionally skip Boost installation/building. + + --skip-ocio + Unconditionally skip OpenColorIO installation/building. + + --skip-oiio + Unconditionally skip OpenImageIO installation/building. + + --skip-llvm + Unconditionally skip LLVM installation/building. + + --skip-osl + Unconditionally skip OpenShadingLanguage installation/building. + + --skip-ffmpeg + Unconditionally skip FFMpeg installation/building.\"" + +PYTHON_VERSION="3.3.0" +PYTHON_VERSION_MIN="3.3" +PYTHON_SOURCE="http://python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.bz2" +PYTHON_FORCE_REBUILD=false +PYTHON_SKIP=false + +BOOST_VERSION="1.51.0" +_boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'` +BOOST_SOURCE="http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download" +BOOST_VERSION_MIN="1.49" +BOOST_FORCE_REBUILD=false +BOOST_SKIP=false + +OCIO_VERSION="1.0.7" +OCIO_SOURCE="https://github.com/imageworks/OpenColorIO/tarball/v$OCIO_VERSION" +OCIO_VERSION_MIN="1.0" +OCIO_FORCE_REBUILD=false +OCIO_SKIP=false + +OIIO_VERSION="1.1.1" +OIIO_SOURCE="https://github.com/OpenImageIO/oiio/tarball/Release-$OIIO_VERSION" +OIIO_VERSION_MIN="1.1" +OIIO_FORCE_REBUILD=false +OIIO_SKIP=false + +LLVM_VERSION="3.1" +LLVM_VERSION_MIN="3.0" +LLVM_VERSION_FOUND="" +LLVM_SOURCE="http://llvm.org/releases/$LLVM_VERSION/llvm-$LLVM_VERSION.src.tar.gz" +LLVM_CLANG_SOURCE="http://llvm.org/releases/$LLVM_VERSION/clang-$LLVM_VERSION.src.tar.gz" +LLVM_FORCE_REBUILD=false +LLVM_SKIP=false + +# OSL needs to be compiled for now! +OSL_VERSION="1.2.0" +OSL_SOURCE="https://github.com/mont29/OpenShadingLanguage/archive/blender-fixes.tar.gz" +OSL_FORCE_REBUILD=false +OSL_SKIP=false + +FFMPEG_VERSION="1.0" +FFMPEG_SOURCE="http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" +FFMPEG_VERSION_MIN="0.7.6" +FFMPEG_FORCE_REBUILD=false +FFMPEG_SKIP=false +_ffmpeg_list_sep=";" + +# FFMPEG optional libs. +VORBIS_USE=false +VORBIS_DEV="" +SCHRO_USE=false +SCRHO_DEV="" +THEORA_USE=false +THEORA_DEV="" +XVID_USE=false +XVID_DEV="" +X264_USE=false +X264_DEV="" +X264_VERSION_MIN=0.118 +VPX_USE=false +VPX_VERSION_MIN=0.9.7 +VPX_DEV="" +MP3LAME_USE=false +MP3LAME_DEV="" +OPENJPEG_USE=false +OPENJPEG_DEV="" + +# Switch to english language, else some things (like check_package_DEB()) won't work! +LANG_BACK=$LANG +LANG="" +export LANG + + +_echo() { + if [ "X$1" = "X-n" ]; then + shift; printf "%s" "$@" + else + printf "%s\n" "$@" + fi +} + +ERROR() { + _echo "$@" +} + +INFO() { + _echo "$@" +} + +# Finish parsing the commandline args. +eval set -- "$ARGS" +while true; do + case $1 in + -s|--source) + SRC="$2"; shift; shift; continue + ;; + -i|--install) + INST="$2"; shift; shift; continue + ;; + -t|--threads) + THREADS="$2"; shift; shift; continue + ;; + -h|--help) + INFO "" + INFO "USAGE:" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + INFO "`eval _echo "$ARGUMENTS_INFO"`" + INFO "" + exit 0 + ;; + --with-all) + WITH_ALL=true; shift; continue + ;; + --with-osl) + WITH_OSL=true; shift; continue + ;; + --all-static) + ALL_STATIC=true; shift; continue + ;; + --force-all) + PYTHON_FORCE_REBUILD=true + BOOST_FORCE_REBUILD=true + OCIO_FORCE_REBUILD=true + OIIO_FORCE_REBUILD=true + LLVM_FORCE_REBUILD=true + OSL_FORCE_REBUILD=true + FFMPEG_FORCE_REBUILD=true + shift; continue + ;; + --force-python) + PYTHON_FORCE_REBUILD=true; shift; continue + ;; + --force-boost) + BOOST_FORCE_REBUILD=true; shift; continue + ;; + --force-ocio) + OCIO_FORCE_REBUILD=true; shift; continue + ;; + --force-oiio) + OIIO_FORCE_REBUILD=true; shift; continue + ;; + --force-llvm) + LLVM_FORCE_REBUILD=true; shift; continue + ;; + --force-osl) + OSL_FORCE_REBUILD=true; shift; continue + ;; + --force-ffmpeg) + FFMPEG_FORCE_REBUILD=true; shift; continue + ;; + --skip-python) + PYTHON_SKIP=true; shift; continue + ;; + --skip-boost) + BOOST_SKIP=true; shift; continue + ;; + --skip-ocio) + OCIO_SKIP=true; shift; continue + ;; + --skip-oiio) + OIIO_SKIP=true; shift; continue + ;; + --skip-llvm) + LLVM_SKIP=true; shift; continue + ;; + --skip-osl) + OSL_SKIP=true; shift; continue + ;; + --skip-ffmpeg) + FFMPEG_SKIP=true; shift; continue + ;; + --) + # no more arguments to parse + break + ;; + *) + INFO "" + INFO "Wrong parameter! Usage:" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + exit 1 + ;; + esac +done + +if $WITH_ALL; then + WITH_OSL=true +fi + +# Return 0 if $1 = $2 (i.e. 1.01.0 = 1.1, but 1.1.1 != 1.1), else 1. +# $1 and $2 should be version numbers made of numbers only. +version_eq() { + backIFS=$IFS + IFS='.' + + # Split both version numbers into their numeric elements. + arr1=( $1 ) + arr2=( $2 ) + + ret=1 + + count1=${#arr1[@]} + count2=${#arr2[@]} + if [ $count2 -ge $count1 ]; then + _t=$count1 + count1=$count2 + count2=$_t + arr1=( $2 ) + arr2=( $1 ) + fi + + ret=0 + for (( i=0; $i < $count2; i++ )) + do + if [ $(( 10#${arr1[$i]} )) -ne $(( 10#${arr2[$i]} )) ]; then + ret=1 + break + fi + done + + for (( i=$count2; $i < $count1; i++ )) + do + if [ $(( 10#${arr1[$i]} )) -ne 0 ]; then + ret=1 + break + fi + done + + IFS=$backIFS + return $ret +} + +# Return 0 if $1 >= $2, else 1. +# $1 and $2 should be version numbers made of numbers only. +version_ge() { + version_eq $1 $2 + if [ $? -eq 1 -a $(_echo "$1" "$2" | sort --version-sort | head --lines=1) = "$1" ]; then + return 1 + else + return 0 + fi +} + +# Return 0 if $1 is into $2 (e.g. 3.3.2 is into 3.3, but not 3.3.0 or 3.3.5), else 1. +# $1 and $2 should be version numbers made of numbers only. +# $1 should be at least as long as $2! +version_match() { + backIFS=$IFS + IFS='.' + + # Split both version numbers into their numeric elements. + arr1=( $1 ) + arr2=( $2 ) + + ret=1 + + count1=${#arr1[@]} + count2=${#arr2[@]} + if [ $count1 -ge $count2 ]; then + ret=0 + for (( i=0; $i < $count2; i++ )) + do + if [ $(( 10#${arr1[$i]} )) -ne $(( 10#${arr2[$i]} )) ]; then + ret=1 + break + fi + done + fi + + IFS=$backIFS + return $ret +} + +detect_distro() { + if [ -f /etc/debian_version ]; then + DISTRO="DEB" + elif [ -f /etc/redhat-release ]; then + DISTRO="RPM" + elif [ -f /etc/SuSE-release ]; then + DISTRO="SUSE" + fi +} + +prepare_opt() { + INFO "Ensuring $INST exists and is writable by us" + if [ ! -d $INST ]; then + sudo mkdir -p $INST + fi + + if [ ! -w $INST ]; then + sudo chown $USER $INST + sudo chmod 775 $INST + fi +} + +# Check whether the current package needs to be recompiled, based on a dummy file containing a magic number in its name... +magic_compile_check() { + if [ -f $INST/.$1-magiccheck-$2 ]; then + return 0 + else + return 1 + fi +} + +magic_compile_set() { + rm -f $INST/.$1-magiccheck-* + touch $INST/.$1-magiccheck-$2 +} + +compile_Python() { + # To be changed each time we make edits that would modify the compiled result! + py_magic=0 + + _src=$SRC/Python-$PYTHON_VERSION + _inst=$INST/python-$PYTHON_VERSION + + # Clean install if needed! + magic_compile_check python-$PYTHON_VERSION $py_magic + if [ $? -eq 1 -o $PYTHON_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building Python-$PYTHON_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + mkdir -p $SRC + wget -c $PYTHON_SOURCE -O $_src.tar.bz2 + + INFO "Unpacking Python-$PYTHON_VERSION" + tar -C $SRC -xf $_src.tar.bz2 + fi + + cd $_src + + ./configure --prefix=$_inst --enable-ipv6 \ + --enable-loadable-sqlite-extensions --with-dbmliborder=bdb \ + --with-computed-gotos --with-pymalloc + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/python-3.3 + ln -s python-$PYTHON_VERSION $INST/python-3.3 + else + ERROR "Python--$PYTHON_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set python-$PYTHON_VERSION $py_magic + + cd $CWD + INFO "Done compiling Python-$PYTHON_VERSION!" + else + INFO "Own Python-$PYTHON_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-python option." + fi +} + +compile_Boost() { + # To be changed each time we make edits that would modify the compiled result! + boost_magic=7 + + _src=$SRC/boost-$BOOST_VERSION + _inst=$INST/boost-$BOOST_VERSION + + # Clean install if needed! + magic_compile_check boost-$BOOST_VERSION $boost_magic + if [ $? -eq 1 -o $BOOST_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building Boost-$BOOST_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + INFO "Downloading Boost-$BOOST_VERSION" + mkdir -p $SRC + wget -c $BOOST_SOURCE -O $_src.tar.bz2 + tar -C $SRC --transform "s,(.*/?)boost_1_[^/]+(.*),\1boost-$BOOST_VERSION\2,x" -xf $_src.tar.bz2 + fi + + cd $_src + if [ ! -f $_src/b2 ]; then + ./bootstrap.sh + fi + ./b2 -j$THREADS -a --with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time \ + --prefix=$_inst --disable-icu boost.locale.icu=off install + ./b2 --clean + + if [ -d $_inst ]; then + rm -f $INST/boost + ln -s boost-$BOOST_VERSION $INST/boost + else + ERROR "Boost-$BOOST_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set boost-$BOOST_VERSION $boost_magic + + # Rebuild dependecies as well! + OIIO_FORCE_REBUILD=true + OSL_FORCE_REBUILD=true + + cd $CWD + INFO "Done compiling Boost-$BOOST_VERSION!" + else + INFO "Own Boost-$BOOST_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-boost option." + fi +} + +compile_OCIO() { + # To be changed each time we make edits that would modify the compiled result! + ocio_magic=1 + + _src=$SRC/OpenColorIO-$OCIO_VERSION + _inst=$INST/ocio-$OCIO_VERSION + + # Clean install if needed! + magic_compile_check ocio-$OCIO_VERSION $ocio_magic + if [ $? -eq 1 -o $OCIO_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building OpenColorIO-$OCIO_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + INFO "Downloading OpenColorIO-$OCIO_VERSION" + mkdir -p $SRC + wget -c $OCIO_SOURCE -O $_src.tar.gz + + INFO "Unpacking OpenColorIO-$OCIO_VERSION" + tar -C $SRC --transform "s,(.*/?)imageworks-OpenColorIO[^/]*(.*),\1OpenColorIO-$OCIO_VERSION\2,x" \ + -xf $_src.tar.gz + fi + + cd $_src + # Always refresh the whole build! + if [ -d build ]; then + rm -rf build + fi + mkdir build + cd build + + if file /bin/cp | grep -q '32-bit'; then + cflags="-fPIC -m32 -march=i686" + else + cflags="-fPIC" + fi + + cmake -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_PREFIX_PATH=$_inst \ + -D CMAKE_INSTALL_PREFIX=$_inst \ + -D CMAKE_CXX_FLAGS="$cflags" \ + -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" \ + -D OCIO_BUILD_APPS=OFF \ + -D OCIO_BUILD_PYGLUE=OFF \ + .. + + make -j$THREADS && make install + + # Force linking against static libs + rm -f $_inst/lib/*.so* + + # Additional depencencies + cp ext/dist/lib/libtinyxml.a $_inst/lib + cp ext/dist/lib/libyaml-cpp.a $_inst/lib + + make clean + + if [ -d $_inst ]; then + rm -f $INST/ocio + ln -s ocio-$OCIO_VERSION $INST/ocio + else + ERROR "OpenColorIO-$OCIO_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set ocio-$OCIO_VERSION $ocio_magic + + cd $CWD + INFO "Done compiling OpenColorIO-$OCIO_VERSION!" + else + INFO "Own OpenColorIO-$OCIO_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-ocio option." + fi +} + +compile_OIIO() { + # To be changed each time we make edits that would modify the compiled result! + oiio_magic=6 + + _src=$SRC/OpenImageIO-$OIIO_VERSION + _inst=$INST/oiio-$OIIO_VERSION + + # Clean install if needed! + magic_compile_check oiio-$OIIO_VERSION $oiio_magic + if [ $? -eq 1 -o $OIIO_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building OpenImageIO-$OIIO_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + mkdir -p $SRC + wget -c $OIIO_SOURCE -O "$_src.tar.gz" + + INFO "Unpacking OpenImageIO-$OIIO_VERSION" + tar -C $SRC --transform "s,(.*/?)OpenImageIO-oiio[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" \ + -xf $_src.tar.gz + + cd $_src + + # XXX Ugly patching hack! + cat << EOF | patch -p1 +diff --git a/src/libutil/SHA1.cpp b/src/libutil/SHA1.cpp +index b9e6c8b..c761185 100644 +--- a/src/libutil/SHA1.cpp ++++ b/src/libutil/SHA1.cpp +@@ -8,9 +8,9 @@ + + // If compiling with MFC, you might want to add #include "StdAfx.h" + ++#include "SHA1.h" + #include "hash.h" + #include "dassert.h" +-#include "SHA1.h" + + #ifdef SHA1_UTILITY_FUNCTIONS + #define SHA1_MAX_FILE_BUFFER 8000 +EOF + + cd $CWD + + fi + + cd $_src + # Always refresh the whole build! + if [ -d build ]; then + rm -rf build + fi + mkdir build + cd build + + cmake_d="-D CMAKE_BUILD_TYPE=Release" + cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" + cmake_d="$cmake_d -D BUILDSTATIC=ON" + + # linking statically could give issues on Debian/Ubuntu (and probably other distros + # which doesn't like static linking) when linking shared oiio library due to missing + # text symbols (static libs should be compiled with -fPIC) + # cmake_d="$cmake_d -D LINKSTATIC=ON" + + if [ -d $INST/boost ]; then + cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON" + if $ALL_STATIC; then + cmake_d="$cmake_d -D Boost_USE_STATIC_LIBS=ON" + fi + fi + + # Looks like we do not need ocio in oiio for now... +# if [ -d $INST/ocio ]; then +# cmake_d="$cmake_d -D OCIO_PATH=$INST/ocio" +# fi + + if file /bin/cp | grep -q '32-bit'; then + cflags="-fPIC -m32 -march=i686" + else + cflags="-fPIC" + fi + + cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" ../src + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/oiio + ln -s oiio-$OIIO_VERSION $INST/oiio + else + ERROR "OpenImageIO-$OIIO_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set oiio-$OIIO_VERSION $oiio_magic + + # Rebuild dependecies as well! + OSL_FORCE_REBUILD=true + + cd $CWD + INFO "Done compiling OpenImageIO-$OIIO_VERSION!" + else + INFO "Own OpenImageIO-$OIIO_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-oiio option." + fi +} + +compile_LLVM() { + # To be changed each time we make edits that would modify the compiled result! + llvm_magic=1 + + _src=$SRC/LLVM-$LLVM_VERSION + _inst=$INST/llvm-$LLVM_VERSION + _src_clang=$SRC/CLANG-$LLVM_VERSION + + # Clean install if needed! + magic_compile_check llvm-$LLVM_VERSION $llvm_magic + if [ $? -eq 1 -o $LLVM_FORCE_REBUILD == true ]; then + rm -rf $_inst + rm -rf $_inst_clang + fi + + if [ ! -d $_inst ]; then + INFO "Building LLVM-$LLVM_VERSION (CLANG included!)" + + prepare_opt + + if [ ! -d $_src -o true ]; then + mkdir -p $SRC + wget -c $LLVM_SOURCE -O "$_src.tar.gz" + wget -c $LLVM_CLANG_SOURCE -O "$_src_clang.tar.gz" + + INFO "Unpacking LLVM-$LLVM_VERSION" + tar -C $SRC --transform "s,([^/]*/?)llvm-[^/]*(.*),\1LLVM-$LLVM_VERSION\2,x" \ + -xf $_src.tar.gz + INFO "Unpacking CLANG-$LLVM_VERSION to $_src/tools/clang" + tar -C $_src/tools \ + --transform "s,([^/]*/?)clang-[^/]*(.*),\1clang\2,x" \ + -xf $_src_clang.tar.gz + + cd $_src + + # XXX Ugly patching hack! + cat << EOF | patch -p1 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -13,7 +13,7 @@ + set(LLVM_VERSION_MAJOR 3) + set(LLVM_VERSION_MINOR 1) + +-set(PACKAGE_VERSION "\${LLVM_VERSION_MAJOR}.\${LLVM_VERSION_MINOR}svn") ++set(PACKAGE_VERSION "\${LLVM_VERSION_MAJOR}.\${LLVM_VERSION_MINOR}") + + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +EOF + + cd $CWD + + fi + + cd $_src + + # Always refresh the whole build! + if [ -d build ]; then + rm -rf build + fi + mkdir build + cd build + + cmake_d="-D CMAKE_BUILD_TYPE=Release" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" + cmake_d="$cmake_d -D LLVM_ENABLE_FFI=ON" + + if [ -d $_FFI_INCLUDE_DIR ]; then + cmake_d="$cmake_d -D FFI_INCLUDE_DIR=$_FFI_INCLUDE_DIR" + fi + + cmake $cmake_d .. + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/llvm + ln -s llvm-$LLVM_VERSION $INST/llvm + else + ERROR "LLVM-$LLVM_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set llvm-$LLVM_VERSION $llvm_magic + + # Rebuild dependecies as well! + OSL_FORCE_REBUILD=true + + cd $CWD + INFO "Done compiling LLVM-$LLVM_VERSION (CLANG included)!" + else + INFO "Own LLVM-$LLVM_VERSION (CLANG included) is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-llvm option." + fi +} + +compile_OSL() { + # To be changed each time we make edits that would modify the compiled result! + osl_magic=7 + + _src=$SRC/OpenShadingLanguage-$OSL_VERSION + _inst=$INST/osl-$OSL_VERSION + + # Clean install if needed! + magic_compile_check osl-$OSL_VERSION $osl_magic + if [ $? -eq 1 -o $OSL_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building OpenShadingLanguage-$OSL_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + mkdir -p $SRC + + # XXX Using git on my own repo for now, looks like archives are not updated immediately... :/ +# wget -c $OSL_SOURCE -O "$_src.tar.gz" + +# INFO "Unpacking OpenShadingLanguage-$OSL_VERSION" +# tar -C $SRC --transform "s,(.*/?)OpenShadingLanguage-[^/]*(.*),\1OpenShadingLanguage-$OSL_VERSION\2,x" \ +# -xf $_src.tar.gz + git clone https://github.com/mont29/OpenShadingLanguage.git $_src + cd $_src + git checkout blender-fixes + cd $CWD + fi + + cd $_src + # XXX For now, always update from latest repo... + git pull origin + + # Always refresh the whole build! + if [ -d build ]; then + rm -rf build + fi + mkdir build + cd build + + cmake_d="-D CMAKE_BUILD_TYPE=Release" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" + cmake_d="$cmake_d -D BUILDSTATIC=ON" + cmake_d="$cmake_d -D BUILD_TESTING=OFF" + + if [ -d $INST/boost ]; then + cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON" + if $ALL_STATIC; then + cmake_d="$cmake_d -D Boost_USE_STATIC_LIBS=ON" + fi + fi + + if [ -d $INST/oiio ]; then + cmake_d="$cmake_d -D OPENIMAGEIOHOME=$INST/oiio" + fi + + if [ ! -z $LLVM_VERSION_FOUND ]; then + cmake_d="$cmake_d -D LLVM_VERSION=$LLVM_VERSION_FOUND" + if [ -d $INST/llvm ]; then + cmake_d="$cmake_d -D LLVM_DIRECTORY=$INST/llvm" + cmake_d="$cmake_d -D LLVM_STATIC=ON" + fi + fi + + cmake $cmake_d ../src + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/osl + ln -s osl-$OSL_VERSION $INST/osl + else + ERROR "OpenShadingLanguage-$OSL_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set osl-$OSL_VERSION $osl_magic + + cd $CWD + INFO "Done compiling OpenShadingLanguage-$OSL_VERSION!" + else + INFO "Own OpenShadingLanguage-$OSL_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-osl option." + fi +} + +compile_FFmpeg() { + # To be changed each time we make edits that would modify the compiled result! + ffmpeg_magic=3 + + _src=$SRC/ffmpeg-$FFMPEG_VERSION + _inst=$INST/ffmpeg-$FFMPEG_VERSION + + # Clean install if needed! + magic_compile_check ffmpeg-$FFMPEG_VERSION $ffmpeg_magic + if [ $? -eq 1 -o $FFMPEG_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building ffmpeg-$FFMPEG_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + INFO "Downloading ffmpeg-$FFMPEG_VERSION" + mkdir -p $SRC + wget -c $FFMPEG_SOURCE -O "$_src.tar.bz2" + + INFO "Unpacking ffmpeg-$FFMPEG_VERSION" + tar -C $SRC -xf $_src.tar.bz2 + fi + + cd $_src + + extra="" + + if $VORBIS_USE; then + extra="$extra --enable-libvorbis" + fi + + if $THEORA_USE; then + extra="$extra --enable-libtheora" + fi + + # XXX At least under Debian, static schro gives problem at blender linking time... :/ + if $SCHRO_USE && ! $ALL_STATIC; then + extra="$extra --enable-libschroedinger" + fi + + if $XVID_USE; then + extra="$extra --enable-libxvid" + fi + + if $X264_USE; then + extra="$extra --enable-libx264" + fi + + if $VPX_USE; then + extra="$extra --enable-libvpx" + fi + + if $MP3LAME_USE; then + extra="$extra --enable-libmp3lame" + fi + + if $OPENJPEG_USE; then + extra="$extra --enable-libopenjpeg" + fi + + ./configure --cc="gcc -Wl,--as-needed" \ + --extra-ldflags="-pthread -static-libgcc" \ + --prefix=$_inst --enable-static \ + --disable-ffplay --disable-ffserver --disable-doc \ + --enable-gray \ + --enable-avfilter --disable-vdpau \ + --disable-bzlib --disable-libgsm --disable-libspeex \ + --enable-pthreads --enable-zlib --enable-stripping --enable-runtime-cpudetect \ + --disable-vaapi --disable-libfaac --disable-nonfree --enable-gpl \ + --disable-postproc --disable-x11grab --disable-librtmp --disable-libopencore-amrnb \ + --disable-libopencore-amrwb --disable-libdc1394 --disable-version3 --disable-outdev=sdl \ + --disable-outdev=alsa --disable-indev=sdl --disable-indev=alsa --disable-indev=jack \ + --disable-indev=lavfi $extra + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/ffmpeg + ln -s ffmpeg-$FFMPEG_VERSION $INST/ffmpeg + else + ERROR "FFmpeg-$FFMPEG_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set ffmpeg-$FFMPEG_VERSION $ffmpeg_magic + + cd $CWD + INFO "Done compiling ffmpeg-$FFMPEG_VERSION!" + else + INFO "Own ffmpeg-$FFMPEG_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-ffmpeg option." + fi +} + +get_package_version_DEB() { + dpkg-query -W -f '${Version}' $1 | sed -r 's/.*:\s*([0-9]+:)(([0-9]+\.?)+).*/\2/' +} + +check_package_DEB() { + r=`apt-cache policy $1 | grep -c 'Candidate:'` + + if [ $r -ge 1 ]; then + return 0 + else + return 1 + fi +} + +check_package_version_match_DEB() { + v=`apt-cache policy $1 | grep 'Candidate:' | sed -r 's/.*:\s*([0-9]+:)(([0-9]+\.?)+).*/\2/'` + + if [ -z "$v" ]; then + return 1 + fi + + version_match $v $2 + return $? +} + +check_package_version_ge_DEB() { + v=`apt-cache policy $1 | grep 'Candidate:' | sed -r 's/.*:\s*([0-9]+:)?(([0-9]+\.?)+).*/\2/'` + + if [ -z "$v" ]; then + return 1 + fi + + version_ge $v $2 + return $? +} + +install_packages_DEB() { + sudo apt-get install -y $@ + if [ $? -ge 1 ]; then + ERROR "apt-get failed to install requested packages, exiting." + exit 1 + fi +} + +install_DEB() { + INFO "" + INFO "Installing dependencies for DEB-based distribution" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + + if [ ! -z "`cat /etc/debian_version | grep ^6`" ]; then + if [ -z "`cat /etc/apt/sources.list | grep backports.debian.org`" ]; then + INFO "Looks like you're using Debian Squeeze which does have broken CMake" + INFO "It is highly recommended to install cmake from backports, otherwise" + INFO "compilation of some libraries could fail" + INFO "" + INFO "You could install newer CMake from debian-backports repository" + INFO "Add this this line to your /etc/apt/sources.lixt:" + INFO "" + INFO "deb http://backports.debian.org/debian-backports squeeze-backports main" + INFO "" + INFO "and then run:" + INFO "" + INFO "sudo apt-get update && sudo apt-get install cmake=2.8.7-4~bpo60+1 sudo apt-get install cmake=2.8.7-4~bpo60+1" + INFO "" + INFO "(you could also add this reporisotry using GUI like synaptic)" + INFO "" + INFO "Hit Enter to continue running the script, or hit Ctrl-C to abort the script" + + read + INFO "" + fi + fi + + sudo apt-get update +# XXX Why in hell? Let's let this stuff to the user's responsability!!! +# sudo apt-get -y upgrade + + # These libs should always be available in debian/ubuntu official repository... + OPENJPEG_DEV="libopenjpeg-dev" + SCHRO_DEV="libschroedinger-dev" + VORBIS_DEV="libvorbis-dev" + THEORA_DEV="libtheora-dev" + + _packages="gawk cmake scons build-essential libjpeg-dev libpng-dev libtiff-dev \ + libfreetype6-dev libx11-dev libxi-dev wget libsqlite3-dev libbz2-dev \ + libncurses5-dev libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV \ + libopenexr-dev libopenal-dev libglew-dev yasm $THEORA_DEV \ + $VORBIS_DEV libsdl1.2-dev libfftw3-dev python-dev patch bzip2" + OPENJPEG_USE=true + VORBIS_USE=true + THEORA_USE=true + + if $WITH_ALL; then + _packages="$_packages $SCHRO_DEV libjack0 libjack-dev" + SCHRO_USE=true + fi + + INFO "" + install_packages_DEB $_packages + + INFO "" + X264_DEV="libx264-dev" + check_package_version_ge_DEB $X264_DEV $X264_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB $X264_DEV + X264_USE=true + fi + + if $WITH_ALL; then + INFO "" + # Grmpf, debian is libxvidcore-dev and ubuntu libxvidcore4-dev! + XVID_DEV="libxvidcore-dev" + check_package_DEB $XVID_DEV + if [ $? -eq 0 ]; then + install_packages_DEB $XVID_DEV + XVID_USE=true + else + XVID_DEV="libxvidcore4-dev" + check_package_DEB $XVID_DEV + if [ $? -eq 0 ]; then + install_packages_DEB $XVID_DEV + XVID_USE=true + fi + fi + + INFO "" + MP3LAME_DEV="libmp3lame-dev" + check_package_DEB $MP3LAME_DEV + if [ $? -eq 0 ]; then + install_packages_DEB $MP3LAME_DEV + MP3LAME_USE=true + fi + + INFO "" + VPX_DEV="libvpx-dev" + check_package_version_ge_DEB $VPX_DEV $VPX_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB $VPX_DEV + VPX_USE=true + fi + + INFO "" + check_package_DEB libspnav-dev + if [ $? -eq 0 ]; then + install_packages_DEB libspnav-dev + fi + fi + + INFO "" + if $PYTHON_SKIP; then + INFO "WARNING! Skipping Python installation, as requested..." + else + check_package_DEB python3.3-dev + if [ $? -eq 0 ]; then + install_packages_DEB python3.3-dev + else + compile_Python + fi + fi + + INFO "" + if $BOOST_SKIP; then + INFO "WARNING! Skipping Boost installation, as requested..." + else + check_package_version_ge_DEB libboost-dev $BOOST_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB libboost-dev + + boost_version=$(echo `get_package_version_DEB libboost-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/') + + check_package_DEB libboost-locale$boost_version-dev + if [ $? -eq 0 ]; then + install_packages_DEB libboost-locale$boost_version-dev libboost-filesystem$boost_version-dev \ + libboost-regex$boost_version-dev libboost-system$boost_version-dev \ + libboost-thread$boost_version-dev + else + compile_Boost + fi + else + compile_Boost + fi + fi + + INFO "" + if $OCIO_SKIP; then + INFO "WARNING! Skipping OpenColorIO installation, as requested..." + else + check_package_version_ge_DEB libopencolorio-dev $OCIO_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB libopencolorio-dev + else + compile_OCIO + fi + fi + + INFO "" + if $OIIO_SKIP; then + INFO "WARNING! Skipping OpenImageIO installation, as requested..." + else + check_package_version_ge_DEB libopenimageio-dev $OIIO_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB libopenimageio-dev + else + compile_OIIO + fi + fi + + if $WITH_OSL; then + have_llvm=false + + if $LLVM_SKIP; then + INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..." + else + INFO "" + check_package_DEB llvm-$LLVM_VERSION-dev + if [ $? -eq 0 ]; then + install_packages_DEB llvm-$LLVM_VERSION-dev + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + else + check_package_DEB llvm-$LLVM_VERSION_MIN-dev + if [ $? -eq 0 ]; then + install_packages_DEB llvm-$LLVM_VERSION_MIN-dev + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION_MIN + else + install_packages_DEB libffi-dev + INFO "" + compile_LLVM + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + fi + fi + fi + + if $OSL_SKIP; then + INFO "" + INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..." + else + if $have_llvm; then + INFO "" + install_packages_DEB clang flex bison libtbb-dev git + # No package currently! + INFO "" + compile_OSL + fi + fi + fi + + + INFO "" + if $FFMPEG_SKIP; then + INFO "WARNING! Skipping FFMpeg installation, as requested..." + else +# XXX Debian features libav packages as ffmpeg, those are not really compatible with blender code currently :/ +# So for now, always build our own ffmpeg. +# check_package_DEB ffmpeg +# if [ $? -eq 0 ]; then +# install_packages_DEB ffmpeg +# ffmpeg_version=`get_package_version_DEB ffmpeg` +# INFO "ffmpeg version: $ffmpeg_version" +# if [ ! -z "$ffmpeg_version" ]; then +# if dpkg --compare-versions $ffmpeg_version gt 0.7.2; then +# install_packages_DEB libavfilter-dev libavcodec-dev libavdevice-dev libavformat-dev libavutil-dev libswscale-dev +# else +# compile_FFmpeg +# fi +# fi +# fi + compile_FFmpeg + fi +} + +get_package_version_RPM() { + yum info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/' +} + +check_package_RPM() { + r=`yum info $1 | grep -c 'Summary'` + + if [ $r -ge 1 ]; then + return 0 + else + return 1 + fi +} + +check_package_version_match_RPM() { + v=`get_package_version_RPM $1` + + if [ -z "$v" ]; then + return 1 + fi + + version_match $v $2 + return $? +} + +check_package_version_ge_RPM() { + v=`get_package_version_RPM $1` + + if [ -z "$v" ]; then + return 1 + fi + + version_ge $v $2 + return $? +} + +install_packages_RPM() { + sudo yum install -y $@ + if [ $? -ge 1 ]; then + ERROR "yum failed to install requested packages, exiting." + exit 1 + fi +} + +install_RPM() { + INFO "" + INFO "Installing dependencies for RPM-based distribution" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + + sudo yum -y update + + # These libs should always be available in debian/ubuntu official repository... + OPENJPEG_DEV="openjpeg-devel" + SCHRO_DEV="schroedinger-devel" + VORBIS_DEV="libvorbis-devel" + THEORA_DEV="libtheora-devel" + + _packages="gawk gcc gcc-c++ cmake scons libpng-devel libtiff-devel freetype-devel \ + libX11-devel libXi-devel wget libsqlite3x-devel ncurses-devel \ + readline-devel $OPENJPEG_DEV openexr-devel openal-soft-devel \ + glew-devel yasm $THEORA_DEV $VORBIS_DEV SDL-devel fftw-devel \ + lame-libs libjpeg-devel patch python-devel" + OPENJPEG_USE=true + VORBIS_USE=true + THEORA_USE=true + + if $WITH_ALL; then + _packages="$_packages $SCHRO_DEV jack-audio-connection-kit-devel libspnav-devel" + SCHRO_USE=true + fi + + INFO "" + install_packages_RPM $_packages + + INFO "" + X264_DEV="x264-devel" + check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM $X264_DEV + X264_USE=true + fi + + if $WITH_ALL; then + INFO "" + XVID_DEV="xvidcore-devel" + check_package_RPM $XVID_DEV + if [ $? -eq 0 ]; then + install_packages_RPM $XVID_DEV + XVID_USE=true + fi + + INFO "" + VPX_DEV="libvpx-devel" + check_package_version_ge_RPM $VPX_DEV $VPX_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM $VPX_DEV + VPX_USE=true + fi + + INFO "" + MP3LAME_DEV="lame-devel" + check_package_RPM $MP3LAME_DEV + if [ $? -eq 0 ]; then + install_packages_RPM $MP3LAME_DEV + MP3LAME_USE=true + fi + fi + + INFO "" + if $PYTHON_SKIP; then + INFO "WARNING! Skipping Python installation, as requested..." + else + check_package_version_match_RPM python3-devel $PYTHON_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM python3-devel + else + compile_Python + fi + fi + + INFO "" + if $BOOST_SKIP; then + INFO "WARNING! Skipping Boost installation, as requested..." + else + check_package_version_ge_RPM boost-devel $BOOST_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM boost-devel + else + compile_Boost + fi + fi + + INFO "" + if $OCIO_SKIP; then + INFO "WARNING! Skipping OpenColorIO installation, as requested..." + else + check_package_version_ge_RPM OpenColorIO-devel $OCIO_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM OpenColorIO-devel + else + compile_OCIO + fi + fi + + INFO "" + if $OIIO_SKIP; then + INFO "WARNING! Skipping OpenImageIO installation, as requested..." + else + check_package_version_ge_RPM OpenImageIO-devel $OIIO_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM OpenImageIO-devel + else + compile_OIIO + fi + fi + + if $WITH_OSL; then + have_llvm=false + + INFO "" + if $LLVM_SKIP; then + INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..." + else + check_package_RPM llvm-$LLVM_VERSION-devel + if [ $? -eq 0 ]; then + install_packages_RPM llvm-$LLVM_VERSION-devel + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + else +# check_package_RPM llvm-$LLVM_VERSION_MIN-devel +# if [ $? -eq 0 ]; then +# install_packages_RPM llvm-$LLVM_VERSION_MIN-devel +# have_llvm=true +# LLVM_VERSION_FOUND=$LLVM_VERSION_MIN +# else +# check_package_version_ge_RPM llvm-devel $LLVM_VERSION_MIN +# if [ $? -eq 0 ]; then +# install_packages_RPM llvm-devel +# have_llvm=true +# LLVM_VERSION_FOUND=`get_package_version_RPM llvm-devel` +# fi +# fi + install_packages_RPM libffi-devel + # XXX Stupid fedora puts ffi header into a darn stupid dir! + _FFI_INCLUDE_DIR=`rpm -ql libffi-devel | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'` + INFO "" + compile_LLVM + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + fi + fi + + if $OSL_SKIP; then + INFO "" + INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..." + else + if $have_llvm; then + INFO "" + install_packages_RPM flex bison clang tbb-devel git + # No package currently! + INFO "" + compile_OSL + fi + fi + fi + + INFO "" + if $FFMPEG_SKIP; then + INFO "WARNING! Skipping FFMpeg installation, as requested..." + else + # Always for now, not sure which packages should be installed + compile_FFmpeg + fi +} + +get_package_version_SUSE() { + zypper info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/' +} + +check_package_SUSE() { + r=`zypper info $1 | grep -c 'Summary'` + + if [ $r -ge 1 ]; then + return 0 + else + return 1 + fi +} + +check_package_version_match_SUSE() { + v=`get_package_version_SUSE $1` + + if [ -z "$v" ]; then + return 1 + fi + + version_match $v $2 + return $? +} + +check_package_version_ge_SUSE() { + v=`get_package_version_SUSE $1` + + if [ -z "$v" ]; then + return 1 + fi + + version_ge $v $2 + return $? +} + +install_packages_SUSE() { + sudo zypper --non-interactive install --auto-agree-with-licenses $@ + if [ $? -ge 1 ]; then + ERROR "zypper failed to install requested packages, exiting." + exit 1 + fi +} + + +install_SUSE() { + INFO "" + INFO "Installing dependencies for SuSE-based distribution" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + + sudo zypper --non-interactive update --auto-agree-with-licenses + + # These libs should always be available in debian/ubuntu official repository... + OPENJPEG_DEV="openjpeg-devel" + SCHRO_DEV="schroedinger-devel" + VORBIS_DEV="libvorbis-devel" + THEORA_DEV="libtheora-devel" + + _packages="gawk gcc gcc-c++ cmake scons libpng12-devel libtiff-devel freetype-devel \ + libX11-devel libXi-devel wget sqlite3-devel ncurses-devel \ + readline-devel $OPENJPEG_DEV libopenexr-devel openal-soft-devel \ + glew-devel yasm $THEORA_DEV $VORBIS_DEV libSDL-devel fftw3-devel \ + libjpeg62-devel patch python-devel" + OPENJPEG_USE=true + VORBIS_USE=true + THEORA_USE=true + + if $WITH_ALL; then + _packages="$_packages $SCHRO_DEV libjack-devel libspnav-devel" + SCHRO_USE=true + fi + + INFO "" + install_packages_SUSE $_packages + + OPENJPEG_USE=true + SCHRO_USE=true + VORBIS_USE=true + THEORA_USE=true + + INFO "" + X264_DEV="x264-devel" + check_package_version_ge_SUSE $X264_DEV $X264_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_SUSE $X264_DEV + X264_USE=true + fi + + if $WITH_ALL; then + INFO "" + XVID_DEV="xvidcore-devel" + check_package_SUSE $XVID_DEV + if [ $? -eq 0 ]; then + install_packages_SUSE $XVID_DEV + XVID_USE=true + fi + + INFO "" + VPX_DEV="libvpx-devel" + check_package_version_ge_SUSE $VPX_DEV $VPX_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_SUSE $VPX_DEV + VPX_USE=true + fi + + INFO "" + # No mp3 in suse, it seems. + MP3LAME_DEV="lame-devel" + check_package_SUSE $MP3LAME_DEV + if [ $? -eq 0 ]; then + install_packages_SUSE $MP3LAME_DEV + MP3LAME_USE=true + fi + fi + + INFO "" + if $PYTHON_SKIP; then + INFO "WARNING! Skipping Python installation, as requested..." + else + check_package_version_match_SUSE python3-devel 3.3. + if [ $? -eq 0 ]; then + install_packages_SUSE python3-devel + else + compile_Python + fi + fi + + INFO "" + if $BOOST_SKIP; then + INFO "WARNING! Skipping Boost installation, as requested..." + else + # No boost_locale currently available, so let's build own boost. + compile_Boost + fi + + INFO "" + if $OCIO_SKIP; then + INFO "WARNING! Skipping OpenColorIO installation, as requested..." + else + # No ocio currently available, so let's build own boost. + compile_OCIO + fi + + INFO "" + if $OIIO_SKIP; then + INFO "WARNING! Skipping OpenImageIO installation, as requested..." + else + # No oiio currently available, so let's build own boost. + compile_OIIO + fi + + if $WITH_OSL; then + have_llvm=false + + INFO "" + if $LLVM_SKIP; then + INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..." + else + # Suse llvm package *_$SUCKS$_* (tm) !!! +# check_package_version_ge_SUSE llvm-devel $LLVM_VERSION_MIN +# if [ $? -eq 0 ]; then +# install_packages_SUSE llvm-devel +# have_llvm=true +# LLVM_VERSION_FOUND=`get_package_version_SUSE llvm-devel` +# fi + + install_packages_SUSE libffi47-devel + INFO "" + compile_LLVM + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + fi + + if $OSL_SKIP; then + INFO "" + INFO "WARNING! Skipping OpenShaderLanguage installation, as requested..." + else + if $have_llvm; then + INFO "" + # XXX No tbb lib! + install_packages_SUSE flex bison git + # No package currently! + INFO "" + compile_OSL + fi + fi + fi + + INFO "" + if $FFMPEG_SKIP; then + INFO "WARNING! Skipping FFMpeg installation, as requested..." + else + # No ffmpeg currently available, so let's build own boost. + compile_FFmpeg + fi +} + +print_info_ffmpeglink_DEB() { + if $ALL_STATIC; then + dpkg -L $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }' + else + dpkg -L $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }' + fi +} + +print_info_ffmpeglink_RPM() { + if $ALL_STATIC; then + rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }' + else + rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }' + fi +} + +print_info_ffmpeglink_SUSE() { + if $ALL_STATIC; then + rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }' + else + rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }' + fi +} + +print_info_ffmpeglink() { + # This func must only print a ';'-separated list of libs... + if [ -z "$DISTRO" ]; then + ERROR "Failed to detect distribution type" + exit 1 + fi + + # Create list of packages from which to get libs names... + _packages="" + + if $THEORA_USE; then + _packages="$_packages $THEORA_DEV" + fi + + if $VORBIS_USE; then + _packages="$_packages $VORBIS_DEV" + fi + + if $XVID_USE; then + _packages="$_packages $XVID_DEV" + fi + + if $VPX_USE; then + _packages="$_packages $VPX_DEV" + fi + + if $MP3LAME_USE; then + _packages="$_packages $MP3LAME_DEV" + fi + + if $X264_USE; then + _packages="$_packages $X264_DEV" + fi + + if $OPENJPEG_USE; then + _packages="$_packages $OPENJPEG_DEV" + fi + + # XXX At least under Debian, static schro gives problem at blender linking time... :/ + if $SCHRO_USE && ! $ALL_STATIC; then + _packages="$_packages $SCHRO_DEV" + fi + + if [ "$DISTRO" = "DEB" ]; then + print_info_ffmpeglink_DEB + elif [ "$DISTRO" = "RPM" ]; then + print_info_ffmpeglink_RPM + elif [ "$DISTRO" = "SUSE" ]; then + print_info_ffmpeglink_SUSE + # XXX TODO! + else INFO "" + fi +} + +print_info() { + INFO "" + INFO "If you're using CMake add this to your configuration flags:" + + if $ALL_STATIC; then + INFO " -D WITH_STATIC_LIBS=ON" + fi + + if [ -d $INST/boost ]; then + INFO " -D BOOST_ROOT=$INST/boost" + INFO " -D Boost_NO_SYSTEM_PATHS=ON" + elif $ALL_STATIC; then + INFO " -D Boost_USE_ICU=ON" + fi + + if [ -d $INST/osl -a $WITH_OSL == true ]; then + INFO " -D CYCLES_OSL=$INST/osl" + INFO " -D WITH_CYCLES_OSL=ON" + INFO " -D LLVM_VERSION=$LLVM_VERSION_FOUND" + if [ -d $INST/llvm ]; then + INFO " -D LLVM_DIRECTORY=$INST/llvm" + INFO " -D LLVM_STATIC=ON" + fi + fi + + if [ -d $INST/ffmpeg ]; then + INFO " -D WITH_CODEC_FFMPEG=ON" + INFO " -D FFMPEG=$INST/ffmpeg" + INFO " -D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;rt;`print_info_ffmpeglink`'" + fi + + INFO "" + INFO "If you're using SCons add this to your user-config:" + + if [ -d $INST/python-3.3 ]; then + INFO "BF_PYTHON = '$INST/python-3.3'" + INFO "BF_PYTHON_ABI_FLAGS = 'm'" + fi + + if [ -d $INST/ocio ]; then + INFO "BF_OCIO = '$INST/ocio'" + fi + + if [ -d $INST/oiio ]; then + INFO "BF_OIIO = '$INST/oiio'" + fi + + if [ -d $INST/boost ]; then + INFO "BF_BOOST = '$INST/boost'" + fi + + if [ -d $INST/ffmpeg ]; then + INFO "BF_FFMPEG = '$INST/ffmpeg'" + _ffmpeg_list_sep=" " + INFO "BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice `print_info_ffmpeglink`'" + fi + + INFO "" + INFO "" + INFO "WARNING: If this script had to build boost into $INST, and you are dynamically linking " + INFO " blender against it, you will have to run those commands as root user:" + INFO "" + INFO " echo \"$INST/boost/lib\" > /etc/ld.so.conf.d/boost.conf" + INFO " ldconfig" + INFO "" +} + +# Detect distributive type used on this machine +detect_distro + +if [ -z "$DISTRO" ]; then + ERROR "Failed to detect distribution type" + exit 1 +elif [ "$DISTRO" = "DEB" ]; then + install_DEB +elif [ "$DISTRO" = "RPM" ]; then + install_RPM +elif [ "$DISTRO" = "SUSE" ]; then + install_SUSE +fi + +print_info + +# Switch back to user language. +LANG=LANG_BACK +export LANG diff --git a/build_files/build_environment/prepare_release_env.sh b/build_files/build_environment/prepare_release_env.sh index b16ce784be9..9889feadcd2 100755 --- a/build_files/build_environment/prepare_release_env.sh +++ b/build_files/build_environment/prepare_release_env.sh @@ -88,6 +88,9 @@ OIIO_V="1.0.9" OCIO_V="1.0.7" MESA_V="8.0.5" +OPENSSL_V="0.9.8o" +OPENSSL_FV="0.9.8o-4squeeze13" + CUDA_V="4.2.9" CUDA_DISTR="ubuntu10.04" CUDA_32="cudatoolkit_${CUDA_V}_linux_32_${CUDA_DISTR}.run" @@ -611,6 +614,15 @@ INSTALL_SOURCES() { -P "$SOURCES_PATH/backport/gcc-4.7" fi + if [ ! -d "$SOURCES_PATH/backport/openssl" ]; then + INFO "Downloading openssl" + mkdir -p "$SOURCES_PATH/backport/openssl" + wget -c $DEBIAN_MIRROR/pool/main/o/openssl/openssl_$OPENSSL_FV.debian.tar.gz \ + $DEBIAN_MIRROR/pool/main/o/openssl/openssl_$OPENSSL_FV.dsc \ + $DEBIAN_MIRROR/pool/main/o/openssl/openssl_$OPENSSL_V.orig.tar.gz \ + -P "$SOURCES_PATH/backport/openssl" + fi + # JeMalloc J="$SOURCES_PATH/packages/jemalloc-$JEMALLOC_V" if [ ! -d "$J" ]; then @@ -731,7 +743,6 @@ EOF chmod +x "$P/0config.sh" fi - # OpenImageIO O="$SOURCES_PATH/packages/OpenImageIO-$OIIO_V" if [ ! -d "$O" ]; then @@ -1075,6 +1086,64 @@ DO_BACKPORT() { INFO "Cleaning gcc-4.7" $RUN sh -c "cd '$G' && fakeroot debian/rules clean" fi + + # Backport OpenSSL + if [ ! -f $CHROOT_PATH/usr/lib/libssl_pic.a ]; then + INFO "Backporting OpenSSL" + O="$P/openssl/openssl-$OPENSSL_V" + + pkg="libssl-dev_0.9.8o-4squeeze13_amd64.deb libssl0.9.8_0.9.8o-4squeeze13_amd64.deb openssl_0.9.8o-4squeeze13_amd64.deb" + + if [ ! -d "$CHROOT_PATH/$O" ]; then + INFO "Unpacking OpenSSL" + $RUN dpkg-source -x "$P/openssl/openssl_$OPENSSL_FV.dsc" "$O" + fi + + if [ "$CHROOT_ARCH" = "i386" ]; then + pkg=`echo "$pkg" | sed -r 's/amd64/i386/g'` + fi + + ok=true + for x in `echo "$pkg"`; do + if [ ! -f "$CHROOT_PATH/$P/openssl/$x" ]; then + ok=false + break; + fi + done + + if ! $ok; then + INFO "Compiling OpenSSL" + sed -ie 's/#\s*mv debian\/tmp\/usr\/lib\/libcrypto.a debian\/tmp\/usr\/lib\/libcrypto_pic.a/ mv debian\/tmp\/usr\/lib\/libcrypto.a debian\/tmp\/usr\/lib\/libcrypto_pic.a/' "$CHROOT_PATH/$O/debian/rules" + sed -ie 's/#\s*mv debian\/tmp\/usr\/lib\/libssl.a debian\/tmp\/usr\/lib\/libssl_pic.a/ mv debian\/tmp\/usr\/lib\/libssl.a debian\/tmp\/usr\/lib\/libssl_pic.a/' "$CHROOT_PATH/$O/debian/rules" + cat << EOF > $CHROOT_PATH/$O/debian/libssl-dev.files +usr/lib/libssl.so +usr/lib/libcrypto.so +usr/lib/libssl.a +usr/lib/libcrypto.a +usr/lib/libssl_pic.a +usr/lib/libcrypto_pic.a +usr/lib/pkgconfig +usr/include +usr/share/man/man3 +EOF + $RUN sh -c "cd '$O' && dpkg-buildpackage -rfakeroot -j$THREADS" + fi + + inst="" + for x in `echo "$pkg"`; do + inst="$inst $P/openssl/$x" + done + + INFO "Installing OpenSSL" + $RUN dpkg -i $inst + + echo "openssl hold" | $RUN dpkg --set-selections + echo "libssl-dev hold" | $RUN dpkg --set-selections + echo "libssl0.9.8 hold" | $RUN dpkg --set-selections + + INFO "Cleaning OpenSSL" + $RUN sh -c "cd '$O' && fakeroot debian/rules clean" + fi } DO_COMPILE() { @@ -1161,6 +1230,8 @@ _sha256 sha256module.c _sha512 sha512module.c EOF + sed -ie "s/libraries = \['ssl', 'crypto'\]/libraries = ['ssl_pic', 'crypto_pic', 'z']/" "$P/Python-$PYTHON_V/setup.py" + $RUN sh -c "cd '$P/Python-$PYTHON_V' && ./0config.sh && make clean && make -j$THREADS && make install && make clean" rm -f "$L/python-$PYTHIN_V_SHORT" @@ -1356,6 +1427,7 @@ EOF fi INFO "Installing packages from repository" + $RUN apt-get install -y mc gcc g++ cmake python dpkg-dev build-essential autoconf bison \ flex gettext texinfo dejagnu quilt file lsb-release zlib1g-dev fakeroot debhelper \ g++-multilib libtool autoconf2.64 automake gawk lzma patchutils gperf sharutils \ @@ -1366,7 +1438,7 @@ EOF libsqlite3-dev liblzma-dev libncurses5-dev xutils-dev libxext-dev python-libxml2 \ libglu1-mesa-dev libfftw3-dev libfreetype6-dev libsdl1.2-dev libopenal-dev libjack-dev \ libxi-dev portaudio19-dev po4a subversion scons libpcre3-dev libexpat1-dev sudo \ - expect + expect bc if [ $CHROOT_ARCH = "amd64" ]; then $RUN apt-get install -y libc6-dev-i386 lib32gcc1 diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py index 23ab87a6ba3..e665657d91e 100644 --- a/build_files/buildbot/config/user-config-glibc211-i686.py +++ b/build_files/buildbot/config/user-config-glibc211-i686.py @@ -110,8 +110,7 @@ BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a' # Cycles WITH_BF_CYCLES = True WITH_BF_CYCLES_CUDA_BINARIES = True -#BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] -BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30'] +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] WITH_BF_OIIO = True WITH_BF_STATICOIIO = True @@ -120,6 +119,24 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = False +BF_OSL = '/opt/lib/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +BF_OSL_LIB = 'oslcomp oslexec oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +WITH_BF_STATICLLVM = False +BF_LLVM = '/opt/lib/llvm-3.1' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + # Color management WITH_BF_OCIO = True WITH_BF_STATICOCIO = True @@ -133,7 +150,8 @@ WITH_BF_STATICBOOST = True BF_BOOST = '/opt/lib/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ - '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \ + ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # Ocean Simulation @@ -141,5 +159,6 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-lrt'] +BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map'] diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py index 84899cc3848..420d9ed4db9 100644 --- a/build_files/buildbot/config/user-config-glibc211-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py @@ -119,6 +119,24 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = False +BF_OSL = '/opt/lib/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +BF_OSL_LIB = 'oslcomp oslexec oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +WITH_BF_STATICLLVM = False +BF_LLVM = '/opt/lib/llvm-3.1' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + # Color management WITH_BF_OCIO = True WITH_BF_STATICOCIO = True @@ -132,7 +150,8 @@ WITH_BF_STATICBOOST = True BF_BOOST = '/opt/lib/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ - '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \ + ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # Ocean Simulation @@ -140,5 +159,6 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-lrt'] +BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map'] diff --git a/build_files/buildbot/config/user-config-glibc27-i686.py b/build_files/buildbot/config/user-config-glibc27-i686.py index c1e72662f89..b36196fd835 100644 --- a/build_files/buildbot/config/user-config-glibc27-i686.py +++ b/build_files/buildbot/config/user-config-glibc27-i686.py @@ -97,8 +97,7 @@ WITH_BF_JACK = True # Cycles WITH_BF_CYCLES = True WITH_BF_CYCLES_CUDA_BINARIES = True -#BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] -BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30'] +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] WITH_BF_OIIO = True WITH_BF_STATICOIIO = True @@ -107,6 +106,24 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = False +BF_OSL = '/opt/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +BF_OSL_LIB = 'oslcomp oslexec oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +WITH_BF_STATICLLVM = False +BF_LLVM = '/opt/llvm-3.1' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + # Color management WITH_BF_OCIO = True WITH_BF_STATICOCIO = True @@ -119,7 +136,7 @@ WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # Ocean Simulation @@ -127,5 +144,6 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-DNDEBUG', '-O2'] # C & C++ PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib32'] +BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map'] diff --git a/build_files/buildbot/config/user-config-glibc27-x86_64.py b/build_files/buildbot/config/user-config-glibc27-x86_64.py index 4380b404ac3..7359e155586 100644 --- a/build_files/buildbot/config/user-config-glibc27-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc27-x86_64.py @@ -106,6 +106,24 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = False +BF_OSL = '/opt/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +BF_OSL_LIB = 'oslcomp oslexec oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +WITH_BF_STATICLLVM = False +BF_LLVM = '/opt/llvm-3.1' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + # Color management WITH_BF_OCIO = True WITH_BF_STATICOCIO = True @@ -118,7 +136,7 @@ WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # Ocean Simulation @@ -126,5 +144,6 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib64'] +BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map'] diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py index 1b387445390..96f201235c4 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py @@ -98,7 +98,8 @@ WITH_BF_STATICBOOST = True BF_BOOST = '/opt/lib/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ - '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \ + ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # JACK @@ -116,5 +117,5 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-lrt'] diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py index 83540150c33..75979d0bcfe 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py +++ b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py @@ -98,7 +98,8 @@ WITH_BF_STATICBOOST = True BF_BOOST = '/opt/lib/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ - '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \ + ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # JACK @@ -116,5 +117,5 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-lrt'] diff --git a/build_files/buildbot/config/user-config-player-glibc27-i686.py b/build_files/buildbot/config/user-config-player-glibc27-i686.py index e200e0fccf4..82b105c4527 100644 --- a/build_files/buildbot/config/user-config-player-glibc27-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc27-i686.py @@ -94,7 +94,7 @@ WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # JACK @@ -110,5 +110,5 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2'] # C & C++ PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib32'] diff --git a/build_files/buildbot/config/user-config-player-glibc27-x86_64.py b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py index 2ee177960cd..1e6aa4af802 100644 --- a/build_files/buildbot/config/user-config-player-glibc27-x86_64.py +++ b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py @@ -94,7 +94,7 @@ WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # JACK @@ -110,5 +110,5 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib64'] diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg index e9deade6e99..90f0c805f58 100644 --- a/build_files/buildbot/master.cfg +++ b/build_files/buildbot/master.cfg @@ -77,17 +77,18 @@ def svn_step(branch=''): def lib_svn_step(dir): return SVN(name='lib svn', baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir, mode='update', defaultBranch='trunk', workdir='lib/' + dir) -def rsync_step(file_from, file_to): - return ShellCommand(name='rsync', command=['rsync', '-v', '-P', file_from, 'brecht@builder.blender.org:/data/buildbot-master/' + file_to], haltOnFailure=True, description=['rsync']) +def rsync_step(id, branch, rsync_script): + return ShellCommand(name='rsync', command=['python', rsync_script, id, branch], description='uploading', descriptionDone='uploaded', workdir='install') # generic builder def generic_builder(id, libdir='', branch='', rsync=False): - filename = 'buildbot_upload_' + id + '.zip' + filename = 'uploaded/buildbot_upload_' + id + '.zip' compile_script = '../blender/build_files/buildbot/slave_compile.py' test_script = '../blender/build_files/buildbot/slave_test.py' pack_script = '../blender/build_files/buildbot/slave_pack.py' + rsync_script = '../blender/build_files/buildbot/slave_rsync.py' unpack_script = 'master_unpack.py' f = BuildFactory() @@ -95,11 +96,11 @@ def generic_builder(id, libdir='', branch='', rsync=False): if libdir != '': f.addStep(lib_svn_step(libdir)) - f.addStep(Compile(command=['python', compile_script, id])) + f.addStep(Compile(command=['python', compile_script, id], timeout=3600)) f.addStep(Test(command=['python', test_script, id])) f.addStep(ShellCommand(name='package', command=['python', pack_script, id, branch], description='packaging', descriptionDone='packaged')) if rsync: - f.addStep(rsync_step('../install/buildbot_upload.zip', filename)) + f.addStep(rsync_step(id, branch, rsync_script)) elif id.find('cmake') != -1: f.addStep(FileUpload(name='upload', slavesrc='buildbot_upload.zip', masterdest=filename, maxsize=100 * 1024 * 1024)) else: @@ -109,7 +110,8 @@ def generic_builder(id, libdir='', branch='', rsync=False): # builders -add_builder(c, 'mac_x86_64_scons', '', generic_builder) +add_builder(c, 'mac_x86_64_10_6_scons', 'darwin-9.x.universal', generic_builder, '', True) +add_builder(c, 'mac_x86_64_10_5_scons', '', generic_builder, '', True) #add_builder(c, 'salad_mac_x86_64_scons', 'darwin-9.x.universal', generic_builder, 'soc-2011-salad') add_builder(c, 'mac_i386_scons', 'darwin-9.x.universal', generic_builder) add_builder(c, 'mac_ppc_scons', 'darwin-9.x.universal', generic_builder) diff --git a/build_files/buildbot/slave_rsync.py b/build_files/buildbot/slave_rsync.py new file mode 100644 index 00000000000..aea1b65e333 --- /dev/null +++ b/build_files/buildbot/slave_rsync.py @@ -0,0 +1,45 @@ +# ##### 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 ##### + +# + +# Runs on buildbot slave, rsync zip directly to buildbot server rather +# than using upload which is much slower + +import os +import sys + +# get builder name +if len(sys.argv) < 2: + sys.stderr.write("Not enough arguments, expecting builder name\n") + sys.exit(1) + +builder = sys.argv[1] + +# rsync, this assumes ssh keys are setup so no password is needed +local_zip = "buildbot_upload.zip" +remote_folder = "builder.blender.org:/data/buildbot-master/uploaded/" +remote_zip = remote_folder + "buildbot_upload_" + builder + ".zip" +command = "rsync -avz %s %s" % (local_zip, remote_zip) + +print(command) + +ret = os.system(command) +sys.exit(ret) + + diff --git a/build_files/cmake/Modules/FindIcuLinux.cmake b/build_files/cmake/Modules/FindIcuLinux.cmake new file mode 100644 index 00000000000..e0e5873a4eb --- /dev/null +++ b/build_files/cmake/Modules/FindIcuLinux.cmake @@ -0,0 +1,146 @@ +# - Find static icu libraries +# Find the native static icu libraries (needed for static boost_locale :/ ). +# This module defines +# ICU_LIBRARIES, libraries to link against to use icu. +# ICU_ROOT_DIR, The base directory to search for icu. +# This can also be an environment variable. +# ICU_FOUND, If false, do not try to use icu. +# +# also defined, but not for general use are +# ICU_LIBRARY_xxx, where to find the icu libraries. + +#============================================================================= +# Copyright 2012 Blender Foundation. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +# If ICU_ROOT_DIR was defined in the environment, use it. +IF(NOT ICU_ROOT_DIR AND NOT $ENV{ICU_ROOT_DIR} STREQUAL "") + SET(ICU_ROOT_DIR $ENV{ICU_ROOT_DIR}) +ENDIF() + +if(Boost_USE_STATIC_LIBS) + set(_icu_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) +endif() + +SET(_icu_SEARCH_DIRS + ${ICU_ROOT_DIR} + /usr/local + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave +) + +# We don't need includes, only libs to link against... +#FIND_PATH(ICU_INCLUDE_DIR +# NAMES +# utf.h +# HINTS +# ${_icu_SEARCH_DIRS} +# PATH_SUFFIXES +# include/unicode +#) + +FIND_LIBRARY(ICU_LIBRARY_DATA + NAMES + icudata + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_I18N + NAMES + icui18n + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_IO + NAMES + icuio + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_LE + NAMES + icule + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_LX + NAMES + iculx + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_TU + NAMES + icutu + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_UC + NAMES + icuuc + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +# Restore the original find library ordering +if(Boost_USE_STATIC_LIBS) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_icu_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) +endif() + +# handle the QUIETLY and REQUIRED arguments and set ICU_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Icu DEFAULT_MSG + ICU_LIBRARY_DATA + ICU_LIBRARY_I18N + ICU_LIBRARY_IO + ICU_LIBRARY_LE + ICU_LIBRARY_LX + ICU_LIBRARY_TU + ICU_LIBRARY_UC +) + +IF(ICU_FOUND) + SET(ICU_LIBRARIES ${ICU_LIBRARY_DATA} ${ICU_LIBRARY_I18N} ${ICU_LIBRARY_IO} ${ICU_LIBRARY_LE} ${ICU_LIBRARY_LX} ${ICU_LIBRARY_TU} ${ICU_LIBRARY_UC}) + SET(ICU_INCLUDE_DIRS ${ICU_INCLUDE_DIR}) +ENDIF(ICU_FOUND) + +MARK_AS_ADVANCED( + ICU_INCLUDE_DIR + ICU_LIBRARY_DATA + ICU_LIBRARY_I18N + ICU_LIBRARY_IO + ICU_LIBRARY_LE + ICU_LIBRARY_LX + ICU_LIBRARY_TU + ICU_LIBRARY_UC +) diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake index 79bc0127674..e152f0f81d9 100644 --- a/build_files/cmake/Modules/FindOpenColorIO.cmake +++ b/build_files/cmake/Modules/FindOpenColorIO.cmake @@ -39,6 +39,7 @@ SET(_opencolorio_SEARCH_DIRS /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave + /opt/lib/ocio ) FIND_PATH(OPENCOLORIO_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindOpenImageIO.cmake b/build_files/cmake/Modules/FindOpenImageIO.cmake index 7512b93e09e..9b8c8b075b1 100644 --- a/build_files/cmake/Modules/FindOpenImageIO.cmake +++ b/build_files/cmake/Modules/FindOpenImageIO.cmake @@ -33,6 +33,7 @@ SET(_openimageio_SEARCH_DIRS /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave + /opt/lib/oiio ) FIND_PATH(OPENIMAGEIO_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake index 34394864861..1dffd54fed1 100644 --- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake +++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake @@ -9,6 +9,7 @@ # This module defines # PYTHON_VERSION # PYTHON_INCLUDE_DIRS +# PYTHON_INCLUDE_CONFIG_DIRS # PYTHON_LIBRARIES # PYTHON_LIBPATH, Used for installation # PYTHON_LINKFLAGS @@ -46,17 +47,25 @@ MARK_AS_ADVANCED(PYTHON_LINKFLAGS) # if the user passes these defines as args, we dont want to overwrite SET(_IS_INC_DEF OFF) +SET(_IS_INC_CONF_DEF OFF) SET(_IS_LIB_DEF OFF) +SET(_IS_LIB_PATH_DEF OFF) IF(DEFINED PYTHON_INCLUDE_DIR) SET(_IS_INC_DEF ON) ENDIF() +IF(DEFINED PYTHON_INCLUDE_CONFIG_DIR) + SET(_IS_INC_CONF_DEF ON) +ENDIF() IF(DEFINED PYTHON_LIBRARY) SET(_IS_LIB_DEF ON) ENDIF() +IF(DEFINED PYTHON_LIBPATH) + SET(_IS_LIB_PATH_DEF ON) +ENDIF() # only search for the dirs if we havn't already -IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) +IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_LIB_PATH_DEF)) SET(_python_ABI_FLAGS "m;mu;u; " # release @@ -69,6 +78,7 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) ${PYTHON_ROOT_DIR} "$ENV{HOME}/py${_PYTHON_VERSION_NO_DOTS}" "/opt/py${_PYTHON_VERSION_NO_DOTS}" + "/opt/lib/python-${PYTHON_VERSION}" ) FOREACH(_CURRENT_ABI_FLAGS ${_python_ABI_FLAGS}) @@ -85,9 +95,27 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) ${_python_SEARCH_DIRS} PATH_SUFFIXES include/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} + include/${CMAKE_LIBRARY_ARCHITECTURE}/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} ) ENDIF() + IF(NOT DEFINED PYTHON_INCLUDE_CONFIG_DIR) + FIND_PATH(PYTHON_INCLUDE_CONFIG_DIR + NAMES + pyconfig.h + HINTS + ${_python_SEARCH_DIRS} + PATH_SUFFIXES + include/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} + include/${CMAKE_LIBRARY_ARCHITECTURE}/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} + ) + IF((NOT PYTHON_INCLUDE_CONFIG_DIR) AND PYTHON_INCLUDE_DIR) + # Fallback... + UNSET(PYTHON_INCLUDE_CONFIG_DIR CACHE) + SET(PYTHON_INCLUDE_CONFIG_DIR ${PYTHON_INCLUDE_DIR} CACHE PATH "") + ENDIF() + ENDIF() + IF(NOT DEFINED PYTHON_LIBRARY) FIND_LIBRARY(PYTHON_LIBRARY NAMES @@ -99,16 +127,38 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) ) ENDIF() - IF(PYTHON_LIBRARY AND PYTHON_INCLUDE_DIR) + IF(NOT DEFINED PYTHON_LIBPATH) + FIND_PATH(PYTHON_LIBPATH + NAMES + "python${PYTHON_VERSION}/abc.py" # This is a bit hackish! :/ + HINTS + ${_python_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + IF((NOT PYTHON_LIBPATH) AND PYTHON_LIBRARY) + # Fallback... + UNSET(PYTHON_LIBPATH CACHE) + GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) + ENDIF() + ENDIF() + + IF(PYTHON_LIBRARY AND PYTHON_LIBPATH AND PYTHON_INCLUDE_DIR AND PYTHON_INCLUDE_CONFIG_DIR) break() ELSE() # ensure we dont find values from 2 different ABI versions IF(NOT _IS_INC_DEF) UNSET(PYTHON_INCLUDE_DIR CACHE) ENDIF() + IF(NOT _IS_INC_CONF_DEF) + UNSET(PYTHON_INCLUDE_CONFIG_DIR CACHE) + ENDIF() IF(NOT _IS_LIB_DEF) UNSET(PYTHON_LIBRARY CACHE) ENDIF() + IF(NOT _IS_LIB_PATH_DEF) + UNSET(PYTHON_LIBPATH CACHE) + ENDIF() ENDIF() ENDFOREACH() @@ -120,22 +170,24 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) ENDIF() UNSET(_IS_INC_DEF) +UNSET(_IS_INC_CONF_DEF) UNSET(_IS_LIB_DEF) +UNSET(_IS_LIB_PATH_DEF) # handle the QUIETLY and REQUIRED arguments and SET PYTHONLIBSUNIX_FOUND to TRUE IF # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix DEFAULT_MSG - PYTHON_LIBRARY PYTHON_INCLUDE_DIR) - + PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR) IF(PYTHONLIBSUNIX_FOUND) # Assign cache items - SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR}) + SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR} ${PYTHON_INCLUDE_CONFIG_DIR}) SET(PYTHON_LIBRARIES ${PYTHON_LIBRARY}) # we need this for installation - GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) + # XXX No more valid with debian-like py3.3 packages... +# GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) # not used # SET(PYTHON_BINARY ${PYTHON_EXECUTABLE} CACHE STRING "") @@ -143,5 +195,6 @@ ENDIF() MARK_AS_ADVANCED( PYTHON_INCLUDE_DIR + PYTHON_INCLUDE_CONFIG_DIR PYTHON_LIBRARY ) diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py index 072bbb12fb3..b13b0ddb424 100755 --- a/build_files/cmake/cmake_consistency_check.py +++ b/build_files/cmake/cmake_consistency_check.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -222,8 +222,8 @@ def cmake_get_src(f): ''' # reset - sources_h[:] = [] - sources_c[:] = [] + del sources_h[:] + del sources_c[:] filen.close() diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py index 8f3835c3401..2f36cad4d24 100755 --- a/build_files/cmake/cmake_netbeans_project.py +++ b/build_files/cmake/cmake_netbeans_project.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py index 83ea761e2d1..86201da23de 100755 --- a/build_files/cmake/cmake_qtcreator_project.py +++ b/build_files/cmake/cmake_qtcreator_project.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/build_files/cmake/cmake_static_check_clang_array.py b/build_files/cmake/cmake_static_check_clang_array.py index 941407170ff..7f45cc6aadc 100644 --- a/build_files/cmake/cmake_static_check_clang_array.py +++ b/build_files/cmake/cmake_static_check_clang_array.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -27,6 +27,8 @@ import subprocess import sys import os +USE_QUIET = (os.environ.get("QUIET", None) is not None) + CHECKER_IGNORE_PREFIX = [ "extern", "intern/moto", @@ -59,11 +61,12 @@ def main(): process_functions = [] def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.flush() - sys.stdout.write("%s " % percent_str) + sys.stdout.flush() + sys.stdout.write("%s " % percent_str) return subprocess.Popen(cmd) diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py index c458e8ede11..d79145f8586 100644 --- a/build_files/cmake/cmake_static_check_cppcheck.py +++ b/build_files/cmake/cmake_static_check_cppcheck.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -27,6 +27,8 @@ import subprocess import sys import os +USE_QUIET = (os.environ.get("QUIET", None) is not None) + CHECKER_IGNORE_PREFIX = [ "extern", "intern/moto", @@ -44,6 +46,9 @@ CHECKER_ARGS = [ # "--enable=all", # if you want sixty hundred pedantic suggestions ] +if USE_QUIET: + CHECKER_ARGS.append("--quiet") + def main(): source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX) @@ -62,11 +67,12 @@ def main(): process_functions = [] def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.flush() - sys.stdout.write("%s " % percent_str) + sys.stdout.flush() + sys.stdout.write("%s " % percent_str) return subprocess.Popen(cmd) @@ -75,6 +81,8 @@ def main(): project_source_info.queue_processes(process_functions) + print("Finished!") + if __name__ == "__main__": main() diff --git a/build_files/cmake/cmake_static_check_smatch.py b/build_files/cmake/cmake_static_check_smatch.py index 5681d2ae5ed..7535f1cc55a 100644 --- a/build_files/cmake/cmake_static_check_smatch.py +++ b/build_files/cmake/cmake_static_check_smatch.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -37,7 +37,9 @@ CHECKER_ARGS = [ import project_source_info import subprocess import sys +import os +USE_QUIET = (os.environ.get("QUIET", None) is not None) def main(): source_info = project_source_info.build_info(use_cxx=False, ignore_prefix_list=CHECKER_IGNORE_PREFIX) @@ -55,11 +57,12 @@ def main(): check_commands.append((c, cmd)) def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.flush() - sys.stdout.write("%s %s\n" % (percent_str, c)) + sys.stdout.flush() + sys.stdout.write("%s %s\n" % (percent_str, c)) return subprocess.Popen(cmd) diff --git a/build_files/cmake/cmake_static_check_sparse.py b/build_files/cmake/cmake_static_check_sparse.py index 4f4eb838dd5..06bef1a1327 100644 --- a/build_files/cmake/cmake_static_check_sparse.py +++ b/build_files/cmake/cmake_static_check_sparse.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -35,6 +35,9 @@ CHECKER_ARGS = [ import project_source_info import subprocess import sys +import os + +USE_QUIET = (os.environ.get("QUIET", None) is not None) def main(): @@ -53,11 +56,12 @@ def main(): check_commands.append((c, cmd)) def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.flush() - sys.stdout.write("%s %s\n" % (percent_str, c)) + sys.stdout.flush() + sys.stdout.write("%s %s\n" % (percent_str, c)) return subprocess.Popen(cmd) diff --git a/build_files/cmake/cmake_static_check_splint.py b/build_files/cmake/cmake_static_check_splint.py index 7be28c01af8..5b1207543f5 100644 --- a/build_files/cmake/cmake_static_check_splint.py +++ b/build_files/cmake/cmake_static_check_splint.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -68,6 +68,9 @@ CHECKER_ARGS = [ import project_source_info import subprocess import sys +import os + +USE_QUIET = (os.environ.get("QUIET", None) is not None) def main(): @@ -85,11 +88,12 @@ def main(): check_commands.append((c, cmd)) def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.write("%s %s\n" % (percent_str, c)) - sys.stdout.flush() + sys.stdout.write("%s %s\n" % (percent_str, c)) + sys.stdout.flush() return subprocess.Popen(cmd) diff --git a/build_files/cmake/example_scripts/make_quicky.py b/build_files/cmake/example_scripts/make_quicky.py index 9b853fc01d4..76d4df32f86 100755 --- a/build_files/cmake/example_scripts/make_quicky.py +++ b/build_files/cmake/example_scripts/make_quicky.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ##### BEGIN GPL LICENSE BLOCK ##### # diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 3c321cc60be..efa258aa9dc 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -196,10 +196,6 @@ macro(SETUP_LIBDIRS) if(WITH_PYTHON) # AND NOT WITH_PYTHON_MODULE # WIN32 needs link_directories(${PYTHON_LIBPATH}) endif() - if(WITH_INTERNATIONAL) - link_directories(${ICONV_LIBPATH}) - link_directories(${GETTEXT_LIBPATH}) - endif() if(WITH_SDL) link_directories(${SDL_LIBPATH}) endif() @@ -287,14 +283,6 @@ macro(setup_liblinks target_link_libraries(${target} ${GLEW_LIBRARY}) endif() - if(WITH_INTERNATIONAL) - target_link_libraries(${target} ${GETTEXT_LIBRARIES}) - - if(WIN32 AND NOT UNIX) - target_link_libraries(${target} ${ICONV_LIBRARIES}) - endif() - endif() - if(WITH_OPENAL) target_link_libraries(${target} ${OPENAL_LIBRARY}) endif() @@ -324,6 +312,9 @@ macro(setup_liblinks endif() if(WITH_BOOST) target_link_libraries(${target} ${BOOST_LIBRARIES}) + if(Boost_USE_STATIC_LIBS AND Boost_USE_ICU) + target_link_libraries(${target} ${ICU_LIBRARIES}) + endif() endif() target_link_libraries(${target} ${JPEG_LIBRARIES}) if(WITH_IMAGE_OPENEXR) @@ -712,7 +703,11 @@ macro(delayed_install destination) foreach(f ${files}) - set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${base}/${f}) + if(IS_ABSOLUTE ${f}) + set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${f}) + else() + set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${base}/${f}) + endif() set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_DESTINATIONS ${destination}) endforeach() endmacro() diff --git a/build_files/cmake/project_info.py b/build_files/cmake/project_info.py index b154d578144..34f378a58dd 100755 --- a/build_files/cmake/project_info.py +++ b/build_files/cmake/project_info.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index afab4131de8..252a1b1b37e 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -118,16 +118,16 @@ BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' BF_FFMPEG_LIB = 'avcodec avdevice avformat avutil mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg bz2' #bz2 is a standard osx dynlib -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_OSX_STATICPYTHON = True if WITH_OSX_STATICPYTHON: - # python 3.2 uses precompiled libraries in bf svn /lib by default + # python 3.3 uses precompiled libraries in bf svn /lib by default BF_PYTHON = LIBDIR + '/python' - BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' + BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}m' # BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' - BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' + BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}m' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}' # BF_PYTHON_LINKFLAGS = ['-u', '_PyMac_Error', '-framework', 'System'] else: @@ -223,11 +223,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True @@ -281,23 +276,42 @@ BF_PCRE_LIBPATH = '${BF_PCRE}/lib' # Cycles WITH_BF_CYCLES = True +#OSL + +WITH_BF_CYCLES_OSL = True +BF_OSL = LIBDIR + '/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +#BF_OSL_LIB = 'oslcomp oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +BF_LLVM = LIBDIR + '/llvm' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + WITH_BF_OIIO = True BF_OIIO = LIBDIR + '/openimageio' -BF_OIIO_INC = BF_OIIO + '/include' +BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB = 'OpenImageIO' -BF_OIIO_LIBPATH = BF_OIIO + '/lib' +BF_OIIO_LIBPATH = '${BF_OIIO}/lib' WITH_BF_OCIO = True BF_OCIO = LIBDIR + '/opencolorio' -BF_OCIO_INC = BF_OCIO + '/include' +BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB = 'OpenColorIO tinyxml yaml-cpp' -BF_OCIO_LIBPATH = BF_OCIO + '/lib' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' -BF_BOOST_INC = BF_BOOST + '/include' -BF_BOOST_LIB = 'boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt' -BF_BOOST_LIBPATH = BF_BOOST + '/lib' +BF_BOOST_INC = '${BF_BOOST}/include' +BF_BOOST_LIB = 'boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt boost_wave-mt' +BF_BOOST_LIB_INTERNATIONAL = 'boost_locale-mt' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' WITH_BF_CYCLES_CUDA_BINARIES = False BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc' diff --git a/build_files/scons/config/freebsd7-config.py b/build_files/scons/config/freebsd7-config.py index 412b08d895b..02c9093567a 100644 --- a/build_files/scons/config/freebsd7-config.py +++ b/build_files/scons/config/freebsd7-config.py @@ -7,7 +7,7 @@ LIBDIR = "${LCGDIR}" BF_PYTHON_ABI_FLAGS = '' BF_PYTHON = '/usr/local' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/freebsd8-config.py b/build_files/scons/config/freebsd8-config.py index ece86f799c3..5d3308c50d4 100644 --- a/build_files/scons/config/freebsd8-config.py +++ b/build_files/scons/config/freebsd8-config.py @@ -7,7 +7,7 @@ LIBDIR = "${LCGDIR}" BF_PYTHON_ABI_FLAGS = '' BF_PYTHON = '/usr/local' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/freebsd9-config.py b/build_files/scons/config/freebsd9-config.py index a31c6da90f0..98c2c8fa500 100644 --- a/build_files/scons/config/freebsd9-config.py +++ b/build_files/scons/config/freebsd9-config.py @@ -7,7 +7,7 @@ LIBDIR = "${LCGDIR}" BF_PYTHON_ABI_FLAGS = '' BF_PYTHON = '/usr/local' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py index 45f6602e4dd..038a9bc421d 100644 --- a/build_files/scons/config/linux-config.py +++ b/build_files/scons/config/linux-config.py @@ -89,13 +89,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' -#WITH_BF_GETTEXT_STATIC = True -#BF_GETTEXT_LIB_STATIC = '${BF_GETTEXT}/lib/libgettextlib.a' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True @@ -211,9 +204,9 @@ BF_OIIO = LIBDIR + '/oiio' if not os.path.exists(LCGDIR + '/oiio'): WITH_BF_OIIO = False BF_OIIO = '/usr' -BF_OIIO_INC = BF_OIIO + '/include' +BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB = 'OpenImageIO' -BF_OIIO_LIBPATH = BF_OIIO + '/lib' +BF_OIIO_LIBPATH = '${BF_OIIO}/lib' WITH_BF_OCIO = True WITH_BF_STATICOCIO = False @@ -221,9 +214,9 @@ BF_OCIO = LIBDIR + '/ocio' if not os.path.exists(LCGDIR + '/ocio'): WITH_BF_OCIO = False BF_OCIO = '/usr' -BF_OCIO_INC = BF_OCIO + '/include' +BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB = 'OpenColorIO yaml-cpp tinyxml' -BF_OCIO_LIBPATH = BF_OCIO + '/lib' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' WITH_BF_BOOST = True WITH_BF_STATICBOOST = False @@ -231,9 +224,10 @@ BF_BOOST = LIBDIR + '/boost' if not os.path.exists(LCGDIR + '/boost'): WITH_BF_BOOST = False BF_BOOST = '/usr' -BF_BOOST_INC = BF_BOOST + '/include' +BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'boost_date_time boost_filesystem boost_regex boost_system boost_thread' -BF_BOOST_LIBPATH = BF_BOOST + '/lib' +BF_BOOST_LIB_INTERNATIONAL = 'boost_locale' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' WITH_BF_CYCLES = WITH_BF_OIIO and WITH_BF_BOOST @@ -304,3 +298,7 @@ BF_INSTALLDIR='../install/linux' #Link against pthread PLATFORM_LINKFLAGS = ['-pthread'] +#Fix for LLVM conflict with Mesa llvmpipe +if WITH_BF_LLVM: + PLATFORM_LINKFLAGS += ['-Wl,--version-script=source/creator/blender.map'] + diff --git a/build_files/scons/config/linuxcross-config.py b/build_files/scons/config/linuxcross-config.py index 6866241793b..54faf59b2a4 100644 --- a/build_files/scons/config/linuxcross-config.py +++ b/build_files/scons/config/linuxcross-config.py @@ -2,7 +2,7 @@ LCGDIR = '#../lib/windows' LIBDIR = '${LCGDIR}' BF_PYTHON = LIBDIR + '/python' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}mw' @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gcc/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = False WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py index 0a72d87bb2a..391421609d2 100644 --- a/build_files/scons/config/win32-mingw-config.py +++ b/build_files/scons/config/win32-mingw-config.py @@ -2,12 +2,12 @@ LCGDIR = '#../lib/mingw32' LIBDIR = "${LCGDIR}" BF_PYTHON = LIBDIR + '/python' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}mw' -BF_PYTHON_DLL = 'python32' +BF_PYTHON_DLL = 'python33' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}.a' @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_OPENJPEG = True BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' @@ -155,21 +150,22 @@ WITH_BF_CYCLES = True WITH_BF_OIIO = True BF_OIIO = LIBDIR + '/openimageio' -BF_OIIO_INC = BF_OIIO + '/include' +BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB = 'OpenImageIO' -BF_OIIO_LIBPATH = BF_OIIO + '/lib' +BF_OIIO_LIBPATH = '${BF_OIIO}/lib' WITH_BF_OCIO = True BF_OCIO = LIBDIR + '/opencolorio' -BF_OCIO_INC = BF_OCIO + '/include' +BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB = 'OpenColorIO' -BF_OCIO_LIBPATH = BF_OCIO + '/lib' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' -BF_BOOST_INC = BF_BOOST + '/include' +BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_49 boost_filesystem-mgw46-mt-s-1_49 boost_regex-mgw46-mt-s-1_49 boost_system-mgw46-mt-s-1_49 boost_thread-mgw46-mt-s-1_49' -BF_BOOST_LIBPATH = BF_BOOST + '/lib' +BF_BOOST_LIB_INTERNATIONAL = 'boost_locale-mgw46-mt-s-1_49' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #Ray trace optimization WITH_BF_RAYOPTIMIZATION = True diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py index b77ff8e70e0..21488e75f7e 100644 --- a/build_files/scons/config/win32-vc-config.py +++ b/build_files/scons/config/win32-vc-config.py @@ -9,10 +9,10 @@ BF_FFMPEG_LIB = 'avformat-53.lib avcodec-53.lib avdevice-53.lib avutil-51.lib sw 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.2' +BF_PYTHON_VERSION = '3.3' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' -BF_PYTHON_LIB = 'python32' +BF_PYTHON_LIB = 'python33' BF_PYTHON_DLL = '${BF_PYTHON_LIB}' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' @@ -54,7 +54,7 @@ BF_PTHREADS_LIBPATH = '${BF_PTHREADS}/lib' WITH_BF_OPENEXR = True WITH_BF_STATICOPENEXR = False BF_OPENEXR = LIBDIR + '/openexr' -BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath ' +BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR ' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' @@ -87,11 +87,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gnu_gettext' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True @@ -155,22 +150,40 @@ WITH_BF_OPENMP = True #Cycles WITH_BF_CYCLES = True +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = True +BF_OSL = '${LIBDIR}/osl' +BF_OSL_INC = '${BF_OSL}/include' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_LIB_STATIC = '${BF_OSL_LIBPATH}/oslcomp.lib ${BF_OSL_LIBPATH}/oslexec.lib ${BF_OSL_LIBPATH}/oslquery.lib ' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +BF_LLVM = LIBDIR + '/llvm' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + WITH_BF_OIIO = True BF_OIIO = '${LIBDIR}/openimageio' BF_OIIO_INC = '${BF_OIIO}/include' -BF_OIIO_LIB = 'OpenImageIO' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/OpenImageIO.lib' +WITH_BF_STATICOIIO = True WITH_BF_OCIO = True BF_OCIO = '${LIBDIR}/opencolorio' BF_OCIO_INC = '${BF_OCIO}/include' -BF_OCIO_LIB = 'OpenColorIO' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/OpenColorIO.lib' +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' +BF_BOOST_LIB_INTERNATIONAL = 'libboost_locale-vc90-mt-s-1_49' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #CUDA @@ -208,7 +221,7 @@ C_WARN = [] CC_WARN = [] CXX_WARN = [] -LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid'] +LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi'] PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/STACK:2097152','/INCREMENTAL:NO', '/LARGEADDRESSAWARE', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib'] diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py index 838822bbbcb..d00e7a3ffa7 100644 --- a/build_files/scons/config/win64-mingw-config.py +++ b/build_files/scons/config/win64-mingw-config.py @@ -2,12 +2,12 @@ LCGDIR = '#../lib/mingw64' LIBDIR = "${LCGDIR}" BF_PYTHON = LIBDIR + '/python' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}mw' -BF_PYTHON_DLL = 'python32' +BF_PYTHON_DLL = 'python33' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = True @@ -80,11 +80,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_OPENJPEG = True BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' @@ -118,7 +113,7 @@ BF_FREETYPE_LIBPATH = '${BF_FREETYPE}/lib' WITH_BF_QUICKTIME = False -WITH_BF_ICONV = True +WITH_BF_ICONV = False BF_ICONV = LIBDIR + "/iconv" BF_ICONV_INC = '${BF_ICONV}/include' BF_ICONV_LIB = 'iconv' @@ -167,9 +162,10 @@ BF_OCIO_LIBPATH = '${BF_OCIO}/lib' WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' -BF_BOOST_INC = BF_BOOST + '/include' +BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'boost_date_time-mgw47-mt-s-1_49 boost_date_time-mgw47-mt-sd-1_49 boost_filesystem-mgw47-mt-s-1_49 boost_filesystem-mgw47-mt-sd-1_49 boost_regex-mgw47-mt-s-1_49 boost_regex-mgw47-mt-sd-1_49 boost_system-mgw47-mt-s-1_49 boost_system-mgw47-mt-sd-1_49 boost_thread-mgw47-mt-s-1_49 boost_thread-mgw47-mt-sd-1_49' -BF_BOOST_LIBPATH = BF_BOOST + '/lib' +BF_BOOST_LIB_INTERNATIONAL = ' boost_locale-mgw47-mt-s-1_49 boost_locale-mgw47-mt-sd-1_49' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #Ray trace optimization WITH_BF_RAYOPTIMIZATION = True diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py index 4b719469c39..c0ea7972aeb 100644 --- a/build_files/scons/config/win64-vc-config.py +++ b/build_files/scons/config/win64-vc-config.py @@ -9,10 +9,10 @@ BF_FFMPEG_LIB = 'avformat-53.lib avcodec-53.lib avdevice-53.lib avutil-51.lib sw 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.2' +BF_PYTHON_VERSION = '3.3' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' -BF_PYTHON_LIB = 'python32' +BF_PYTHON_LIB = 'python33' BF_PYTHON_DLL = '${BF_PYTHON_LIB}' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' @@ -50,7 +50,7 @@ BF_PTHREADS_LIBPATH = '${BF_PTHREADS}/lib' WITH_BF_OPENEXR = True WITH_BF_STATICOPENEXR = False BF_OPENEXR = LIBDIR + '/openexr' -BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath ' +BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR ' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gnu_gettext' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True @@ -151,24 +146,40 @@ WITH_BF_OPENMP = True #Cycles WITH_BF_CYCLES = True +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = True +BF_OSL = '${LIBDIR}/osl' +BF_OSL_INC = '${BF_OSL}/include' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_LIB_STATIC = '${BF_OSL_LIBPATH}/oslcomp.lib ${BF_OSL_LIBPATH}/oslexec.lib ${BF_OSL_LIBPATH}/oslquery.lib ' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +BF_LLVM = LIBDIR + '/llvm' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + WITH_BF_OIIO = True BF_OIIO = '${LIBDIR}/openimageio' BF_OIIO_INC = '${BF_OIIO}/include' -BF_OIIO_LIB = 'OpenImageIO' -BF_OIIO_LIBPATH = '${BF_OIIO}/lib' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/OpenImageIO.lib' +WITH_BF_STATICOIIO = True WITH_BF_OCIO = True BF_OCIO = '${LIBDIR}/opencolorio' BF_OCIO_INC = '${BF_OCIO}/include' -BF_OCIO_LIB = 'OpenColorIO' -BF_OCIO_LIBPATH = '${BF_OCIO}/lib' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/OpenColorIO.lib' +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' +BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc90-mt-s-1_49' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #CUDA @@ -207,7 +218,7 @@ C_WARN = [] CC_WARN = [] CXX_WARN = [] -LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid'] +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'] diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index eb646f27d53..94a9f1d9c24 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -166,16 +166,15 @@ def setup_staticlibs(lenv): libincs += Split(lenv['BF_FFTW3_LIBPATH']) if lenv['WITH_BF_STATICFFTW3']: statlibs += Split(lenv['BF_FFTW3_LIB_STATIC']) + ''' if lenv['WITH_BF_ELTOPO']: libincs += Split(lenv['BF_LAPACK_LIBPATH']) if lenv['WITH_BF_STATICLAPACK']: - statlibs += Split(lenv['BF_LAPACK_LIB_STATIC']) + statlibs += Split(lenv['BF_LAPACK_LIB_STATIC']) + ''' if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']: statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC']) if lenv['WITH_BF_INTERNATIONAL']: - libincs += Split(lenv['BF_GETTEXT_LIBPATH']) - if lenv['WITH_BF_GETTEXT_STATIC']: - statlibs += Split(lenv['BF_GETTEXT_LIB_STATIC']) if lenv['WITH_BF_FREETYPE_STATIC']: statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC']) if lenv['WITH_BF_OPENAL']: @@ -225,6 +224,16 @@ def setup_staticlibs(lenv): if lenv['WITH_BF_STATICBOOST']: statlibs += Split(lenv['BF_BOOST_LIB_STATIC']) + if lenv['WITH_BF_CYCLES_OSL']: + libincs += Split(lenv['BF_OSL_LIBPATH']) + if lenv['WITH_BF_STATICOSL']: + statlibs += Split(lenv['BF_OSL_LIB_STATIC']) + + if lenv['WITH_BF_LLVM']: + libincs += Split(lenv['BF_LLVM_LIBPATH']) + if lenv['WITH_BF_STATICLLVM']: + statlibs += Split(lenv['BF_LLVM_LIB_STATIC']) + # setting this last so any overriding of manually libs could be handled if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross', 'win64-mingw'): libincs.append('/usr/lib') @@ -252,8 +261,6 @@ def setup_syslibs(lenv): syslibs.append(lenv['BF_PYTHON_LIB']+'_d') else: syslibs.append(lenv['BF_PYTHON_LIB']) - if lenv['WITH_BF_INTERNATIONAL'] and not lenv['WITH_BF_GETTEXT_STATIC']: - syslibs += Split(lenv['BF_GETTEXT_LIB']) if lenv['WITH_BF_OPENAL']: if not lenv['WITH_BF_STATICOPENAL']: syslibs += Split(lenv['BF_OPENAL_LIB']) @@ -288,8 +295,10 @@ def setup_syslibs(lenv): syslibs += Split(lenv['BF_SNDFILE_LIB']) if lenv['WITH_BF_FFTW3'] and not lenv['WITH_BF_STATICFFTW3']: syslibs += Split(lenv['BF_FFTW3_LIB']) + ''' if lenv['WITH_BF_ELTOPO']: syslibs += Split(lenv['BF_LAPACK_LIB']) + ''' if lenv['WITH_BF_SDL']: syslibs += Split(lenv['BF_SDL_LIB']) if not lenv['WITH_BF_STATICOPENGL']: @@ -315,6 +324,15 @@ def setup_syslibs(lenv): if lenv['WITH_BF_BOOST'] and not lenv['WITH_BF_STATICBOOST']: syslibs += Split(lenv['BF_BOOST_LIB']) + + if lenv['WITH_BF_INTERNATIONAL']: + syslibs += Split(lenv['BF_BOOST_LIB_INTERNATIONAL']) + + if lenv['WITH_BF_CYCLES_OSL'] and not lenv['WITH_BF_STATICOSL']: + syslibs += Split(lenv['BF_OSL_LIB']) + + if lenv['WITH_BF_LLVM'] and not lenv['WITH_BF_STATICLLVM']: + syslibs += Split(lenv['BF_LLVM_LIB']) if not lenv['WITH_BF_STATICJPEG']: syslibs += Split(lenv['BF_JPEG_LIB']) @@ -582,8 +600,8 @@ def AppIt(target=None, source=None, env=None): bldroot = env.Dir('.').abspath binary = env['BINARYKIND'] - sourcedir = bldroot + '/source/darwin/%s.app'%binary - sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary + sourcedir = bldroot + '/release/darwin/%s.app' % binary + sourceinfo = bldroot + "/release/darwin/%s.app/Contents/Info.plist"%binary targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary cmd = installdir + '/' +'%s.app'%binary @@ -633,11 +651,19 @@ def AppIt(target=None, source=None, env=None): commands.getoutput(cmd) cmd = 'cp -R %s/kernel/*.h %s/kernel/*.cl %s/kernel/*.cu %s/kernel/' % (croot, croot, croot, cinstalldir) commands.getoutput(cmd) - cmd = 'cp -R %s/kernel/svm %s/util/util_color.h %s/util/util_math.h %s/util/util_transform.h %s/util/util_types.h %s/kernel/' % (croot, croot, croot, croot, croot, cinstalldir) + cmd = 'cp -R %s/kernel/svm %s/kernel/closure %s/util/util_color.h %s/util/util_math.h %s/util/util_transform.h %s/util/util_types.h %s/kernel/' % (croot, croot, croot, croot, croot, croot, cinstalldir) commands.getoutput(cmd) cmd = 'cp -R %s/../intern/cycles/kernel/*.cubin %s/lib/' % (builddir, cinstalldir) commands.getoutput(cmd) + if env['WITH_BF_CYCLES_OSL']: + cmd = 'mkdir %s/shader' % (cinstalldir) + commands.getoutput(cmd) + cmd = 'cp -R %s/kernel/shaders/*.h %s/shader' % (croot, cinstalldir) + commands.getoutput(cmd) + cmd = 'cp -R %s/../intern/cycles/kernel/shaders/*.oso %s/shader' % (builddir, cinstalldir) + commands.getoutput(cmd) + if env['WITH_OSX_STATICPYTHON']: cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION) commands.getoutput(cmd) @@ -664,7 +690,7 @@ def AppIt(target=None, source=None, env=None): commands.getoutput(cmd) cmd = 'rm -rf %s/set_simulation_threads.app'%(installdir) # first clear omp_num_threads applescript commands.getoutput(cmd) - cmd = 'cp -R %s/source/darwin/set_simulation_threads.app %s/'%(bldroot, installdir) # copy the omp_num_threads applescript + cmd = 'cp -R %s/release/darwin/set_simulation_threads.app %s/'%(bldroot, installdir) # copy the omp_num_threads applescript commands.getoutput(cmd) # extract copy system python, be sure to update other build systems @@ -792,6 +818,20 @@ class BlenderEnvironment(SConsEnvironment): def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None, cc_compilerchange=None, cxx_compilerchange=None): global vcp + + # sanity check + # run once in a while to check we dont have duplicates + if 0: + for name, dirs in (("source", sources), ("include", includes)): + files_clean = [os.path.normpath(f) for f in dirs] + files_clean_set = set(files_clean) + if len(files_clean) != len(files_clean_set): + for f in sorted(files_clean_set): + if f != '.' and files_clean.count(f) > 1: + raise Exception("Found duplicate %s %r" % (name, f)) + del name, dirs, files_clean, files_clean_set, f + # end sanity check + if not self or not libname or not sources: print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC self.Exit() @@ -871,6 +911,7 @@ class BlenderEnvironment(SConsEnvironment): print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC lenv = self.Clone() lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS']) + lenv.Append(LINKFLAGS = lenv['BF_PROGRAM_LINKFLAGS']) if lenv['OURPLATFORM'] in ('win32-mingw', 'win64-mingw', 'linuxcross', 'cygwin', 'linux'): lenv.Replace(LINK = '$CXX') if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'): diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 19652bb7851..19f4ac9a1de 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -116,11 +116,11 @@ def validate_arguments(args, bc): 'WITH_BF_TIFF', 'BF_TIFF', 'BF_TIFF_INC', 'BF_TIFF_LIB', 'BF_TIFF_LIBPATH', 'WITH_BF_STATICTIFF', 'BF_TIFF_LIB_STATIC', 'WITH_BF_ZLIB', 'BF_ZLIB', 'BF_ZLIB_INC', 'BF_ZLIB_LIB', 'BF_ZLIB_LIBPATH', 'WITH_BF_STATICZLIB', 'BF_ZLIB_LIB_STATIC', 'WITH_BF_INTERNATIONAL', - 'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'WITH_BF_GETTEXT_STATIC', 'BF_GETTEXT_LIB_STATIC', 'BF_GETTEXT_LIBPATH', 'WITH_BF_ICONV', 'BF_ICONV', 'BF_ICONV_INC', 'BF_ICONV_LIB', 'BF_ICONV_LIBPATH', 'WITH_BF_GAMEENGINE', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB', - 'WITH_BF_ELTOPO', 'BF_LAPACK', 'BF_LAPACK_LIB', 'BF_LAPACK_LIBPATH', 'BF_LAPACK_LIB_STATIC', + # 'WITH_BF_ELTOPO', # now only available in a branch + 'BF_LAPACK', 'BF_LAPACK_LIB', 'BF_LAPACK_LIBPATH', 'BF_LAPACK_LIB_STATIC', 'BF_WINTAB', 'BF_WINTAB_INC', 'BF_FREETYPE', 'BF_FREETYPE_INC', 'BF_FREETYPE_LIB', 'BF_FREETYPE_LIBPATH', 'BF_FREETYPE_LIB_STATIC', 'WITH_BF_FREETYPE_STATIC', 'WITH_BF_QUICKTIME', 'BF_QUICKTIME', 'BF_QUICKTIME_INC', 'BF_QUICKTIME_LIB', 'BF_QUICKTIME_LIBPATH', @@ -164,8 +164,10 @@ def validate_arguments(args, bc): 'WITH_BF_CYCLES', 'WITH_BF_CYCLES_CUDA_BINARIES', 'BF_CYCLES_CUDA_NVCC', 'BF_CYCLES_CUDA_NVCC', 'WITH_BF_CYCLES_CUDA_THREADED_COMPILE', 'WITH_BF_OIIO', 'WITH_BF_STATICOIIO', 'BF_OIIO', 'BF_OIIO_INC', 'BF_OIIO_LIB', 'BF_OIIO_LIB_STATIC', 'BF_OIIO_LIBPATH', 'WITH_BF_OCIO', 'WITH_BF_STATICOCIO', 'BF_OCIO', 'BF_OCIO_INC', 'BF_OCIO_LIB', 'BF_OCIO_LIB_STATIC', 'BF_OCIO_LIBPATH', - 'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH', - 'WITH_BF_LIBMV' + 'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_INTERNATIONAL', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH', + 'WITH_BF_LIBMV', + 'WITH_BF_CYCLES_OSL', 'WITH_BF_STATICOSL', 'BF_OSL', 'BF_OSL_INC', 'BF_OSL_LIB', 'BF_OSL_LIBPATH', 'BF_OSL_LIB_STATIC', 'BF_OSL_COMPILER', + 'WITH_BF_LLVM', 'WITH_BF_STATICLLVM', 'BF_LLVM', 'BF_LLVM_LIB', 'BF_LLVM_LIBPATH', 'BF_LLVM_LIB_STATIC', 'BF_PROGRAM_LINKFLAGS' ] # Have options here that scons expects to be lists @@ -179,7 +181,7 @@ def validate_arguments(args, bc): 'BF_DEBUG_CFLAGS', 'BF_DEBUG_CCFLAGS', 'BF_DEBUG_CXXFLAGS', 'C_WARN', 'CC_WARN', 'CXX_WARN', 'LLIBS', 'PLATFORM_LINKFLAGS','MACOSX_ARCHITECTURE', 'MACOSX_SDK_CHECK', 'XCODE_CUR_VER', - 'BF_CYCLES_CUDA_BINARIES_ARCH', + 'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET' ] @@ -381,15 +383,8 @@ def read_opts(env, cfg, args): ('BF_ZLIB_LIBPATH', 'ZLib library path', ''), ('BF_ZLIB_LIB_STATIC', 'ZLib static library', ''), - (BoolVariable('WITH_BF_INTERNATIONAL', 'Use Gettext if true', True)), + (BoolVariable('WITH_BF_INTERNATIONAL', 'Use Boost::locale if true', True)), - ('BF_GETTEXT', 'gettext base path', ''), - ('BF_GETTEXT_INC', 'gettext include path', ''), - ('BF_GETTEXT_LIB', 'gettext library', ''), - (BoolVariable('WITH_BF_GETTEXT_STATIC', 'Use static gettext library if true', False)), - ('BF_GETTEXT_LIB_STATIC', 'static gettext library', ''), - ('BF_GETTEXT_LIBPATH', 'gettext library path', ''), - (BoolVariable('WITH_BF_ICONV', 'Use iconv if true', True)), ('BF_ICONV', 'iconv base path', ''), ('BF_ICONV_INC', 'iconv include path', ''), @@ -399,8 +394,7 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_GAMEENGINE', 'Build with gameengine' , False)), (BoolVariable('WITH_BF_BULLET', 'Use Bullet if true', True)), - - (BoolVariable('WITH_BF_ELTOPO', 'Use Eltopo collision library if true', False)), + # (BoolVariable('WITH_BF_ELTOPO', 'Use Eltopo collision library if true', False)), # this is now only available in a branch ('BF_LAPACK', 'LAPACK base path', ''), ('BF_LAPACK_LIB', 'LAPACK library', ''), ('BF_LAPACK_LIB_STATIC', 'LAPACK library', ''), @@ -508,8 +502,9 @@ def read_opts(env, cfg, args): ('LLIBS', 'Platform libs', []), ('PLATFORM_LINKFLAGS', 'Platform linkflags', []), ('MACOSX_ARCHITECTURE', 'python_arch.zip select', ''), - ('MACOSX_SDK_CHECK', 'detect available OSX sdk`s', ''), - ('XCODE_CUR_VER', 'detect XCode version', ''), + ('MACOSX_SDK_CHECK', 'Detect available OS X SDK`s', ''), + ('XCODE_CUR_VER', 'Detect XCode version', ''), + ('MACOSX_DEPLOYMENT_TARGET', 'Detect OS X target version', ''), (BoolVariable('BF_PROFILE', 'Add profiling information if true', False)), ('BF_PROFILE_CFLAGS', 'C only profiling flags', []), @@ -598,11 +593,30 @@ def read_opts(env, cfg, args): ('BF_BOOST', 'Boost root path', ''), ('BF_BOOST_INC', 'Boost include path', ''), ('BF_BOOST_LIB', 'Boost library', ''), + ('BF_BOOST_LIB_INTERNATIONAL', 'Boost library', ''), ('BF_BOOST_LIBPATH', 'Boost library path', ''), ('BF_BOOST_LIB_STATIC', 'Boost static library', ''), (BoolVariable('WITH_GHOST_XDND', 'Build with drag-n-drop support on Linux platforms using XDND protocol', True)), - (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', False)) + (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', False)), + + (BoolVariable('WITH_BF_CYCLES_OSL', 'Build with OSL sypport in Cycles', False)), + (BoolVariable('WITH_BF_STATICOSL', 'Staticly link to OSL', False)), + ('BF_OSL', 'OSL root path', ''), + ('BF_OSL_INC', 'OSL include path', ''), + ('BF_OSL_LIB', 'OSL library', ''), + ('BF_OSL_LIBPATH', 'OSL library path', ''), + ('BF_OSL_LIB_STATIC', 'OSL static library', ''), + ('BF_OSL_COMPILER', 'OSL compiler', ''), + + (BoolVariable('WITH_BF_LLVM', 'Build with LLVM sypport (required for OSL)', False)), + (BoolVariable('WITH_BF_STATICLLVM', 'Staticly link to LLVM', False)), + ('BF_LLVM', 'LLVM root path', ''), + ('BF_LLVM_LIB', 'LLVM library', ''), + ('BF_LLVM_LIBPATH', 'LLVM library path', ''), + ('BF_LLVM_LIB_STATIC', 'LLVM static library', ''), + + ('BF_PROGRAM_LINKFLAGS', 'Link flags applied only to final binaries (blender and blenderplayer, not makesrna/makesdna)', '') ) # end of opts.AddOptions() return localopts @@ -673,7 +687,7 @@ def buildslave(target=None, source=None, env=None): elif bitness == '32bit': platform = 'linux-' + glibc + '-i686' if platform == 'darwin': - platform = 'OSX-' + env['MACOSX_ARCHITECTURE'] + platform = 'OSX-' + env['MACOSX_DEPLOYMENT_TARGET'] + '-' + env['MACOSX_ARCHITECTURE'] branch = env['BUILDBOT_BRANCH'] diff --git a/doc/blender_file_format/BlendFileDnaExporter_25.py b/doc/blender_file_format/BlendFileDnaExporter_25.py index b7b89c89268..837b67c6eed 100755 --- a/doc/blender_file_format/BlendFileDnaExporter_25.py +++ b/doc/blender_file_format/BlendFileDnaExporter_25.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/doc/blender_file_format/BlendFileReader.py b/doc/blender_file_format/BlendFileReader.py index b7091ad8ff5..a4d2f494c5b 100644 --- a/doc/blender_file_format/BlendFileReader.py +++ b/doc/blender_file_format/BlendFileReader.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/doc/manpage/blender.1 b/doc/manpage/blender.1 index e7164fcb96b..2addb60c5f7 100644 --- a/doc/manpage/blender.1 +++ b/doc/manpage/blender.1 @@ -1,4 +1,4 @@ -.TH "BLENDER" "1" "October 04, 2012" "Blender Blender 2\&.64 (sub 0)" +.TH "BLENDER" "1" "December 04, 2012" "Blender Blender 2\&.65" .SH NAME blender \- a 3D modelling and rendering package @@ -15,7 +15,7 @@ Use Blender to create TV commercials, to make technical visualizations, business http://www.blender.org .SH OPTIONS -Blender 2.64 (sub 0) +Blender 2.65 Usage: blender [args ...] [file] [args ...] .br .SS "Render Options:" @@ -145,6 +145,10 @@ Playback , only operates this way when not running in background. .br \-j Set frame step to .br + \-s Play from +.br + \-e Play until +.br .IP @@ -344,6 +348,12 @@ Enable debug messages for python Enable debug messages for the event system .br +.TP +.B \-\-debug\-handlers +.br +Enable debug messages for event handling +.br + .TP .B \-\-debug\-wm .br diff --git a/doc/python_api/examples/bmesh.ops.1.py b/doc/python_api/examples/bmesh.ops.1.py new file mode 100644 index 00000000000..abce087ceb3 --- /dev/null +++ b/doc/python_api/examples/bmesh.ops.1.py @@ -0,0 +1,108 @@ +# This script uses bmesh operators to make 2 links of a chain. + +import bpy +import bmesh +import math +import mathutils + +# Make a new BMesh +bm = bmesh.new() + +# Add a circle XXX, should return all geometry created, not just verts. +bmesh.ops.create_circle( + bm, + cap_ends=False, + diameter=0.2, + segments=8) + + +# Spin and deal with geometry on side 'a' +edges_start_a = bm.edges[:] +geom_start_a = bm.verts[:] + edges_start_a +ret = bmesh.ops.spin( + bm, + geom=geom_start_a, + angle=math.radians(180.0), + steps=8, + axis=(1.0, 0.0, 0.0), + cent=(0.0, 1.0, 0.0)) +edges_end_a = [ele for ele in ret["geom_last"] + if isinstance(ele, bmesh.types.BMEdge)] +del ret + + +# Extrude and create geometry on side 'b' +ret = bmesh.ops.extrude_edge_only( + bm, + edges=edges_start_a) +geom_extrude_mid = ret["geom"] +del ret + + +# Collect the edges to spin XXX, 'extrude_edge_only' could return this. +verts_extrude_b = [ele for ele in geom_extrude_mid + if isinstance(ele, bmesh.types.BMVert)] +edges_extrude_b = [ele for ele in geom_extrude_mid + if isinstance(ele, bmesh.types.BMEdge) and ele.is_boundary] +bmesh.ops.translate( + bm, + verts=verts_extrude_b, + vec=(0.0, 0.0, 1.0)) + + +# Create the circle on side 'b' +ret = bmesh.ops.spin( + bm, + geom=verts_extrude_b + edges_extrude_b, + angle=-math.radians(180.0), + steps=8, + axis=(1.0, 0.0, 0.0), + cent=(0.0, 1.0, 1.0)) +edges_end_b = [ele for ele in ret["geom_last"] + if isinstance(ele, bmesh.types.BMEdge)] +del ret + + +# Bridge the resulting edge loops of both spins 'a & b' +bmesh.ops.bridge_loops( + bm, + edges=edges_end_a + edges_end_b) + + +# Now we have made a links of the chain, make a copy and rotate it +# (so this looks something like a chain) + +ret = bmesh.ops.duplicate( + bm, + geom=bm.verts[:] + bm.edges[:] + bm.faces[:]) +geom_dupe = ret["geom"] +verts_dupe = [ele for ele in geom_dupe if isinstance(ele, bmesh.types.BMVert)] +del ret + +# position the new link +bmesh.ops.translate( + bm, + verts=verts_dupe, + vec=(0.0, 0.0, 2.0)) +bmesh.ops.rotate( + bm, + verts=verts_dupe, + cent=(0.0, 1.0, 0.0), + matrix=mathutils.Matrix.Rotation(math.radians(90.0), 3, 'Z')) + +# Done with creating the mesh, simply link it into the scene so we can see it + +# Finish up, write the bmesh into a new mesh +me = bpy.data.meshes.new("Mesh") +bm.to_mesh(me) +bm.free() + + +# Add the mesh to the scene +scene = bpy.context.scene +obj = bpy.data.objects.new("Object", me) +scene.objects.link(obj) + +# Select and make active +scene.objects.active = obj +obj.select = True diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst index 260a86f7c59..7d20aa31a36 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -254,13 +254,6 @@ General functions :rtype: list [float], len(getSpectrum()) == 512 -.. function:: stopDSP() - - Stops the sound driver using DSP effects. - - Only the fmod sound driver supports this. - DSP can be computationally expensive. - .. function:: getMaxLogicFrame() Gets the maximum number of logic frames per render frame. @@ -331,6 +324,24 @@ General functions .. warning: Not implimented yet +.. function:: getExitKey() + + Gets the key used to exit the game engine + + :return: The key (defaults to :mod:`bge.events.ESCKEY`) + :rtype: int + +.. function:: setExitKey(key) + + Sets the key used to exit the game engine + + :arg key: A key constant from :mod:`bge.events` + :type key: int + +.. function:: NextFrame() + + Render next frame (if Python has control) + ***************** Utility functions ***************** @@ -373,6 +384,10 @@ Utility functions .. function:: PrintGLInfo() Prints GL Extension Info into the console + +.. function:: PrintMemInfo() + + Prints engine statistics into the console ********* Constants @@ -401,6 +416,45 @@ Sensor Status .. data:: KX_SENSOR_ACTIVE .. data:: KX_SENSOR_JUST_DEACTIVATED +--------------- +Armature Sensor +--------------- + +.. _armaturesensor-type: + +See :class:`bge.types.KX_ArmatureSensor.type` + +.. data:: KX_ARMSENSOR_STATE_CHANGED + + Detect that the constraint is changing state (active/inactive) + + :value: 0 + +.. data:: KX_ARMSENSOR_LIN_ERROR_BELOW + + Detect that the constraint linear error is above a threshold + + :value: 1 + +.. data:: KX_ARMSENSOR_LIN_ERROR_ABOVE + + Detect that the constraint linear error is below a threshold + + :value: 2 + +.. data:: KX_ARMSENSOR_ROT_ERROR_BELOW + + Detect that the constraint rotation error is above a threshold + + :value: 3 + +.. data:: KX_ARMSENSOR_ROT_ERROR_ABOVE + + Detect that the constraint rotation error is below a threshold + + :value: 4 + + .. _logic-property-sensor: --------------- @@ -483,6 +537,52 @@ See :class:`bge.types.BL_ActionActuator` .. data:: KX_ACTIONACT_LOOPEND .. data:: KX_ACTIONACT_PROPERTY +----------------- +Armature Actuator +----------------- + + .. _armatureactuator-constants-type: + +See :class:`bge.types.BL_ArmatureActuator.type` + +.. data:: KX_ACT_ARMATURE_RUN + + Just make sure the armature will be updated on the next graphic frame. + This is the only persistent mode of the actuator: + it executes automatically once per frame until stopped by a controller + + :value: 0 + +.. data:: KX_ACT_ARMATURE_ENABLE + + Enable the constraint. + + :value: 1 + +.. data:: KX_ACT_ARMATURE_DISABLE + + Disable the constraint (runtime constraint values are not updated). + + :value: 2 + +.. data:: KX_ACT_ARMATURE_SETTARGET + + Change target and subtarget of constraint. + + :value: 3 + +.. data:: KX_ACT_ARMATURE_SETWEIGHT + + Change weight of constraint (IK only). + + :value: 4 + +.. data:: KX_ACT_ARMATURE_SETINFLUENCE + + Change influence of constraint. + + :value: 5 + ------------------- Constraint Actuator ------------------- @@ -493,31 +593,31 @@ See :class:`bge.types.KX_ConstraintActuator.option` * Applicable to Distance constraint: - .. data:: KX_ACT_CONSTRAINT_NORMAL +.. data:: KX_CONSTRAINTACT_NORMAL Activate alignment to surface - .. data:: KX_ACT_CONSTRAINT_DISTANCE +.. data:: KX_CONSTRAINTACT_DISTANCE Activate distance control - .. data:: KX_ACT_CONSTRAINT_LOCAL +.. data:: KX_CONSTRAINTACT_LOCAL Direction of the ray is along the local axis * Applicable to Force field constraint: - .. data:: KX_ACT_CONSTRAINT_DOROTFH +.. data:: KX_CONSTRAINTACT_DOROTFH Force field act on rotation as well * Applicable to both: - .. data:: KX_ACT_CONSTRAINT_MATERIAL +.. data:: KX_CONSTRAINTACT_MATERIAL Detect material rather than property - .. data:: KX_ACT_CONSTRAINT_PERMANENT +.. data:: KX_CONSTRAINTACT_PERMANENT No deactivation if ray does not hit target @@ -585,27 +685,27 @@ See :class:`bge.types.KX_ConstraintActuator.limit` Set orientation of Z axis -.. data:: KX_ACT_CONSTRAINT_FHNX +.. data:: KX_CONSTRAINTACT_FHNX Set force field along negative X axis -.. data:: KX_ACT_CONSTRAINT_FHNY +.. data:: KX_CONSTRAINTACT_FHNY Set force field along negative Y axis -.. data:: KX_ACT_CONSTRAINT_FHNZ +.. data:: KX_CONSTRAINTACT_FHNZ Set force field along negative Z axis -.. data:: KX_ACT_CONSTRAINT_FHPX +.. data:: KX_CONSTRAINTACT_FHPX Set force field along positive X axis -.. data:: KX_ACT_CONSTRAINT_FHPY +.. data:: KX_CONSTRAINTACT_FHPY Set force field along positive Y axis -.. data:: KX_ACT_CONSTRAINT_FHPZ +.. data:: KX_CONSTRAINTACT_FHPZ Set force field along positive Z axis @@ -708,102 +808,32 @@ See :class:`bge.types.KX_SoundActuator` .. data:: KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP :value: 6 - + +----------------- +Steering Actuator +----------------- + +.. _logic-steering-actuator: + +See :class:`bge.types.KX_SteeringActuator.behavior` + +.. data:: KX_STEERING_SEEK + + :value: 1 + +.. data:: KX_STEERING_FLEE + + :value: 2 + +.. data:: KX_STEERING_PATHFOLLOWING + + :value: 3 + ======= Various ======= -.. _input-status: - ------------- -Input Status ------------- - -See :class:`bge.types.SCA_PythonKeyboard`, :class:`bge.types.SCA_PythonMouse`, :class:`bge.types.SCA_MouseSensor`, :class:`bge.types.SCA_KeyboardSensor` - -.. data:: KX_INPUT_NONE -.. data:: KX_INPUT_JUST_ACTIVATED -.. data:: KX_INPUT_ACTIVE -.. data:: KX_INPUT_JUST_RELEASED - -------------- -Mouse Buttons -------------- - -See :class:`bge.types.SCA_MouseSensor` - -.. data:: KX_MOUSE_BUT_LEFT -.. data:: KX_MOUSE_BUT_MIDDLE -.. data:: KX_MOUSE_BUT_RIGHT - ------- -States ------- - -See :class:`bge.types.KX_StateActuator` - -.. data:: KX_STATE1 -.. data:: KX_STATE2 -.. data:: KX_STATE3 -.. data:: KX_STATE4 -.. data:: KX_STATE5 -.. data:: KX_STATE6 -.. data:: KX_STATE7 -.. data:: KX_STATE8 -.. data:: KX_STATE9 -.. data:: KX_STATE10 -.. data:: KX_STATE11 -.. data:: KX_STATE12 -.. data:: KX_STATE13 -.. data:: KX_STATE14 -.. data:: KX_STATE15 -.. data:: KX_STATE16 -.. data:: KX_STATE17 -.. data:: KX_STATE18 -.. data:: KX_STATE19 -.. data:: KX_STATE20 -.. data:: KX_STATE21 -.. data:: KX_STATE22 -.. data:: KX_STATE23 -.. data:: KX_STATE24 -.. data:: KX_STATE25 -.. data:: KX_STATE26 -.. data:: KX_STATE27 -.. data:: KX_STATE28 -.. data:: KX_STATE29 -.. data:: KX_STATE30 - -.. _state-actuator-operation: - -See :class:`bge.types.KX_StateActuator.operation` - -.. data:: KX_STATE_OP_CLR - - Substract bits to state mask - - :value: 0 - -.. data:: KX_STATE_OP_CPY - - Copy state mask - - :value: 1 - -.. data:: KX_STATE_OP_NEG - - Invert bits to state mask - - :value: 2 - -.. data:: KX_STATE_OP_SET - - Add bits to state mask - - :value: 3 - -.. _Two-D-FilterActuator-mode: - --------- 2D Filter --------- @@ -877,6 +907,227 @@ See :class:`bge.types.KX_StateActuator.operation` .. data:: RAS_2DFILTER_SOBEL :value: 7 + +---------------- +Armature Channel +---------------- +.. _armaturechannel-constants-rotation-mode: + +See :class:`bge.types.BL_ArmatureChannel.rotation_mode` + +.. note: + euler mode are named as in Blender UI but the actual axis order is reversed + +.. data:: ROT_MODE_QUAT + + Use quaternion in rotation attribute to update bone rotation. + + :value: 0 + +.. data:: ROT_MODE_XYZ + + Use euler_rotation and apply angles on bone's Z, Y, X axis successively. + + :value: 1 + +.. data:: ROT_MODE_XZY + + Use euler_rotation and apply angles on bone's Y, Z, X axis successively. + + :value: 2 + +.. data:: ROT_MODE_YXZ + + Use euler_rotation and apply angles on bone's Z, X, Y axis successively. + + :value: 3 + +.. data:: ROT_MODE_YZX + + Use euler_rotation and apply angles on bone's X, Z, Y axis successively. + + :value: 4 + +.. data:: ROT_MODE_ZXY + + Use euler_rotation and apply angles on bone's Y, X, Z axis successively. + + :value: 5 + +.. data:: ROT_MODE_ZYX + + Use euler_rotation and apply angles on bone's X, Y, Z axis successively. + + :value: 6 + + +------------------- +Armature Constraint +------------------- +.. _armatureconstraint-constants-type: + +See :class:`bge.types.BL_ArmatureConstraint.type` + +.. data:: CONSTRAINT_TYPE_TRACKTO +.. data:: CONSTRAINT_TYPE_KINEMATIC +.. data:: CONSTRAINT_TYPE_ROTLIKE +.. data:: CONSTRAINT_TYPE_LOCLIKE +.. data:: CONSTRAINT_TYPE_MINMAX +.. data:: CONSTRAINT_TYPE_SIZELIKE +.. data:: CONSTRAINT_TYPE_LOCKTRACK +.. data:: CONSTRAINT_TYPE_STRETCHTO +.. data:: CONSTRAINT_TYPE_CLAMPTO +.. data:: CONSTRAINT_TYPE_TRANSFORM +.. data:: CONSTRAINT_TYPE_DISTLIMIT + +.. _armatureconstraint-constants-ik-type: + +See :class:`bge.types.BL_ArmatureConstraint.ik_type` + +.. data:: CONSTRAINT_IK_COPYPOSE + + constraint is trying to match the position and eventually the rotation of the target. + + :value: 0 + +.. data:: CONSTRAINT_IK_DISTANCE + + Constraint is maintaining a certain distance to target subject to ik_mode + + :value: 1 + +.. _armatureconstraint-constants-ik-flag: + +See :class:`bge.types.BL_ArmatureConstraint.ik_flag` + +.. data:: CONSTRAINT_IK_FLAG_TIP + + Set when the constraint operates on the head of the bone and not the tail + + :value: 1 + +.. data:: CONSTRAINT_IK_FLAG_ROT + + Set when the constraint tries to match the orientation of the target + + :value: 2 + +.. data:: CONSTRAINT_IK_FLAG_STRETCH + + Set when the armature is allowed to stretch (only the bones with stretch factor > 0.0) + + :value: 16 + +.. data:: CONSTRAINT_IK_FLAG_POS + + Set when the constraint tries to match the position of the target. + + :value: 32 + +.. _armatureconstraint-constants-ik-mode: + +See :class:`bge.types.BL_ArmatureConstraint.ik_mode` + +.. data:: CONSTRAINT_IK_MODE_INSIDE + + The constraint tries to keep the bone within ik_dist of target + + :value: 0 + +.. data:: CONSTRAINT_IK_MODE_OUTSIDE + + The constraint tries to keep the bone outside ik_dist of the target + + :value: 1 + +.. data:: CONSTRAINT_IK_MODE_ONSURFACE + + The constraint tries to keep the bone exactly at ik_dist of the target. + + :value: 2 + +.. _input-status: + +---------------- +Blender Material +---------------- + +.. data:: BL_DST_ALPHA +.. data:: BL_DST_COLOR +.. data:: BL_ONE +.. data:: BL_ONE_MINUS_DST_ALPHA +.. data:: BL_ONE_MINUS_DST_COLOR +.. data:: BL_ONE_MINUS_SRC_ALPHA +.. data:: BL_ONE_MINUS_SRC_COLOR +.. data:: BL_SRC_ALPHA +.. data:: BL_SRC_ALPHA_SATURATE +.. data:: BL_SRC_COLOR +.. data:: BL_ZERO + +------------ +Input Status +------------ + +See :class:`bge.types.SCA_PythonKeyboard`, :class:`bge.types.SCA_PythonMouse`, :class:`bge.types.SCA_MouseSensor`, :class:`bge.types.SCA_KeyboardSensor` + +.. data:: KX_INPUT_NONE +.. data:: KX_INPUT_JUST_ACTIVATED +.. data:: KX_INPUT_ACTIVE +.. data:: KX_INPUT_JUST_RELEASED + +------------- +KX_GameObject +------------- +.. _gameobject-playaction-mode: + +See :class:`bge.types.KX_GameObject.playAction` + +.. data:: KX_ACTION_MODE_PLAY + + Play the action once. + + :value: 0 + +.. data:: KX_ACTION_MODE_LOOP + + Loop the action (repeat it). + + :value: 1 + +.. data:: KX_ACTION_MODE_PING_PONG + + Play the action one direct then back the other way when it has completed. + + :value: 2 + + +------------- +Mouse Buttons +------------- + +See :class:`bge.types.SCA_MouseSensor` + +.. data:: KX_MOUSE_BUT_LEFT +.. data:: KX_MOUSE_BUT_MIDDLE +.. data:: KX_MOUSE_BUT_RIGHT + +-------------------------- +Navigation Mesh Draw Modes +-------------------------- + +.. _navmesh-draw-mode: + +.. data:: RM_WALLS + + Draw only the walls. + +.. data:: RM_POLYS + + Draw only polygons. + +.. data:: RM_TRIS + + Draw triangle mesh. ------ Shader @@ -904,18 +1155,69 @@ Shader .. data:: SHD_TANGENT ----------------- -Blender Material ----------------- +------ +States +------ -.. data:: BL_DST_ALPHA -.. data:: BL_DST_COLOR -.. data:: BL_ONE -.. data:: BL_ONE_MINUS_DST_ALPHA -.. data:: BL_ONE_MINUS_DST_COLOR -.. data:: BL_ONE_MINUS_SRC_ALPHA -.. data:: BL_ONE_MINUS_SRC_COLOR -.. data:: BL_SRC_ALPHA -.. data:: BL_SRC_ALPHA_SATURATE -.. data:: BL_SRC_COLOR -.. data:: BL_ZERO +See :class:`bge.types.KX_StateActuator` + +.. data:: KX_STATE1 +.. data:: KX_STATE2 +.. data:: KX_STATE3 +.. data:: KX_STATE4 +.. data:: KX_STATE5 +.. data:: KX_STATE6 +.. data:: KX_STATE7 +.. data:: KX_STATE8 +.. data:: KX_STATE9 +.. data:: KX_STATE10 +.. data:: KX_STATE11 +.. data:: KX_STATE12 +.. data:: KX_STATE13 +.. data:: KX_STATE14 +.. data:: KX_STATE15 +.. data:: KX_STATE16 +.. data:: KX_STATE17 +.. data:: KX_STATE18 +.. data:: KX_STATE19 +.. data:: KX_STATE20 +.. data:: KX_STATE21 +.. data:: KX_STATE22 +.. data:: KX_STATE23 +.. data:: KX_STATE24 +.. data:: KX_STATE25 +.. data:: KX_STATE26 +.. data:: KX_STATE27 +.. data:: KX_STATE28 +.. data:: KX_STATE29 +.. data:: KX_STATE30 + +.. _state-actuator-operation: + +See :class:`bge.types.KX_StateActuator.operation` + +.. data:: KX_STATE_OP_CLR + + Substract bits to state mask + + :value: 0 + +.. data:: KX_STATE_OP_CPY + + Copy state mask + + :value: 1 + +.. data:: KX_STATE_OP_NEG + + Invert bits to state mask + + :value: 2 + +.. data:: KX_STATE_OP_SET + + Add bits to state mask + + :value: 3 + +.. _Two-D-FilterActuator-mode: diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst index fdaeb61173f..8cf9ccb794c 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -205,6 +205,18 @@ Types :type: boolean + .. attribute:: pos_ticks + + The number of ticks since the last positive pulse (read-only). + + :type: int + + .. attribute:: neg_ticks + + The number of ticks since the last negative pulse (read-only). + + :type: int + .. attribute:: status The status of the sensor (read-only): can be one of :ref:`these constants`. @@ -621,6 +633,71 @@ Types :type: string + +.. class:: KX_SteeringActuator(SCA_IActuator) + + Steering Actuator for navigation. + + .. attribute:: behavior + + The steering behavior to use. + + :type: one of :ref:`these constants ` + + .. attribute:: velocity + + Velocity magnitude + + :type: float + + .. attribute:: acceleration + + Max acceleration + + :type: float + + .. attribute:: turnspeed + + Max turn speed + + :type: float + + .. attribute:: distance + + Relax distance + + :type: float + + .. attribute:: target + + Target object + + :type: :class:`KX_GameObject` + + .. attribute:: navmesh + + Navigation mesh + + :type: :class:`KX_GameObject` + + .. attribute:: selfterminated + + Terminate when target is reached + + :type: boolean + + .. attribute:: enableVisualization + + Enable debug visualization + + :type: boolean + + .. attribute:: pathUpdatePeriod + + Path update period + + :type: int + .. class:: CListValue(CPropValue) This is a list like object used in the game engine internally that behaves similar to a python list in most ways. @@ -682,10 +759,32 @@ Types The id is derived from a memory location and will be different each time the game engine starts. + .. warning:: + + The id can't be stored as an integer in game object properties, as those only have a limited range that the id may not be contained in. Instead an id can be stored as a string game property and converted back to an integer for use in from_id lookups. + .. class:: KX_BlenderMaterial(PyObjectPlus) KX_BlenderMaterial + .. attribute:: shader + + The materials shader. + + :type: :class:`BL_Shader` + + .. attribute:: blending + + Ints used for pixel blending, (src, dst), matching the setBlending method. + + :type: (integer, integer) + + .. attribute:: material_index + + The material's index. + + :type: integer + .. method:: getShader() Returns the material's shader. @@ -743,7 +842,13 @@ Types strength of of the camera following movement. :type: float - + + .. attribute:: axis + + The camera axis (0, 1, 2) for positive ``XYZ``, (3, 4, 5) for negative ``XYZ``. + + :type: int + .. attribute:: min minimum distance to the target object maintained by the actuator. @@ -762,12 +867,6 @@ Types :type: float - .. attribute:: useXY - - axis this actuator is tracking, True=X, False=Y. - - :type: boolean - .. attribute:: object the object this actuator tracks. @@ -988,14 +1087,14 @@ Types The object's parent object. (read-only). :type: :class:`KX_GameObject` or None - - .. attribute:: group_children + + .. attribute:: groupMembers Returns the list of group members if the object is a group object, otherwise None is returned. :type: :class:`CListValue` of :class:`KX_GameObject` or None - .. attribute:: group_parent + .. attribute:: groupObject Returns the group object that the object belongs to or None if the object is not part of a group. @@ -1100,30 +1199,30 @@ Types The object's world space transform matrix. 4x4 Matrix. :type: :class:`mathutils.Matrix` - + .. attribute:: localLinearVelocity - The object's local linear velocity. [x, y, z] - - :type: :class:`mathutils.Vector` - + The object's local linear velocity. [x, y, z] + + :type: :class:`mathutils.Vector` + .. attribute:: worldLinearVelocity The object's world linear velocity. [x, y, z] - - :type: :class:`mathutils.Vector` - + + :type: :class:`mathutils.Vector` + .. attribute:: localAngularVelocity The object's local angular velocity. [x, y, z] - - :type: :class:`mathutils.Vector` - + + :type: :class:`mathutils.Vector` + .. attribute:: worldAngularVelocity The object's world angular velocity. [x, y, z] - - :type: :class:`mathutils.Vector` + + :type: :class:`mathutils.Vector` .. attribute:: timeOffset @@ -1211,6 +1310,13 @@ Types :type: :class:`CListValue` of :class:`KX_GameObject`'s + .. attribute:: life + + The number of seconds until the object ends, assumes 50fps. + (when added with an add object actuator), (read-only). + + :type: float + .. method:: endObject() Delete this object, can be used in place of the EndObject Actuator. @@ -1653,7 +1759,7 @@ Types :arg blendin: the amount of blending between this animation and the previous one on this layer :type blendin: float :arg play_mode: the play mode - :type play_mode: KX_ACTION_MODE_PLAY, KX_ACTION_MODE_LOOP, or KX_ACTION_MODE_PING_PONG + :type play_mode: one of :ref:`these constants ` :arg layer_weight: how much of the previous layer to use for blending (0 = add) :type layer_weight: float :arg ipo_flags: flags for the old IPO behaviors (force, etc) @@ -1810,10 +1916,6 @@ Types :type: list [r, g, b] - .. attribute:: colour - - Synonym for color. - .. attribute:: lin_attenuation The linear component of this light's attenuation. (SPOT and NORMAL lights only). @@ -1898,11 +2000,6 @@ Types :type: integer - .. method:: getNumMaterials() - - :return: number of materials associated with this object - :rtype: integer - .. method:: getMaterialName(matid) Gets the name of the specified material. @@ -1943,11 +2040,6 @@ Types :return: a vertex object. :rtype: :class:`KX_VertexProxy` - .. method:: getNumPolygons() - - :return: The number of polygon in the mesh. - :rtype: integer - .. method:: getPolygon(index) Gets the specified polygon from the mesh. @@ -1957,6 +2049,28 @@ Types :return: a polygon object. :rtype: :class:`PolyProxy` + .. method:: transform(matid, matrix) + + Transforms the vertices of a mesh. + + :arg matid: material index, -1 transforms all. + :type matid: integer + :arg matrix: transformation matrix. + :type matrix: 4x4 matrix [[float]] + + .. method:: transformUV(matid, matrix, uv_index=-1, uv_index_from=-1) + + Transforms the vertices UV's of a mesh. + + :arg matid: material index, -1 transforms all. + :type matid: integer + :arg matrix: transformation matrix. + :type matrix: 4x4 matrix [[float]] + :arg uv_index: optional uv index, -1 for all, otherwise 0 or 1. + :type uv_index: integer + :arg uv_index_from: optional uv index to copy from, -1 to transform the current uv. + :type uv_index_from: integer + .. class:: SCA_MouseSensor(SCA_ISensor) Mouse Sensor logic brick. @@ -2156,6 +2270,52 @@ Types :type: list of strings + +.. class:: KX_FontObject(KX_GameObject) + + TODO. + + +.. class:: KX_NavMeshObject(KX_GameObject) + + Python interface for using and controlling navigation meshes. + + .. method:: findPath(start, goal) + + Finds the path from start to goal points. + + :arg start: the start point + :arg start: 3D Vector + :arg goal: the goal point + :arg start: 3D Vector + :return: a path as a list of points + :rtype: list of points + + .. method:: raycast(start, goal) + + Raycast from start to goal points. + + :arg start: the start point + :arg start: 3D Vector + :arg goal: the goal point + :arg start: 3D Vector + :return: the hit factor + :rtype: float + + .. method:: draw(mode) + + Draws a debug mesh for the navigation mesh. + + :arg mode: the drawing mode (one of :ref:`these constants `) + :arg mode: integer + :return: None + + .. method:: rebuild() + + Rebuild the navigation mesh. + + :return: None + .. class:: KX_ObjectActuator(SCA_IActuator) The object actuator ("Motion Actuator") applies force, torque, displacement, angular displacement, @@ -2309,49 +2469,6 @@ Types :type: boolean -.. class:: KX_PhysicsObjectWrapper(PyObjectPlus) - - KX_PhysicsObjectWrapper - - .. method:: setActive(active) - - Set the object to be active. - - :arg active: set to True to be active - :type active: boolean - - .. method:: setAngularVelocity(x, y, z, local) - - Set the angular velocity of the object. - - :arg x: angular velocity for the x-axis - :type x: float - - :arg y: angular velocity for the y-axis - :type y: float - - :arg z: angular velocity for the z-axis - :type z: float - - :arg local: set to True for local axis - :type local: boolean - - .. method:: setLinearVelocity(x, y, z, local) - - Set the linear velocity of the object. - - :arg x: linear velocity for the x-axis - :type x: float - - :arg y: linear velocity for the y-axis - :type y: float - - :arg z: linear velocity for the z-axis - :type z: float - - :arg local: set to True for local axis - :type local: boolean - .. class:: KX_PolyProxy(SCA_IObject) A polygon holds the index of the vertex forming the poylgon. @@ -2360,7 +2477,7 @@ Types The polygon attributes are read-only, you need to retrieve the vertex proxy if you want to change the vertex settings. - .. attribute:: matname + .. attribute:: material_name The name of polygon material, empty if no material. @@ -2372,13 +2489,13 @@ Types :type: :class:`KX_PolygonMaterial` or :class:`KX_BlenderMaterial` - .. attribute:: texture + .. attribute:: texture_name The texture name of the polygon. :type: string - .. attribute:: matid + .. attribute:: material_id The material index of the polygon, use this to retrieve vertex proxy from mesh proxy. @@ -2609,18 +2726,6 @@ Types :type: boolean - .. attribute:: lightlayer - - Light layers this material affects. - - :type: bitfield. - - .. attribute:: triangle - - Mesh data with this material is triangles. It's probably not safe to change this. - - :type: boolean - .. attribute:: diffuse The diffuse color of the material. black = [0.0, 0.0, 0.0] white = [1.0, 1.0, 1.0]. @@ -2886,8 +2991,8 @@ Types .. method:: instantAddObject() adds the object without needing to calling SCA_PythonController.activate() - - .. note:: Use objectLastCreated to get the newly created object. + + .. note:: Use objectLastCreated to get the newly created object. .. class:: KX_SCA_DynamicActuator(SCA_IActuator) @@ -3113,6 +3218,12 @@ Types :type: list + .. attribute:: gravity + + The scene gravity using the world x, y and z axis. + + :type: list [fx, fy, fz] + .. method:: addObject(object, other, time=0) Adds an object to the scene like the Add Object Actuator would. @@ -3154,6 +3265,10 @@ Types Return the value matching key, or the default value if its not found. :return: The key value or a default. + .. method:: drawObstacleSimulation() + + Draw debug visualization of obstacle simulation. + .. class:: KX_SceneActuator(SCA_IActuator) Scene Actuator logic brick. @@ -3200,13 +3315,7 @@ Types Sound Actuator. - The :data:`startSound`, :data:`pauseSound` and :data:`stopSound` do not requirethe actuator to be activated - they act instantly provided that the actuator has been activated once at least. - - .. attribute:: fileName - - The filename of the sound this actuator plays. - - :type: string + The :data:`startSound`, :data:`pauseSound` and :data:`stopSound` do not require the actuator to be activated - they act instantly provided that the actuator has been activated once at least. .. attribute:: volume @@ -3214,48 +3323,102 @@ Types :type: float + .. attribute:: time + + The current position in the audio stream (in seconds). + + :type: float + .. attribute:: pitch The pitch of the sound. :type: float - .. attribute:: rollOffFactor - - The roll off factor. Rolloff defines the rate of attenuation as the sound gets further away. - - :type: float - - .. attribute:: looping - - The loop mode of the actuator. - - :type: integer - - .. attribute:: position - - The position of the sound as a list: [x, y, z]. - - :type: float array - - .. attribute:: velocity - - The velocity of the emitter as a list: [x, y, z]. The relative velocity to the observer determines the pitch. List of 3 floats: [x, y, z]. - - :type: float array - - .. attribute:: orientation - - The orientation of the sound. When setting the orientation you can also use quaternion [float, float, float, float] or euler angles [float, float, float]. - - :type: 3x3 matrix [[float]] - .. attribute:: mode The operation mode of the actuator. Can be one of :ref:`these constants` :type: integer + .. attribute:: sound + + The sound the actuator should play. + + :type: Audaspace factory + + .. attribute:: is3D + + Whether or not the actuator should be using 3D sound. (read-only) + + :type: boolean + + .. attribute:: volume_maximum + + The maximum gain of the sound, no matter how near it is. + + :type: float + + .. attribute:: volume_minimum + + The minimum gain of the sound, no matter how far it is away. + + :type: float + + .. attribute:: distance_reference + + The distance where the sound has a gain of 1.0. + + :type: float + + .. attribute:: distance_maximum + + The maximum distance at which you can hear the sound. + + :type: float + + .. attribute:: attenuation + + The influence factor on volume depending on distance. + + :type: float + + .. attribute:: cone_angle_inner + + The angle of the inner cone. + + :type: float + + .. attribute:: cone_angle_outer + + The angle of the outer cone. + + :type: float + + .. attribute:: cone_volume_outer + + The gain outside the outer cone (the gain in the outer cone will be interpolated between this value and the normal gain in the inner cone). + + :type: float + + .. method:: startSound() + + Starts the sound. + + :return: None + + .. method:: pauseSound() + + Pauses the sound. + + :return: None + + .. method:: stopSound() + + Stops the sound. + + :return: None + .. class:: KX_StateActuator(SCA_IActuator) State actuator changes the state mask of parent object. @@ -3472,7 +3635,7 @@ Types Whether or not the character is on the ground. (read-only) - :type: boolean + :type: boolean .. attribute:: gravity @@ -3518,10 +3681,6 @@ Types Black = [0.0, 0.0, 0.0, 1.0], White = [1.0, 1.0, 1.0, 1.0] - .. attribute:: colour - - Synonym for color. - .. attribute:: x The x coordinate of the vertex. @@ -4242,24 +4401,6 @@ Types :type: integer - .. method:: setSeed(seed) - - Sets the seed of the random number generator. - - If the seed is 0, the generator will produce the same value on every call. - - :type seed: integer - - .. method:: getSeed() - - :return: The initial seed of the generator. Equal seeds produce equal random series. - :rtype: integer - - .. method:: getLastDraw() - - :return: The last random number generated. - :rtype: integer - .. class:: SCA_XNORController(SCA_IController) An XNOR controller activates when all linked sensors are the same (activated or inative). @@ -4327,7 +4468,7 @@ Types .. attribute:: projection_matrix This camera's 4x4 projection matrix. - + .. note:: This is the identity matrix prior to rendering the first frame (any Python done on frame 1). @@ -4580,48 +4721,6 @@ Types Armature Actuators change constraint condition on armatures. - .. _armatureactuator-constants-type: - - Constants related to :data:`~bge.types.BL_ArmatureActuator.type` - - .. data:: KX_ACT_ARMATURE_RUN - - Just make sure the armature will be updated on the next graphic frame. - This is the only persistent mode of the actuator: - it executes automatically once per frame until stopped by a controller - - :value: 0 - - .. data:: KX_ACT_ARMATURE_ENABLE - - Enable the constraint. - - :value: 1 - - .. data:: KX_ACT_ARMATURE_DISABLE - - Disable the constraint (runtime constraint values are not updated). - - :value: 2 - - .. data:: KX_ACT_ARMATURE_SETTARGET - - Change target and subtarget of constraint. - - :value: 3 - - .. data:: KX_ACT_ARMATURE_SETWEIGHT - - Change weight of constraint (IK only). - - :value: 4 - - .. data:: KX_ACT_ARMATURE_SETINFLUENCE - - Change influence of constraint. - - :value: 5 - .. attribute:: type The type of action that the actuator executes when it is active. @@ -4676,40 +4775,6 @@ Types Armature sensor detect conditions on armatures. - .. _armaturesensor-type: - - Constants related to :data:`type` - - .. data:: KX_ARMSENSOR_STATE_CHANGED - - Detect that the constraint is changing state (active/inactive) - - :value: 0 - - .. data:: KX_ARMSENSOR_LIN_ERROR_BELOW - - Detect that the constraint linear error is above a threshold - - :value: 1 - - .. data:: KX_ARMSENSOR_LIN_ERROR_ABOVE - - Detect that the constraint linear error is below a threshold - - :value: 2 - - .. data:: KX_ARMSENSOR_ROT_ERROR_BELOW - - Detect that the constraint rotation error is above a threshold - - :value: 3 - - .. data:: KX_ARMSENSOR_ROT_ERROR_ABOVE - - Detect that the constraint rotation error is below a threshold - - :value: 4 - .. attribute:: type The type of measurement that the sensor make when it is active. @@ -4744,87 +4809,6 @@ Types Not all armature constraints are supported in the GE. - .. _armatureconstraint-constants-type: - - Constants related to :data:`type` - - .. data:: CONSTRAINT_TYPE_TRACKTO - .. data:: CONSTRAINT_TYPE_KINEMATIC - .. data:: CONSTRAINT_TYPE_ROTLIKE - .. data:: CONSTRAINT_TYPE_LOCLIKE - .. data:: CONSTRAINT_TYPE_MINMAX - .. data:: CONSTRAINT_TYPE_SIZELIKE - .. data:: CONSTRAINT_TYPE_LOCKTRACK - .. data:: CONSTRAINT_TYPE_STRETCHTO - .. data:: CONSTRAINT_TYPE_CLAMPTO - .. data:: CONSTRAINT_TYPE_TRANSFORM - .. data:: CONSTRAINT_TYPE_DISTLIMIT - - .. _armatureconstraint-constants-ik-type: - - Constants related to :data:`ik_type` - - .. data:: CONSTRAINT_IK_COPYPOSE - - constraint is trying to match the position and eventually the rotation of the target. - - :value: 0 - - .. data:: CONSTRAINT_IK_DISTANCE - - Constraint is maintaining a certain distance to target subject to ik_mode - - :value: 1 - - .. _armatureconstraint-constants-ik-flag: - - Constants related to :data:`ik_flag` - - .. data:: CONSTRAINT_IK_FLAG_TIP - - Set when the constraint operates on the head of the bone and not the tail - - :value: 1 - - .. data:: CONSTRAINT_IK_FLAG_ROT - - Set when the constraint tries to match the orientation of the target - - :value: 2 - - .. data:: CONSTRAINT_IK_FLAG_STRETCH - - Set when the armature is allowed to stretch (only the bones with stretch factor > 0.0) - - :value: 16 - - .. data:: CONSTRAINT_IK_FLAG_POS - - Set when the constraint tries to match the position of the target. - - :value: 32 - - .. _armatureconstraint-constants-ik-mode: - - Constants related to :data:`ik_mode` - - .. data:: CONSTRAINT_IK_MODE_INSIDE - - The constraint tries to keep the bone within ik_dist of target - - :value: 0 - - .. data:: CONSTRAINT_IK_MODE_OUTSIDE - - The constraint tries to keep the bone outside ik_dist of the target - - :value: 1 - - .. data:: CONSTRAINT_IK_MODE_ONSURFACE - - The constraint tries to keep the bone exactly at ik_dist of the target. - - :value: 2 .. attribute:: type @@ -4943,16 +4927,6 @@ Types Proxy to armature pose channel. Allows to read and set armature pose. The attributes are identical to RNA attributes, but mostly in read-only mode. - See :data:`rotation_mode` - - .. data:: PCHAN_ROT_QUAT - .. data:: PCHAN_ROT_XYZ - .. data:: PCHAN_ROT_XZY - .. data:: PCHAN_ROT_YXZ - .. data:: PCHAN_ROT_YZX - .. data:: PCHAN_ROT_ZXY - .. data:: PCHAN_ROT_ZYX - .. attribute:: name channel name (=bone name), read-only. @@ -5086,17 +5060,7 @@ Types Method of updating the bone rotation, read-write. - :type: integer - - Use the following constants (euler mode are named as in Blender UI but the actual axis order is reversed). - - * PCHAN_ROT_QUAT(0) : use quaternioin in rotation attribute to update bone rotation - * PCHAN_ROT_XYZ(1) : use euler_rotation and apply angles on bone's Z, Y, X axis successively - * PCHAN_ROT_XZY(2) : use euler_rotation and apply angles on bone's Y, Z, X axis successively - * PCHAN_ROT_YXZ(3) : use euler_rotation and apply angles on bone's Z, X, Y axis successively - * PCHAN_ROT_YZX(4) : use euler_rotation and apply angles on bone's X, Z, Y axis successively - * PCHAN_ROT_ZXY(5) : use euler_rotation and apply angles on bone's Y, X, Z axis successively - * PCHAN_ROT_ZYX(6) : use euler_rotation and apply angles on bone's X, Y, Z axis successively + :type: integer (one of :ref:`these constants `) .. attribute:: channel_matrix diff --git a/doc/python_api/rst/bgl.rst b/doc/python_api/rst/bgl.rst index 9f7817c6fa2..fc4524b1213 100644 --- a/doc/python_api/rst/bgl.rst +++ b/doc/python_api/rst/bgl.rst @@ -689,7 +689,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. Return the specified pixel map - .. seealso:: `OpenGL Docs `_ + .. seealso:: `OpenGL Docs `_ :type map: Enumerated constant :arg map: Specifies the name of the pixel map to return. @@ -701,7 +701,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. Return the polygon stipple pattern - .. seealso:: `OpenGL Docs `_ + .. seealso:: `OpenGL Docs `_ :type mask: :class:`bgl.Buffer` object I{type GL_BYTE} :arg mask: Returns the stipple pattern. The initial value is all 1's. @@ -824,13 +824,25 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. Set the current color index - .. seealso:: `OpenGL Docs `_ + .. seealso:: `OpenGL Docs `_ :type c: :class:`bgl.Buffer` object. Depends on function prototype. :arg c: Specifies a pointer to a one element array that contains the new value for the current color index. +.. function:: glIndexMask(mask): + + Control the writing of individual bits in the color index buffers + + .. seealso:: `OpenGL Docs `_ + + :type mask: int + :arg mask: Specifies a bit mask to enable and disable the writing of individual bits + in the color index buffers. + Initially, the mask is all 1's. + + .. function:: glInitNames(): Initialize the name stack @@ -1510,7 +1522,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. :arg mode: Specifies a symbolic value representing a shading technique. -.. function:: glStencilFuc(func, ref, mask): +.. function:: glStencilFunc(func, ref, mask): Set function and reference value for stencil testing @@ -1835,7 +1847,238 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. :arg objx, objy, objz: Return the computed object coordinates. -class Buffer: +.. function:: glUseProgram(program): + + Installs a program object as part of current rendering state + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the handle of the program object whose executables are to be used as part of current rendering state. + + +.. function:: glValidateProgram(program): + + Validates a program object + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the handle of the program object to be validated. + + +.. function:: glLinkProgram(program): + + Links a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the handle of the program object to be linked. + + +.. function:: glActiveTexture(texture): + + Select active texture unit. + + .. seealso:: `OpenGL Docs `_ + + :type texture: int + :arg texture: Constant in ``GL_TEXTURE0`` 0 - 8 + + +.. function:: glAttachShader(program, shader): + + Attaches a shader object to a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object to which a shader object will be attached. + :type shader: int + :arg shader: Specifies the shader object that is to be attached. + + +.. function:: glCompileShader(shader): + + Compiles a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the shader object to be compiled. + + +.. function:: glCreateProgram(): + + Creates a program object + + .. seealso:: `OpenGL Docs `_ + + :rtype: int + :return: The new program or zero if an error occurs. + + +.. function:: glCreateShader(shaderType): + + Creates a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shaderType: Specifies the type of shader to be created. + Must be one of ``GL_VERTEX_SHADER``, + ``GL_TESS_CONTROL_SHADER``, + ``GL_TESS_EVALUATION_SHADER``, + ``GL_GEOMETRY_SHADER``, + or ``GL_FRAGMENT_SHADER``. + :arg shaderType: + :rtype: int + :return: 0 if an error occurs. + + +.. function:: glDeleteProgram(program): + + Deletes a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object to be deleted. + + +.. function:: glDeleteShader(shader): + + Deletes a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the shader object to be deleted. + + +.. function:: glDetachShader(program, shader): + + Detaches a shader object from a program object to which it is attached. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object from which to detach the shader object. + :type shader: int + :arg shader: pecifies the program object from which to detach the shader object. + + +.. function:: glGetAttachedShaders(program, maxCount, count, shaders): + + Returns the handles of the shader objects attached to a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object to be queried. + :type maxCount: int + :arg maxCount: Specifies the size of the array for storing the returned object names. + :type count: :class:`bgl.Buffer` int buffer. + :arg count: Returns the number of names actually returned in objects. + :type shaders: :class:`bgl.Buffer` int buffer. + :arg shaders: Specifies an array that is used to return the names of attached shader objects. + + +.. function:: glGetProgramInfoLog(program, maxLength, length, infoLog): + + Returns the information log for a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object whose information log is to be queried. + :type maxLength: int + :arg maxLength: Specifies the size of the character buffer for storing the returned information log. + :type length: :class:`bgl.Buffer` int buffer. + :arg length: Returns the length of the string returned in **infoLog** (excluding the null terminator). + :type infoLog: :class:`bgl.Buffer` char buffer. + :arg infoLog: Specifies an array of characters that is used to return the information log. + + +.. function:: glGetShaderInfoLog(program, maxLength, length, infoLog): + + Returns the information log for a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the shader object whose information log is to be queried. + :type maxLength: int + :arg maxLength: Specifies the size of the character buffer for storing the returned information log. + :type length: :class:`bgl.Buffer` int buffer. + :arg length: Returns the length of the string returned in **infoLog** (excluding the null terminator). + :type infoLog: :class:`bgl.Buffer` char buffer. + :arg infoLog: Specifies an array of characters that is used to return the information log. + + +.. function:: glGetProgramiv(program, pname, params): + + Returns a parameter from a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object to be queried. + :type pname: int + :arg pname: Specifies the object parameter. + :type params: :class:`bgl.Buffer` int buffer. + :arg params: Returns the requested object parameter. + + +.. function:: glIsShader(shader): + + Determines if a name corresponds to a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies a potential shader object. + + +.. function:: glIsProgram(program): + + Determines if a name corresponds to a program object + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies a potential program object. + + +.. function:: glGetShaderSource(shader, bufSize, length, source): + + Returns the source code string from a shader object + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the shader object to be queried. + :type bufSize: int + :arg bufSize: Specifies the size of the character buffer for storing the returned source code string. + :type length: :class:`bgl.Buffer` int buffer. + :arg length: Returns the length of the string returned in source (excluding the null terminator). + :type source: :class:`bgl.Buffer` char. + :arg source: Specifies an array of characters that is used to return the source code string. + + +.. function:: glShaderSource(shader, shader_string): + + Replaces the source code in a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the handle of the shader object whose source code is to be replaced. + :type shader_string: string + :arg shader_string: The shader string. + + +.. class:: Buffer The Buffer object is simply a block of memory that is delineated and initialized by the user. Many OpenGL functions return data to a C-style pointer, however, because this diff --git a/doc/python_api/rst/gpu.rst b/doc/python_api/rst/gpu.rst index 68dc30b6143..a225829b3e8 100644 --- a/doc/python_api/rst/gpu.rst +++ b/doc/python_api/rst/gpu.rst @@ -262,10 +262,16 @@ The calculation of some of the uniforms is based on matrices available in the sc .. data:: GPU_DYNAMIC_SAMPLER_2DSHADOW + The uniform is an float representing the bumpmap scaling. + + :value: 14 + +.. data:: GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE + The uniform is an integer representing a shadow buffer corresponding to a lamp casting shadow. - :value: 14 + :value: 15 GLSL attribute type diff --git a/doc/python_api/rst/include__bmesh.rst b/doc/python_api/rst/include__bmesh.rst index a55bf71b60f..ef4a1c272b4 100644 --- a/doc/python_api/rst/include__bmesh.rst +++ b/doc/python_api/rst/include__bmesh.rst @@ -4,6 +4,13 @@ ./blender.bin -b -noaudio -P doc/python_api/sphinx_doc_gen.py -- --partial bmesh* ; cd doc/python_api ; sphinx-build sphinx-in sphinx-out ; cd ../../ +Submodules: + +* :mod:`bmesh.ops` +* :mod:`bmesh.types` +* :mod:`bmesh.utils` + + Intro ----- @@ -35,7 +42,6 @@ For an overview of BMesh data types and how they reference each other see: TODO items are... * add access to BMesh **walkers** - * add api for calling BMesh operators (unrelated to bpy.ops) * add custom-data manipulation functions add/remove/rename. Example Script diff --git a/doc/python_api/rst/info_api_reference.rst b/doc/python_api/rst/info_api_reference.rst new file mode 100644 index 00000000000..ddee46dce11 --- /dev/null +++ b/doc/python_api/rst/info_api_reference.rst @@ -0,0 +1,305 @@ + +******************* +Reference API Usage +******************* + +Blender has many interlinking data types which have an auto-generated reference api which often has the information +you need to write a script, but can be difficult to use. + +This document is designed to help you understand how to use the reference api. + + +Reference API Scope +=================== + +The reference API covers :mod:`bpy.types`, which stores types accessed via :mod:`bpy.context` - *The user context* +or :mod:`bpy.data` - *Blend file data*. + +Other modules such as :mod:`bge`, :mod:`bmesh` and :mod:`aud` are not using Blenders data API +so this document doesn't apply to those modules. + + +Data Access +=========== + +The most common case for using the reference API is to find out how to access data in the blend file. + +Before going any further its best to be aware of ID Data-Blocks in Blender since you will often find properties +relative to them. + + +ID Data +------- + +ID Data-Blocks are used in Blender as top-level data containers. + +From the user interface this isn't so obvious, but when developing you need to know about ID Data-Blocks. + +ID data types include Scene, Group, Object, Mesh, Screen, World, Armature, Image and Texture. +for a full list see the sub-classes of :class:`bpy.types.ID` + +Here are some characteristics ID Data-Blocks share. + +- ID's are blend file data, so loading a new blend file reloads an entire new set of Data-Blocks. +- ID's can be accessed in Python from ``bpy.data.*`` +- Each data-block has a unique ``.name`` attribute, displayed in the interface. +- Animation data is stored in ID's ``.animation_data``. +- ID's are the only data types that can be linked between blend files. +- ID's can be added/copied and removed via Python. +- ID's have their own garbage-collection system which frees unused ID's when saving. +- When a data-block has a reference to some external data, this is typically an ID Data-Block. + + +Simple Data Access +------------------ + +Lets start with a simple case, say you wan't a python script to adjust the objects location. + +Start by finding this setting in the interface ``Properties Window -> Object -> Transform -> Location`` + +From the button you can right click and select **Online Python Reference**, this will link you to: +:class:`bpy.types.Object.location` + +Being an API reference, this link often gives little more information then the tool-tip, though some of the pages +include examples (normally at the top of the page). + +At this point you may say *Now what?* - you know that you have to use ``.location`` and that its an array of 3 floats +but you're still left wondering how to access this in a script. + +So the next step is to find out where to access objects, go down to the bottom of the page to the **References** +section, for objects there are many references, but one of the most common places to access objects is via the context. + +It's easy to be overwhelmed at this point since there ``Object`` get referenced in so many places - modifiers, +functions, textures and constraints. + +But if you want to access any data the user has selected +you typically only need to check the :mod:`bpy.context` references. + +Even then, in this case there are quite a few though if you read over these - most are mode specific. +If you happen to be writing a tool that only runs in weight paint mode, then using ``weight_paint_object`` +would be appropriate. +However to access an item the user last selected, look for the ``active`` members, +Having access to a single active member the user selects is a convention in Blender: eg. ``active_bone``, +``active_pose_bone``, ``active_node`` ... and in this case we can use - ``active_object``. + + +So now we have enough information to find the location of the active object. + +.. code-block:: python + + bpy.context.active_object.location + +You can type this into the python console to see the result. + +The other common place to access objects in the reference is :class:`bpy.types.BlendData.objects`. + +.. note:: + + This is **not** listed as :mod:`bpy.data.objects`, + this is because :mod:`bpy.data` is an instance of the :class:`bpy.types.BlendData` class, + so the documentation points there. + + +With :mod:`bpy.data.objects`, this is a collection of objects so you need to access one of its members. + +.. code-block:: python + + bpy.data.objects["Cube"].location + + +Nested Properties +----------------- + +The previous example is quite straightforward because ``location`` is a property of ``Object`` which can be accessed +from the context directly. + +Here are some more complex examples: + +.. code-block:: python + + # access a render layers samples + bpy.context.scene.render.layers["RenderLayer"].samples + + # access to the current weight paint brush size + bpy.context.tool_settings.weight_paint.brush.size + + # check if the window is fullscreen + bpy.context.window.screen.show_fullscreen + + +As you can see there are times when you want to access data which is nested +in a way that causes you to go through a few indirections. + +The properties are arranged to match how data is stored internally (in blenders C code) which is often logical but +not always quite what you would expect from using Blender. + +So this takes some time to learn, it helps you understand how data fits together in Blender which is important +to know when writing scripts. + + +When starting out scripting you will often run into the problem where you're not sure how to access the data you want. + +There are a few ways to do this. + +- Use the Python console's auto-complete to inspect properties. *This can be hit-and-miss but has the advantage + that you can easily see the values of properties and assign them to interactively see the results.* + +- Copy the Data-Path from the user interface. *Explained further in :ref:`Copy Data Path `* + +- Using the documentation to follow references. *Explained further in :ref:`Indirect Data Access `* + + +.. _info_data_path_copy + +Copy Data Path +-------------- + +Blender can compute the Python string to a property which is shown in the tool-tip, on the line below ``Python: ...``, +This saves having to use the API reference to click back up the references to find where data is accessed from. + +There is a user-interface feature to copy the data-path which gives the path from an :class:`bpy.types.ID` data-block, +to its property. + +To see how this works we'll get the path to the Subdivision-Surface modifiers subdivision setting. + +Start with the default scene and select the **Modifiers** tab, then add a **Subdivision-Surface** modifier to the cube. + +Now hover your mouse over the button labeled **View**, The tool-tip includes :class:`bpy.types.SubsurfModifier.levels` +but we want the path from the object to this property. + +Note that the text copied won't include the ``bpy.data.collection["name"].`` component since its assumed that +you won't be doing collection look-ups on every access and typically you'll want to use the context rather +then access each :class:`bpy.types.ID` instance by name. + + +Type in the ID path into a Python console :mod:`bpy.context.active_object`. Include the trailing dot and don't hit "enter", yet. + +Now right-click on the button and select **Copy Data Path**, then paste the result into the console. + +So now you should have the answer: + +.. code-block:: python + + bpy.context.active_object.modifiers["Subsurf"].levels + +Hit "enter" and you'll get the current value of 1. Now try changing the value to 2: + +.. code-block:: python + + bpy.context.active_object.modifiers["Subsurf"].levels = 2 + +You can see the value update in the Subdivision-Surface modifier's UI as well as the cube. + + +.. _info_data_path_indirect + +Indirect Data Access +-------------------- + +For this example we'll go over something more involved, showing the steps to access the active sculpt brushes texture. + +Lets say we want to access the texture of a brush via Python, to adjust its ``contrast`` for example. + +- Start in the default scene and enable 'Sculpt' mode from the 3D-View header. + +- From the toolbar expand the **Texture** panel and add a new texture. + + *Notice the texture button its self doesn't have very useful links (you can check the tool-tips).* + +- The contrast setting isn't exposed in the sculpt toolbar, so view the texture in the properties panel... + + - In the properties button select the Texture context. + + - Select the Brush icon to show the brush texture. + + - Expand the **Colors** panel to locate the **Contrast** button. + +- Right click on the contrast button and select **Online Python Reference** This takes you to ``bpy.types.Texture.contrast`` + +- Now we can see that ``contrast`` is a property of texture, so next we'll check on how to access the texture from the brush. + +- Check on the **References** at the bottom of the page, sometimes there are many references, and it may take + some guess work to find the right one, but in this case its obviously ``Brush.texture``. + + *Now we know that the texture can be accessed from* ``bpy.data.brushes["BrushName"].texture`` + *but normally you won't want to access the brush by name, so we'll see now to access the active brush instead.* + +- So the next step is to check on where brushes are accessed from via the **References**. + In this case there is simply ``bpy.context.brush`` which is all we need. + + +Now you can use the Python console to form the nested properties needed to access brush textures contrast, +logically we now know. + +*Context -> Brush -> Texture -> Contrast* + +Since the attribute for each is given along the way we can compose the data path in the python console: + +.. code-block:: python + + bpy.context.brush.texture.contrast + + +There can be multiple ways to access the same data, which you choose often depends on the task. + +An alternate path to access the same setting is... + +.. code-block:: python + + bpy.context.sculpt.brush.texture.contrast + +Or access the brush directly... + +.. code-block:: python + + bpy.data.brushes["BrushName"].texture.contrast + + +If you are writing a user tool normally you want to use the :mod:`bpy.context` since the user normally expects +the tool to operate on what they have selected. + +For automation you are more likely to use :mod:`bpy.data` since you want to be able to access specific data and manipulate +it, no matter what the user currently has the view set at. + + +Operators +========= + +Most key-strokes and buttons in Blender call an operator which is also exposed to python via :mod:`bpy.ops`, + +To see the Python equivalent hover your mouse over the button and see the tool-tip, +eg ``Python: bpy.ops.render.render()``, +If there is no tool-tip or the ``Python:`` line is missing then this button is not using an operator and +can't be accessed from Python. + + +If you want to use this in a script you can press :kbd:`Control-C` while your mouse is over the button to copy it to the +clipboard. + +You can also right click on the button and view the **Online Python Reference**, this mainly shows arguments and +their defaults however operators written in Python show their file and line number which may be useful if you +are interested to check on the source code. + +.. note:: + + Not all operators can be called usefully from Python, for more on this see :ref:`using operators `. + + +Info View +--------- + +Blender records operators you run and displays them in the **Info** space. +This is located above the file-menu which can be dragged down to display its contents. + +Select the **Script** screen that comes default with Blender to see its output. +You can perform some actions and see them show up - delete a vertex for example. + +Each entry can be selected (Right-Mouse-Button), then copied :kbd:`Control-C`, usually to paste in the text editor or python console. + +.. note:: + + Not all operators get registered for display, + zooming the view for example isn't so useful to repeat so its excluded from the output. + + To display *every* operator that runs see :ref:`Show All Operators ` + diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst index 1d561216b52..34145c2ac49 100644 --- a/doc/python_api/rst/info_gotcha.rst +++ b/doc/python_api/rst/info_gotcha.rst @@ -5,6 +5,8 @@ Gotchas This document attempts to help you work with the Blender API in areas that can be troublesome and avoid practices that are known to give instability. +.. _using_operators: + Using Operators =============== @@ -118,18 +120,19 @@ If you insist - yes its possible, but scripts that use this hack wont be conside bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) -I can't edit the mesh in edit-mode! -=================================== +Modes and Mesh Access +===================== -Blender's EditMesh is an internal data structure (not saved and not exposed to python), this gives the main annoyance that you need to exit edit-mode to edit the mesh from python. +When working with mesh data you may run into the problem where a script fails to run as expected in edit-mode. This is caused by edit-mode having its own data which is only written back to the mesh when exiting edit-mode. -The reason we have not made much attempt to fix this yet is because we -will likely move to BMesh mesh API eventually, so any work on the API now will be wasted effort. +A common example is that exporters may access a mesh through ``obj.data`` (a :class:`bpy.types.Mesh`) but the user is in edit-mode, where the mesh data is available but out of sync with the edit mesh. -With the BMesh API we may expose mesh data to python so we can -write useful tools in python which are also fast to execute while in edit-mode. +In this situation you can... -For the time being this limitation just has to be worked around but we're aware its frustrating needs to be addressed. +* Exit edit-mode before running the tool. +* Explicitly update the mesh by calling :class:`bmesh.types.BMesh.to_mesh`. +* Modify the script to support working on the edit-mode data directly, see: :mod:`bmesh.from_edit_mesh`. +* Report the context as incorrect and only allow the script to run outside edit-mode. .. _info_gotcha_mesh_faces: @@ -311,7 +314,7 @@ Naming Limitations A common mistake is to assume newly created data is given the requested name. -This can cause bugs when you add some data (normally imported) and then reference it later by name. +This can cause bugs when you add some data (normally imported) then reference it later by name. .. code-block:: python @@ -493,7 +496,7 @@ Heres an example of threading supported by Blender: t.join() -This an example of a timer which runs many times a second and moves the default cube continuously while Blender runs (Unsupported). +This an example of a timer which runs many times a second and moves the default cube continuously while Blender runs **(Unsupported)**. .. code-block:: python @@ -516,7 +519,7 @@ So far, no work has gone into making Blender's python integration thread safe, s .. note:: - Pythons threads only allow co-currency and won't speed up your scripts on multi-processor systems, the ``subprocess`` and ``multiprocess`` modules can be used with blender and make use of multiple CPU's too. + Pythons threads only allow co-currency and won't speed up your scripts on multi-processor systems, the ``subprocess`` and ``multiprocess`` modules can be used with Blender and make use of multiple CPU's too. Help! My script crashes Blender @@ -536,11 +539,18 @@ Here are some general hints to avoid running into these problems. * Crashes may not happen every time, they may happen more on some configurations/operating-systems. +.. note:: + + To find the line of your script that crashes you can use the ``faulthandler`` module. + See `faulthandler docs `_. + + While the crash may be in Blenders C/C++ code, this can help a lot to track down the area of the script that causes the crash. + Undo/Redo --------- -Undo invalidates all :class:`bpy.types.ID` instances (Object, Scene, Mesh etc). +Undo invalidates all :class:`bpy.types.ID` instances (Object, Scene, Mesh, Lamp... etc). This example shows how you can tell undo changes the memory locations. @@ -557,6 +567,21 @@ This example shows how you can tell undo changes the memory locations. As suggested above, simply not holding references to data when Blender is used interactively by the user is the only way to ensure the script doesn't become unstable. +Undo & Library Data +^^^^^^^^^^^^^^^^^^^ + +One of the advantages with Blenders library linking system that undo can skip checking changes in library data since it is assumed to be static. + +Tools in Blender are not allowed to modify library data. + +Python however does not enforce this restriction. + +This can be useful in some cases, using a script to adjust material values for example. +But its also possible to use a script to make library data point to newly created local data, which is not supported since a call to undo will remove the local data but leave the library referencing it and likely crash. + +So it's best to consider modifying library data an advanced usage of the API and only to use it when you know what you're doing. + + Edit Mode / Memory Access ------------------------- @@ -616,15 +641,36 @@ Removing Data **Any** data that you remove shouldn't be modified or accessed afterwards, this includes f-curves, drivers, render layers, timeline markers, modifiers, constraints along with objects, scenes, groups, bones.. etc. -This is a problem in the API at the moment that we should eventually solve. +The ``remove()`` api calls will invalidate the data they free to prevent common mistakes. + +The following example shows how this precortion works. + +.. code-block:: python + + mesh = bpy.data.meshes.new(name="MyMesh") + # normally the script would use the mesh here... + bpy.data.meshes.remove(mesh) + print(mesh.name) # <- give an exception rather then crashing: + + # ReferenceError: StructRNA of type Mesh has been removed + + +But take care because this is limited to scripts accessing the variable which is removed, the next example will still crash. + +.. code-block:: python + + mesh = bpy.data.meshes.new(name="MyMesh") + vertices = mesh.vertices + bpy.data.meshes.remove(mesh) + print(vertices) # <- this may crash sys.exit ======== -Some python modules will call sys.exit() themselves when an error occurs, while not common behavior this is something to watch out for because it may seem as if blender is crashing since sys.exit() will quit blender immediately. +Some python modules will call ``sys.exit()`` themselves when an error occurs, while not common behavior this is something to watch out for because it may seem as if blender is crashing since ``sys.exit()`` will quit blender immediately. For example, the ``optparse`` module will print an error and exit if the arguments are invalid. -An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of python code is quitting, you could of course replace ``sys.exit``/ with your own function but manipulating python in this way is bad practice. +An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of python code is quitting, you could of course replace ``sys.exit`` with your own function but manipulating python in this way is bad practice. diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst index 818eb692be9..b2d524b74af 100644 --- a/doc/python_api/rst/info_overview.rst +++ b/doc/python_api/rst/info_overview.rst @@ -1,3 +1,5 @@ +.. _info_overview: + ******************* Python API Overview ******************* diff --git a/doc/python_api/rst/info_quickstart.rst b/doc/python_api/rst/info_quickstart.rst index 62ad4e9c4d8..e1264ae9d52 100644 --- a/doc/python_api/rst/info_quickstart.rst +++ b/doc/python_api/rst/info_quickstart.rst @@ -1,3 +1,5 @@ +.. _info_quickstart: + *********************** Quickstart Introduction *********************** diff --git a/doc/python_api/rst/info_tips_and_tricks.rst b/doc/python_api/rst/info_tips_and_tricks.rst index 521031f5e61..75e8ef61f6f 100644 --- a/doc/python_api/rst/info_tips_and_tricks.rst +++ b/doc/python_api/rst/info_tips_and_tricks.rst @@ -44,15 +44,17 @@ if this can't be generated, only the property name is copied. .. note:: - This uses the same method for creating the animation path used by :class:`FCurve.data_path` and :class:`DriverTarget.data_path` drivers. + This uses the same method for creating the animation path used by :class:`bpy.types.FCurve.data_path` and :class:`bpy.types.DriverTarget.data_path` drivers. +.. _info_show_all_operators + Show All Operators ================== While blender logs operators in the Info space, this only reports operators with the ``REGISTER`` option enabeld so as not to flood the Info view with calls to ``bpy.ops.view3d.smoothview`` and ``bpy.ops.view3d.zoom``. -However, for testing it can be useful to see **every** operator called in a terminal, do this by enabling the debug option either by passing the ``--debug`` argument when starting blender or by setting :mod:`bpy.app.debug` to True while blender is running. +However, for testing it can be useful to see **every** operator called in a terminal, do this by enabling the debug option either by passing the ``--debug-wm`` argument when starting blender or by setting :mod:`bpy.app.debug_wm` to True while blender is running. Use an External Editor @@ -218,6 +220,14 @@ The next example is an equivalent single line version of the script above which ``code.interact`` can be added at any line in the script and will pause the script an launch an interactive interpreter in the terminal, when you're done you can quit the interpreter and the script will continue execution. +If you have **IPython** installed you can use their ``embed()`` function which will implicitly use the current namespace, this has autocomplete and some useful features that the standard python eval-loop doesn't have. + +.. code-block:: python + + import IPython + IPython.embed() + + Admittedly this highlights the lack of any python debugging support built into blender, but its still handy to know. .. note:: diff --git a/doc/python_api/rst/info_tutorial_addon.rst b/doc/python_api/rst/info_tutorial_addon.rst new file mode 100644 index 00000000000..2a101041227 --- /dev/null +++ b/doc/python_api/rst/info_tutorial_addon.rst @@ -0,0 +1,645 @@ + +Addon Tutorial +############## + +************ +Introduction +************ + + +Intended Audience +================= + +This tutorial is designed to help technical artists or developers learn to extend Blender. +An understanding of the basics of Python is expected for those working through this tutorial. + + +Prerequisites +------------- + +Before going through the tutorial you should... + +* Familiarity with the basics of working in Blender. + +* Know how to run a script in Blender's text editor (as documented in the quick-start) + +* Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set). + +* Be familiar with the concept of Python modules. + +* Basic understanding of classes (object orientation) in Python. + + +Suggested reading before starting this tutorial. + +* `Dive Into Python `_ sections (1, 2, 3, 4, and 7). +* :ref:`Blender API Quickstart ` + to help become familiar with Blender/Python basics. + + +To best troubleshoot any error message Python prints while writing scripts you run blender with from a terminal, +see :ref:`Use The Terminal `. + +Documentation Links +=================== + +While going through the tutorial you may want to look into our reference documentation. + +* :ref:`Blender API Overview `. - + *This document is rather detailed but helpful if you want to know more on a topic.* + +* :mod:`bpy.context` api reference. - + *Handy to have a list of available items your script may operate on.* + +* :class:`bpy.types.Operator`. - + *The following addons define operators, these docs give details and more examples of operators.* + + +****** +Addons +****** + + +What is an Addon? +================= + +An addon is simply a Python module with some additional requirements so Blender can display it in a list with useful +information. + +To give an example, here is the simplest possible addon. + + +.. code-block:: python + + bl_info = {"name": "My Test Addon", "category": "Object"} + def register(): + print("Hello World") + def unregister(): + print("Goodbye World") + + +* ``bl_info`` is a dictionary containing addon meta-data such as the title, version and author to be displayed in the + user preferences addon list. +* ``register`` is a function which only runs when enabling the addon, this means the module can be loaded without + activating the addon. +* ``unregister`` is a function to unload anything setup by ``register``, this is called when the addon is disabled. + + + +Notice this addon does not do anything related to Blender, (the :mod:`bpy` module is not imported for example). + +This is a contrived example of an addon that serves to illustrate the point +that the base requirements of an addon are simple. + +An addon will typically register operators, panels, menu items etc, but its worth noting that _any_ script can do this, +when executed from the text editor or even the interactive console - there is nothing inherently different about an +addon that allows it to integrate with Blender, such functionality is just provided by the :mod:`bpy` module for any +script to access. + +So an addon is just a way to encapsulate a Python module in a way a user can easily utilize. + +.. note:: + + Running this script within the text editor won't print anything, + to see the output it must be installed through the user preferences. + Messages will be printed when enabling and disabling. + + +Your First Addon +================ + +The simplest possible addon above was useful as an example but not much else. +This next addon is simple but shows how to integrate a script into Blender using an ``Operator`` +which is the typical way to define a tool accessed from menus, buttons and keyboard shortcuts. + +For the first example we'll make a script that simply moves all objects in a scene. + + +Write The Script +---------------- + +Add the following script to the text editor in Blender. + +.. code-block:: python + + import bpy + + scene = bpy.context.scene + for obj in scene.objects: + obj.location.x += 1.0 + + +.. image:: run_script.png + :width: 924px + :align: center + :height: 574px + :alt: Run Script button + +Click the Run Script button, all objects in the active scene are moved by 1.0 Blender unit. +Next we'll make this script into an addon. + + +Write the Addon (Simple) +------------------------ + +This addon takes the body of the script above, and adds them to an operator's ``execute()`` function. + + +.. code-block:: python + + bl_info = { + "name": "Move X Axis", + "category": "Object", + } + + import bpy + + + class ObjectMoveX(bpy.types.Operator): + """My Object Moving Script""" # blender will use this as a tooltip for menu items and buttons. + bl_idname = "object.move_x" # unique identifier for buttons and menu items to reference. + bl_label = "Move X by One" # display name in the interface. + bl_options = {'REGISTER', 'UNDO'} # enable undo for the operator. + + def execute(self, context): # execute() is called by blender when running the operator. + + # The original script + scene = context.scene + for obj in scene.objects: + obj.location.x += 1.0 + + return {'FINISHED'} # this lets blender know the operator finished successfully. + + def register(): + bpy.utils.register_class(ObjectMoveX) + + + def unregister(): + bpy.utils.unregister_class(ObjectMoveX) + + + # This allows you to run the script directly from blenders text editor + # to test the addon without having to install it. + if __name__ == "__main__": + register() + + +.. note:: ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items. + +.. note:: Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``. + In most cases these will be the same however in some cases operators will be passed a custom context + so script authors should prefer the ``context`` argument passed to operators. + + +To test the script you can copy and paste this into Blender text editor and run it, this will execute the script +directly and call register immediately. + +However running the script wont move any objects, for this you need to execute the newly registered operator. + +.. image:: spacebar.png + :width: 924px + :align: center + :height: 574px + :alt: Spacebar + +Do this by pressing ``SpaceBar`` to bring up the operator search dialog and type in "Move X by One" (the ``bl_label``), +then press ``Enter``. + + + +The objects should move as before. + +*Keep this addon open in Blender for the next step - Installing.* + +Install The Addon +----------------- + +Once you have your addon within in Blender's text editor, you will want to be able to install it so it can be enabled in +the user preferences to load on startup. + +Even though the addon above is a test, lets go through the steps anyway so you know how to do it for later. + +To install the Blender text as an addon you will first have to save it to disk, take care to obey the naming +restrictions that apply to Python modules and end with a ``.py`` extension. + +Once the file is on disk, you can install it as you would for an addon downloaded online. + +Open the user **File -> User Preferences**, Select the **Addon** section, press **Install Addon...** and select the file. + +Now the addon will be listed and you can enable it by pressing the check-box, if you want it to be enabled on restart, +press **Save as Default**. + +.. note:: + + The destination of the addon depends on your Blender configuration. + When installing an addon the source and destination path are printed in the console. + You can also find addon path locations by running this in the Python console. + + .. code-block:: python + + import addon_utils + print(addon_utils.paths()) + + More is written on this topic here: + `Directory Layout `_ + + +Your Second Addon +================= + +For our second addon, we will focus on object instancing - this is - to make linked copies of an object in a +similar way to what you may have seen with the array modifier. + + +Write The Script +---------------- + +As before, first we will start with a script, develop it, then convert into an addon. + +.. code-block:: python + + import bpy + from bpy import context + + # Get the current scene + scene = context.scene + + # Get the 3D cursor + cursor = scene.cursor_location + + # Get the active object (assume we have one) + obj = scene.objects.active + + # Now make a copy of the object + obj_new = obj.copy() + + # The object won't automatically get into a new scene + scene.objects.link(obj_new) + + # Now we can place the object + obj_new.location = cursor + + +Now try copy this script into Blender and run it on the default cube. +Make sure you click to move the 3D cursor before running as the duplicate will appear at the cursor's location. + + +... go off and test ... + + +After running, notice that when you go into edit-mode to change the cube - all of the copies change, +in Blender this is known as *Linked-Duplicates*. + + +Next, we're going to do this in a loop, to make an array of objects between the active object and the cursor. + + +.. code-block:: python + + import bpy + from bpy import context + + scene = context.scene + cursor = scene.cursor_location + obj = scene.objects.active + + # Use a fixed value for now, eventually make this user adjustable + total = 10 + + # Add 'total' objects into the scene + for i in range(total): + obj_new = obj.copy() + scene.objects.link(obj_new) + + # Now place the object in between the cursor + # and the active object based on 'i' + factor = i / total + obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor)) + + +Try run this script with with the active object and the cursor spaced apart to see the result. + +With this script you'll notice we're doing some math with the object location and cursor, this works because both are +3D :class:`mathutils.Vector` instances, a convenient class provided by the :mod:`mathutils` module and +allows vectors to be multiplied by numbers and matrices. + +If you are interested in this area, read into :class:`mathutils.Vector` - there are many handy utility functions +such as getting the angle between vectors, cross product, dot products +as well as more advanced functions in :mod:`mathutils.geometry` such as bezier spline interpolation and +ray-triangle intersection. + +For now we'll focus on making this script an addon, but its good to know that this 3D math module is available and +can help you with more advanced functionality later on. + + +Write the Addon +--------------- + +The first step is to convert the script as-is into an addon. + + +.. code-block:: python + + bl_info = { + "name": "Cursor Array", + "category": "Object", + } + + import bpy + + + class ObjectCursorArray(bpy.types.Operator): + """Object Cursor Array""" + bl_idname = "object.cursor_array" + bl_label = "Cursor Array" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self, context): + scene = context.scene + cursor = scene.cursor_location + obj = scene.objects.active + + total = 10 + + for i in range(total): + obj_new = obj.copy() + scene.objects.link(obj_new) + + factor = i / total + obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor)) + + return {'FINISHED'} + + def register(): + bpy.utils.register_class(ObjectCursorArray) + + + def unregister(): + bpy.utils.unregister_class(ObjectCursorArray) + + + if __name__ == "__main__": + register() + + +Everything here has been covered in the previous steps, you may want to try run the addon still +and consider what could be done to make it more useful. + + +... go off and test ... + + +The two of the most obvious missing things are - having the total fixed at 10, and having to access the operator from +space-bar is not very convenient. + +Both these additions are explained next, with the final script afterwards. + + +Operator Property +^^^^^^^^^^^^^^^^^ + +There are a variety of property types that are used for tool settings, common property types include: +int, float, vector, color, boolean and string. + +These properties are handled differently to typical Python class attributes +because Blender needs to be display them in the interface, +store their settings in key-maps and keep settings for re-use. + +While this is handled in a fairly Pythonic way, be mindful that you are in fact defining tool settings that +are loaded into Blender and accessed by other parts of Blender, outside of Python. + + +To get rid of the literal 10 for `total`, we'll us an operator property. +Operator properties are defined via bpy.props module, this is added to the class body. + +.. code-block:: python + + # moved assignment from execute() to the body of the class... + total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100) + + # and this is accessed on the class + # instance within the execute() function as... + self.total + + +These properties from :mod:`bpy.props` are handled specially by Blender when the class is registered +so they display as buttons in the user interface. +There are many arguments you can pass to properties to set limits, change the default and display a tooltip. + +.. seealso:: :mod:`bpy.props.IntProperty` + +This document doesn't go into details about using other property types, +however the link above includes examples of more advanced property usage. + + +Menu Item +^^^^^^^^^ + +Addons can add to the user interface of existing panels, headers and menus defined in Python. + +For this example we'll add to an existing menu. + +.. image:: menu_id.png + :width: 334px + :align: center + :height: 128px + :alt: Menu Identifier + +To find the identifier of a menu you can hover your mouse over the menu item and the identifier is displayed. + +The method used for adding a menu item is to append a draw function into an existing class. + + +.. code-block:: python + + def menu_func(self, context): + self.layout.operator(ObjectCursorArray.bl_idname) + + def register(): + bpy.types.VIEW3D_MT_object.append(menu_func) + + +For docs on extending menus see: :doc:`bpy.types.Menu`. + + +Keymap +^^^^^^ + +In Blender addons have their own key-maps so as not to interfere with Blenders built in key-maps. + +In the example below, a new object-mode :class:`bpy.types.KeyMap` is added, +then a :class:`bpy.types.KeyMapItem` is added to the key-map which references our newly added operator, +using :kbd:`Ctrl-Shift-Space` as the key shortcut to activate it. + + +.. code-block:: python + + # store keymaps here to access after registration + addon_keymaps = [] + + def register(): + + # handle the keymap + wm = bpy.context.window_manager + km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY') + + kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True) + kmi.properties.total = 4 + + addon_keymaps.append(km) + + + def unregister(): + + # handle the keymap + wm = bpy.context.window_manager + for km in addon_keymaps: + wm.keyconfigs.addon.keymaps.remove(km) + # clear the list + addon_keymaps.clear() + + +Notice how the key-map item can have a different ``total`` setting then the default set by the operator, +this allows you to have multiple keys accessing the same operator with different settings. + + +.. note:: + + While :kbd:`Ctrl-Shift-Space` isn't a default Blender key shortcut, its hard to make sure addons won't + overwrite each others keymaps, At least take care when assigning keys that they don't + conflict with important functionality within Blender. + +For API documentation on the functions listed above, see: +:class:`bpy.types.KeyMaps.new`, +:class:`bpy.types.KeyMap`, +:class:`bpy.types.KeyMapItems.new`, +:class:`bpy.types.KeyMapItem`. + + +Bringing it all together +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: python + + bl_info = { + "name": "Cursor Array", + "category": "Object", + } + + import bpy + + + class ObjectCursorArray(bpy.types.Operator): + """Object Cursor Array""" + bl_idname = "object.cursor_array" + bl_label = "Cursor Array" + bl_options = {'REGISTER', 'UNDO'} + + total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100) + + def execute(self, context): + scene = context.scene + cursor = scene.cursor_location + obj = scene.objects.active + + for i in range(self.total): + obj_new = obj.copy() + scene.objects.link(obj_new) + + factor = i / self.total + obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor)) + + return {'FINISHED'} + + + def menu_func(self, context): + self.layout.operator(ObjectCursorArray.bl_idname) + + # store keymaps here to access after registration + addon_keymaps = [] + + + def register(): + bpy.utils.register_class(ObjectCursorArray) + bpy.types.VIEW3D_MT_object.append(menu_func) + + # handle the keymap + wm = bpy.context.window_manager + km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY') + kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True) + kmi.properties.total = 4 + addon_keymaps.append(km) + + def unregister(): + bpy.utils.unregister_class(ObjectCursorArray) + bpy.types.VIEW3D_MT_object.remove(menu_func) + + # handle the keymap + wm = bpy.context.window_manager + for km in addon_keymaps: + wm.keyconfigs.addon.keymaps.remove(km) + # clear the list + del addon_keymaps[:] + + + if __name__ == "__main__": + register() + +.. image:: in_menu.png + :width: 591px + :align: center + :height: 649px + :alt: In the menu + +Run the script (or save it and add it through the Preferences like before) and it will appear in the menu. + +.. image:: op_prop.png + :width: 669px + :align: center + :height: 644px + :alt: Operator Property + +After selecting it from the menu, you can choose how many instance of the cube you want created. + + +.. note:: + + Directly executing the script multiple times will add the menu each time too. + While not useful behavior, theres nothing to worry about since addons won't register them selves multiple + times when enabled through the user preferences. + + +Conclusions +=========== + +Addons can encapsulate certain functionality neatly for writing tools to improve your work-flow or for writing utilities +for others to use. + +While there are limits to what Python can do within Blender, there is certainly a lot that can be achieved without +having to dive into Blender's C/C++ code. + +The example given in the tutorial is limited, but shows the Blender API used for common tasks that you can expand on +to write your own tools. + + +Further Reading +--------------- + +Blender comes commented templates which are accessible from the text editor header, if you have specific areas +you want to see example code for, this is a good place to start. + + +Here are some sites you might like to check on after completing this tutorial. + +* :ref:`Blender/Python API Overview ` - + *For more background details on Blender/Python integration.* + +* `How to Think Like a Computer Scientist `_ - + *Great info for those who are still learning Python.* + +* `Blender Development (Wiki) `_ - + *Blender Development, general information and helpful links.* + +* `Blender Artists (Coding Section) `_ - + *forum where people ask Python development questions* + diff --git a/doc/python_api/rst_from_bmesh_opdefines.py b/doc/python_api/rst_from_bmesh_opdefines.py new file mode 100644 index 00000000000..c1b6643389d --- /dev/null +++ b/doc/python_api/rst_from_bmesh_opdefines.py @@ -0,0 +1,380 @@ +# ##### 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 ##### + +# + +# This is a quite stupid script which extracts bmesh api docs from +# 'bmesh_opdefines.c' in order to avoid having to add a lot of introspection +# data access into the api. +# +# The script is stupid becase it makes assumptions about formatting... +# that each arg has its own line, that comments above or directly after will be __doc__ etc... +# +# We may want to replace this script with something else one day but for now its good enough. +# if it needs large updates it may be better to rewrite using a real parser or +# add introspection into bmesh.ops. +# - campbell + +import os + +CURRENT_DIR = os.path.abspath(os.path.dirname(__file__)) +SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(CURRENT_DIR, "..", "..")))) +FILE_OP_DEFINES_C = os.path.join(SOURCE_DIR, "source", "blender", "bmesh", "intern", "bmesh_opdefines.c") +OUT_RST = os.path.join(CURRENT_DIR, "rst", "bmesh.ops.rst") + +HEADER = r""" +BMesh Operators (bmesh.ops) +=========================== + +.. module:: bmesh.ops + +This module gives access to low level bmesh operations. + +Most operators take input and return output, they can be chained together +to perform useful operations. + +.. note:: + + This API us new in 2.65 and not yet well tested. + + +Operator Example +++++++++++++++++ +This script shows how operators can be used to model a link of a chain. + +.. literalinclude:: ../examples/bmesh.ops.1.py +""" + + +def main(): + fsrc = open(FILE_OP_DEFINES_C, 'r', encoding="utf-8") + + blocks = [] + + is_block = False + is_comment = False # /* global comments only */ + + comment_ctx = None + block_ctx = None + + for l in fsrc: + l = l[:-1] + # weak but ok + if ("BMOpDefine" in l and l.split()[1] == "BMOpDefine") and not "bmo_opdefines[]" in l: + is_block = True + block_ctx = [] + blocks.append((comment_ctx, block_ctx)) + elif l.strip().startswith("/*"): + is_comment = True + comment_ctx = [] + + if is_block: + if l.strip().startswith("//"): + pass + else: + # remove c++ comment if we have one + cpp_comment = l.find("//") + if cpp_comment != -1: + l = l[:cpp_comment] + + block_ctx.append(l) + + if l.strip() == "};": + is_block = False + comment_ctx = None + + if is_comment: + c_comment_start = l.find("/*") + if c_comment_start != -1: + l = l[c_comment_start + 2:] + + c_comment_end = l.find("*/") + if c_comment_end != -1: + l = l[:c_comment_end] + + is_comment = False + comment_ctx.append(l) + + fsrc.close() + del fsrc + + + # namespace hack + vars = ( + "BMO_OP_SLOT_ELEMENT_BUF", + "BMO_OP_SLOT_BOOL", + "BMO_OP_SLOT_FLT", + "BMO_OP_SLOT_INT", + "BMO_OP_SLOT_MAT", + "BMO_OP_SLOT_VEC", + "BMO_OP_SLOT_PTR", + "BMO_OP_SLOT_MAPPING", + + "BMO_OP_SLOT_SUBTYPE_MAP_ELEM", + "BMO_OP_SLOT_SUBTYPE_MAP_BOOL", + "BMO_OP_SLOT_SUBTYPE_MAP_INT", + "BMO_OP_SLOT_SUBTYPE_MAP_FLT", + "BMO_OP_SLOT_SUBTYPE_MAP_EMPTY", + "BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL", + + "BMO_OP_SLOT_SUBTYPE_PTR_SCENE", + "BMO_OP_SLOT_SUBTYPE_PTR_OBJECT", + "BMO_OP_SLOT_SUBTYPE_PTR_MESH", + "BMO_OP_SLOT_SUBTYPE_PTR_BMESH", + + "BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE", + + "BM_VERT", + "BM_EDGE", + "BM_FACE", + + "BMO_OP_FLAG_UNTAN_MULTIRES", + ) + vars_dict = {} + for i, v in enumerate(vars): + vars_dict[v] = (1 << i) + globals().update(vars_dict) + # reverse lookup + vars_dict_reverse = {v: k for k, v in vars_dict.items()} + # end namespace hack + + blocks_py = [] + for comment, b in blocks: + # magic, translate into python + b[0] = b[0].replace("static BMOpDefine ", "") + + for i, l in enumerate(b): + l = l.strip() + l = l.replace("{", "(") + l = l.replace("}", ")") + + if l.startswith("/*"): + l = l.replace("/*", "'''own <") + else: + l = l.replace("/*", "'''inline <") + l = l.replace("*/", ">''',") + + # exec func. eg: bmo_rotate_edges_exec, + if l.startswith("bmo_") and l.endswith("_exec,"): + l = "None," + b[i] = l + + #for l in b: + # print(l) + + text = "\n".join(b) + global_namespace = { + "__file__": "generated", + "__name__": "__main__", + } + + global_namespace.update(vars_dict) + + text_a, text_b = text.split("=", 1) + text = "result = " + text_b + exec(compile(text, "generated", 'exec'), global_namespace) + # print(global_namespace["result"]) + blocks_py.append((comment, global_namespace["result"])) + + + # --------------------- + # Now convert into rst. + fout = open(OUT_RST, 'w', encoding="utf-8") + fw = fout.write + fw(HEADER) + for comment, b in blocks_py: + args_in = None + args_out = None + for member in b[1:]: + if type(member) == tuple: + if args_in is None: + args_in = member + elif args_out is None: + args_out = member + break + + args_in_index = [] + args_out_index = [] + + if args_in is not None: + args_in_index[:] = [i for (i, a) in enumerate(args_in) if type(a) == tuple] + if args_out is not None: + args_out_index[:] = [i for (i, a) in enumerate(args_out) if type(a) == tuple] + + fw(".. function:: %s(bm, %s)\n\n" % (b[0], ", ".join([args_in[i][0] for i in args_in_index]))) + + # -- wash the comment + comment_washed = [] + for i, l in enumerate(comment): + assert((l.strip() == "") or + (l in {"/*", " *"}) or + (l.startswith(("/* ", " * ")))) + + l = l[3:] + if i == 0 and not l.strip(): + continue + if l.strip(): + l = " " + l + comment_washed.append(l) + + fw("\n".join(comment_washed)) + fw("\n") + # -- done + + + # get the args + def get_args_wash(args, args_index, is_ret): + args_wash = [] + for i in args_index: + arg = args[i] + if len(arg) == 3: + name, tp, tp_sub = arg + elif len(arg) == 2: + name, tp = arg + tp_sub = None + else: + print(arg) + assert(0) + + tp_str = "" + + comment_prev = "" + comment_next = "" + if i != 0: + comment_prev = args[i + 1] + if type(comment_prev) == str and comment_prev.startswith("our <"): + comment_prev = comment_next[5:-1] # strip inline <...> + else: + comment_prev = "" + + if i + 1 < len(args): + comment_next = args[i + 1] + if type(comment_next) == str and comment_next.startswith("inline <"): + comment_next = comment_next[8:-1] # strip inline <...> + else: + comment_next = "" + + comment = "" + if comment_prev: + comment += comment_prev.strip() + if comment_next: + comment += ("\n" if comment_prev else "") + comment_next.strip() + + if tp == BMO_OP_SLOT_FLT: + tp_str = "float" + elif tp == BMO_OP_SLOT_INT: + tp_str = "int" + elif tp == BMO_OP_SLOT_BOOL: + tp_str = "bool" + elif tp == BMO_OP_SLOT_MAT: + tp_str = ":class:`mathutils.Matrix`" + elif tp == BMO_OP_SLOT_VEC: + tp_str = ":class:`mathutils.Vector`" + if not is_ret: + tp_str += " or any sequence of 3 floats" + elif tp == BMO_OP_SLOT_PTR: + tp_str = "dict" + assert(tp_sub is not None) + if tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_BMESH: + tp_str = ":class:`bmesh.types.BMesh`" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_SCENE: + tp_str = ":class:`bpy.types.Scene`" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_OBJECT: + tp_str = ":class:`bpy.types.Object`" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_MESH: + tp_str = ":class:`bpy.types.Mesh`" + else: + print("Cant find", vars_dict_reverse[tp_sub]) + assert(0) + + elif tp == BMO_OP_SLOT_ELEMENT_BUF: + assert(tp_sub is not None) + + ls = [] + if tp_sub & BM_VERT: ls.append(":class:`bmesh.types.BMVert`") + if tp_sub & BM_EDGE: ls.append(":class:`bmesh.types.BMEdge`") + if tp_sub & BM_FACE: ls.append(":class:`bmesh.types.BMFace`") + assert(ls) # must be at least one + + if tp_sub & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE: + tp_str = "/".join(ls) + else: + tp_str = ("list of (%s)" % ", ".join(ls)) + + del ls + elif tp == BMO_OP_SLOT_MAPPING: + if tp_sub & BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: + tp_str = "set of vert/edge/face type" + else: + tp_str = "dict mapping vert/edge/face types to " + if tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_BOOL: + tp_str += "bool" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_INT: + tp_str += "int" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_FLT: + tp_str += "float" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_ELEM: + tp_str += ":class:`bmesh.types.BMVert`/:class:`bmesh.types.BMEdge`/:class:`bmesh.types.BMFace`" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL: + tp_str += "unknown internal data, not compatible with python" + else: + print("Cant find", vars_dict_reverse[tp_sub]) + assert(0) + else: + print("Cant find", vars_dict_reverse[tp]) + assert(0) + + args_wash.append((name, tp_str, comment)) + return args_wash + # end get_args_wash + + # all ops get this arg + fw(" :arg bm: The bmesh to operate on.\n") + fw(" :type bm: :class:`bmesh.types.BMesh`\n") + + args_in_wash = get_args_wash(args_in, args_in_index, False) + args_out_wash = get_args_wash(args_out, args_out_index, True) + + for (name, tp, comment) in args_in_wash: + if comment == "": + comment = "Undocumented." + + fw(" :arg %s: %s\n" % (name, comment)) + fw(" :type %s: %s\n" % (name, tp)) + + if args_out_wash: + fw(" :return:\n\n") + + for (name, tp, comment) in args_out_wash: + assert(name.endswith(".out")) + name = name[:-4] + fw(" - ``%s``: %s\n\n" % (name, comment)) + fw(" **type** %s\n" % tp) + + fw("\n") + fw(" :rtype: dict with string keys\n") + + fw("\n\n") + + fout.close() + del fout + print(OUT_RST) + + +if __name__ == "__main__": + main() diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 6f7d4f3582a..441a6c04efe 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -35,7 +35,7 @@ API dump in RST files ./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --output ../python_api For quick builds: - ./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --partial + ./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --partial bmesh.* Sphinx: HTML generation @@ -245,6 +245,7 @@ else: "bgl", "blf", "bmesh", + "bmesh.ops", "bmesh.types", "bmesh.utils", "bpy.app", @@ -297,7 +298,7 @@ try: __import__("aud") except ImportError: BPY_LOGGER.debug("Warning: Built without 'aud' module, docs incomplete...") - EXCLUDE_MODULES = EXCLUDE_MODULES + ("aud", ) + EXCLUDE_MODULES = list(EXCLUDE_MODULES) + ["aud"] # examples EXAMPLES_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "examples")) @@ -315,6 +316,8 @@ RST_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "rst")) INFO_DOCS = ( ("info_quickstart.rst", "Blender/Python Quickstart: new to blender/scripting and want to get your feet wet?"), ("info_overview.rst", "Blender/Python API Overview: a more complete explanation of python integration"), + ("info_tutorial_addon.rst", "Blender/Python Addon Tutorial: a step by step guide on how to write an addon from scratch"), + ("info_api_reference.rst", "Blender/Python API Reference Usage: examples of how to use the API reference docs"), ("info_best_practice.rst", "Best Practice: Conventions to follow for writing good scripts"), ("info_tips_and_tricks.rst", "Tips and Tricks: Hints to help you while writing scripts for blender"), ("info_gotcha.rst", "Gotcha's: some of the problems you may come up against when writing scripts"), @@ -1251,7 +1254,7 @@ def pyrna2sphinx(basepath): bases = list(reversed(struct.get_bases())) # props - lines[:] = [] + del lines[:] if _BPY_STRUCT_FAKE: descr_items = [(key, descr) for key, descr in sorted(bpy.types.Struct.__bases__[0].__dict__.items()) if not key.startswith("__")] @@ -1282,7 +1285,7 @@ def pyrna2sphinx(basepath): fw("\n") # funcs - lines[:] = [] + del lines[:] if _BPY_STRUCT_FAKE: for key, descr in descr_items: @@ -1305,7 +1308,7 @@ def pyrna2sphinx(basepath): fw(line) fw("\n") - lines[:] = [] + del lines[:] if struct.references: # use this otherwise it gets in the index for a normal heading. @@ -1472,6 +1475,11 @@ def write_sphinx_conf_py(basepath): file.close() +def execfile(filepath): + global_namespace = {"__file__": filepath, "__name__": "__main__"} + exec(compile(open(filepath).read(), filepath, 'exec'), global_namespace) + + def write_rst_contents(basepath): ''' Write the rst file of the main page, needed for sphinx (index.html) @@ -1532,14 +1540,18 @@ def write_rst_contents(basepath): "mathutils", "mathutils.geometry", "mathutils.noise", # misc "bgl", "blf", "gpu", "aud", "bpy_extras", - # bmesh - "bmesh", "bmesh.types", "bmesh.utils", + # bmesh, submodules are in own page + "bmesh", ) for mod in standalone_modules: if mod not in EXCLUDE_MODULES: fw(" %s\n\n" % mod) + # special case, this 'bmesh.ops.rst' is extracted from C source + if "bmesh.ops" not in EXCLUDE_MODULES: + execfile(os.path.join(SCRIPT_DIR, "rst_from_bmesh_opdefines.py")) + # game engine if "bge" not in EXCLUDE_MODULES: fw(title_string("Game Engine Modules", "=", double=True)) @@ -1701,6 +1713,8 @@ def copy_handwritten_rsts(basepath): "bgl", # "Blender OpenGl wrapper" "gpu", # "GPU Shader Module" + "bmesh.ops", # generated by rst_from_bmesh_opdefines.py + # includes... "include__bmesh", ] @@ -1712,6 +1726,11 @@ def copy_handwritten_rsts(basepath): # changelog shutil.copy2(os.path.join(RST_DIR, "change_log.rst"), basepath) + # copy images, could be smarter but just glob for now. + for f in os.listdir(RST_DIR): + if f.endswith(".png"): + shutil.copy2(os.path.join(RST_DIR, f), basepath) + def rna2sphinx(basepath): diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 151df493062..2640c528c94 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -32,9 +32,10 @@ if(WITH_BULLET) add_subdirectory(bullet2) endif() -if(WITH_MOD_CLOTH_ELTOPO) - add_subdirectory(eltopo) -endif() +# now only available in a branch +#if(WITH_MOD_CLOTH_ELTOPO) +# add_subdirectory(eltopo) +#endif() if(WITH_BINRELOC) add_subdirectory(binreloc) diff --git a/extern/SConscript b/extern/SConscript index ce366deb38a..71998ee072c 100644 --- a/extern/SConscript +++ b/extern/SConscript @@ -8,8 +8,11 @@ SConscript(['colamd/SConscript']) if env['WITH_BF_GAMEENGINE']: SConscript(['recastnavigation/SConscript']) +# now only available in a branch +''' if env['WITH_BF_ELTOPO']: SConscript(['eltopo/SConscript']) +''' if env['WITH_BF_BULLET']: SConscript(['bullet2/src/SConscript']) diff --git a/extern/glew/src/glew.c b/extern/glew/src/glew.c index 5d886ce7807..833d3999268 100644 --- a/extern/glew/src/glew.c +++ b/extern/glew/src/glew.c @@ -93,7 +93,7 @@ void* dlGetProcAddress (const GLubyte* name) #include #include -#ifdef MAC_OS_X_VERSION_10_3 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3 #include @@ -142,7 +142,7 @@ void* NSGLGetProcAddress (const GLubyte *name) return NULL; #endif } -#endif /* MAC_OS_X_VERSION_10_3 */ +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #endif /* __APPLE__ */ /* diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 38be34add75..ebc5953d956 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -102,6 +102,8 @@ set(SRC libmv/multiview/conditioning.h libmv/multiview/euclidean_resection.h libmv/multiview/fundamental.h + libmv/multiview/homography.h + libmv/multiview/homography_parameterization.h libmv/multiview/nviewtriangulation.h libmv/multiview/projection.h libmv/multiview/resection.h @@ -131,6 +133,7 @@ set(SRC libmv/tracking/pyramid_region_tracker.h libmv/tracking/region_tracker.h libmv/tracking/retrack_region_tracker.h + libmv/tracking/track_region.h libmv/tracking/trklt_region_tracker.h third_party/fast/fast.h diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index a15927f881d..8e483abd386 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -192,7 +192,7 @@ static void imageToFloatBuf(const libmv::FloatImage *image, int channels, float } #if defined(DUMP_FAILURE) || defined (DUMP_ALWAYS) -void savePNGImage(png_bytep *row_pointers, int width, int height, int depth, int color_type, char *file_name) +static void savePNGImage(png_bytep *row_pointers, int width, int height, int depth, int color_type, char *file_name) { png_infop info_ptr; png_structp png_ptr; @@ -437,6 +437,9 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, #endif saveImage("old_patch", old_patch, x1[4], y1[4]); saveImage("new_patch", new_patch, x2[4], y2[4]); + + if (options->image1_mask) + saveImage("mask", image1_mask, x2[4], y2[4]); } #endif @@ -897,7 +900,7 @@ void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics intrinsics->SetFocalLength(focal_length, focal_length); if (intrinsics->principal_point_x() != principal_x || intrinsics->principal_point_y() != principal_y) - intrinsics->SetFocalLength(focal_length, focal_length); + intrinsics->SetPrincipalPoint(principal_x, principal_y); if (intrinsics->k1() != k1 || intrinsics->k2() != k2 || intrinsics->k3() != k3) intrinsics->SetRadialDistortion(k1, k2, k3); diff --git a/extern/libmv/libmv/simple_pipeline/resect.cc b/extern/libmv/libmv/simple_pipeline/resect.cc index 4c9ca6d8677..3929271e66f 100644 --- a/extern/libmv/libmv/simple_pipeline/resect.cc +++ b/extern/libmv/libmv/simple_pipeline/resect.cc @@ -57,7 +57,7 @@ struct EuclideanResectCostFunction { EuclideanResectCostFunction(const vector &markers, const EuclideanReconstruction &reconstruction, - const Mat3 initial_R) + const Mat3 &initial_R) : markers(markers), reconstruction(reconstruction), initial_R(initial_R) {} diff --git a/extern/xdnd/xdnd.c b/extern/xdnd/xdnd.c index 9bdee89c1ce..50d1fec4969 100644 --- a/extern/xdnd/xdnd.c +++ b/extern/xdnd/xdnd.c @@ -347,7 +347,7 @@ void xdnd_set_dnd_aware (DndClass * dnd, Window window, Atom * typelist) &nchildren_return); if (children_return) XFree (children_return); - if (r) + if (r && parent != root_return) xdnd_set_dnd_aware (dnd, parent, typelist); } diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index cb2fc239859..be797c45ba1 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -65,6 +65,10 @@ if(WITH_CYCLES) add_subdirectory(cycles) endif() +if(WITH_INTERNATIONAL) + add_subdirectory(locale) +endif() + # only windows needs utf16 converter if(WIN32) add_subdirectory(utfconv) diff --git a/intern/SConscript b/intern/SConscript index 59e412333b0..5360ce4ea88 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -30,6 +30,9 @@ if env['WITH_BF_CYCLES']: if env['WITH_BF_BOOLEAN']: SConscript(['bsp/SConscript']) +if env['WITH_BF_INTERNATIONAL']: + SConscript(['locale/SConscript']) + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'): SConscript(['utfconv/SConscript']) diff --git a/intern/audaspace/intern/AUD_FileWriter.h b/intern/audaspace/intern/AUD_FileWriter.h index da52c7e0fb2..3291c1ad03a 100644 --- a/intern/audaspace/intern/AUD_FileWriter.h +++ b/intern/audaspace/intern/AUD_FileWriter.h @@ -64,8 +64,8 @@ public: * Writes a reader to a writer. * \param reader The reader to read from. * \param writer The writer to write to. - * \param length How many samples should be transfered. - * \param buffersize How many samples should be transfered at once. + * \param length How many samples should be transferred. + * \param buffersize How many samples should be transferred at once. */ static void writeReader(boost::shared_ptr reader, boost::shared_ptr writer, unsigned int length, unsigned int buffersize); @@ -73,8 +73,8 @@ public: * Writes a reader to several writers. * \param reader The reader to read from. * \param writers The writers to write to. - * \param length How many samples should be transfered. - * \param buffersize How many samples should be transfered at once. + * \param length How many samples should be transferred. + * \param buffersize How many samples should be transferred at once. */ static void writeReader(boost::shared_ptr reader, std::vector >& writers, unsigned int length, unsigned int buffersize); }; diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp index 6aa0faed863..b342b8f31fb 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -81,7 +81,7 @@ void AUD_LinearResampleReader::read(int& length, bool& eos, sample_t* buffer) int samplesize = AUD_SAMPLE_SIZE(specs); int size = length; float factor = m_rate / m_reader->getSpecs().rate; - float spos; + float spos = 0.0f; sample_t low, high; eos = false; diff --git a/intern/bsp/intern/BOP_CarveInterface.cpp b/intern/bsp/intern/BOP_CarveInterface.cpp index f7da76e5794..bb3a783548c 100644 --- a/intern/bsp/intern/BOP_CarveInterface.cpp +++ b/intern/bsp/intern/BOP_CarveInterface.cpp @@ -205,7 +205,7 @@ static void Carve_getIntersectedOperandMeshes(std::vector::mesh_t*> & std::vector::mesh_t*>::iterator it = meshes.begin(); std::vector< RTreeNode<3, Face<3> *> *> meshRTree; - while(it != meshes.end()) { + while (it != meshes.end()) { MeshSet<3>::mesh_t *mesh = *it; bool isAdded = false; @@ -279,7 +279,7 @@ static MeshSet<3> *Carve_unionIntersectingMeshes(MeshSet<3> *poly, return poly; } - while(orig_meshes.size()) { + while (orig_meshes.size()) { MeshSet<3> *right = Carve_getIntersectedOperand(orig_meshes, otherAABB); if (!right) { diff --git a/intern/container/CTR_HashedPtr.h b/intern/container/CTR_HashedPtr.h index b7ac460f270..ee832eee153 100644 --- a/intern/container/CTR_HashedPtr.h +++ b/intern/container/CTR_HashedPtr.h @@ -46,13 +46,13 @@ class CTR_HashedPtr void *m_valptr; public: CTR_HashedPtr(void *val) : m_valptr(val) { - }; + } unsigned int hash() const { return CTR_Hash(m_valptr); - }; + } inline friend bool operator ==(const CTR_HashedPtr & rhs, const CTR_HashedPtr & lhs) { return rhs.m_valptr == lhs.m_valptr; - }; + } void *getValue() const { return m_valptr; } diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 7562ee0a0a5..12829f15aed 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -21,8 +21,11 @@ elseif(CMAKE_COMPILER_IS_GNUCC) endif() # for OSL -set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") -# set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +if(WIN32 AND MSVC) + set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang")) + set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +endif() # Definitions and Includes @@ -44,10 +47,6 @@ if(WITH_CYCLES_OSL) include_directories(${OSL_INCLUDES}) endif() -if(WITH_CYCLES_PARTIO) - add_definitions(-DWITH_PARTIO) -endif() - if(WITH_CYCLES_CUDA_BINARIES) add_definitions(-DWITH_CUDA_BINARIES) endif() @@ -69,7 +68,10 @@ if(WITH_CYCLES_BLENDER) add_subdirectory(blender) endif() -add_subdirectory(app) +if(WITH_CYCLES_TEST) + add_subdirectory(app) +endif() + add_subdirectory(bvh) add_subdirectory(device) add_subdirectory(doc) diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index c0e0353d37d..a0e2650ddc6 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -23,6 +23,10 @@ defs.append('WITH_OPENCL') defs.append('WITH_MULTI') defs.append('WITH_CUDA') +if env['WITH_BF_CYCLES_OSL']: + defs.append('WITH_OSL') + incs.append(cycles['BF_OSL_INC']) + if env['WITH_BF_CYCLES_CUDA_BINARIES']: defs.append('WITH_CUDA_BINARIES') @@ -32,7 +36,8 @@ incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.sp incs.extend('#extern/glew/include #intern/mikktspace'.split()) incs.append(cycles['BF_OIIO_INC']) incs.append(cycles['BF_BOOST_INC']) -incs.append(cycles['BF_PYTHON_INC']) +incs.append(cycles['BF_OPENEXR_INC'].split()) +incs.extend(cycles['BF_PYTHON_INC'].split()) if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) @@ -44,7 +49,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', ' # optimized kernel if env['WITH_BF_RAYOPTIMIZATION']: - optim_cxxflags = [] + optim_cxxflags = Split(env['CXXFLAGS']) if env['OURPLATFORM'] == 'win32-vc': optim_cxxflags.append('/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) @@ -62,6 +67,12 @@ if env['WITH_BF_RAYOPTIMIZATION']: cycles.BlenderLib('bf_intern_cycles', sources, incs, defs, libtype=['intern'], priority=[0], cxx_compileflags=cxxflags) +if env['WITH_BF_CYCLES_OSL']: + oso_files = SConscript(['kernel/shaders/SConscript']) + cycles.Depends("kernel/osl/osl_shader.o", oso_files) + + SConscript(['kernel/osl/SConscript']) + # cuda kernel binaries if env['WITH_BF_CYCLES_CUDA_BINARIES']: kernel_binaries = SConscript(['kernel/SConscript']) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 83b3f731ffe..3fb8aaf934f 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -35,10 +35,6 @@ if(WITH_CYCLES_OSL) list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES}) endif() -if(WITH_CYCLES_PARTIO) - list(APPEND LIBRARIES ${PARTIO_LIBRARIES}) -endif() - include_directories(${INC}) include_directories(SYSTEM ${INC_SYS}) diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index e921cc46fe4..625e8cc1706 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -326,7 +326,7 @@ using namespace ccl; int main(int argc, const char **argv) { - path_init("../build/bin/2.59/scripts/addons/cycles/"); + path_init(); options_parse(argc, argv); diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h index 469d63d1530..b8a30b71717 100644 --- a/intern/cycles/blender/CCL_api.h +++ b/intern/cycles/blender/CCL_api.h @@ -23,12 +23,12 @@ extern "C" { #endif -/* returns a list of devices for selection, array is name NULL pointer +/* returns a list of devices for selection, array is empty identifier * terminated and must not be freed */ typedef struct CCLDeviceInfo { - const char *identifier; - const char *name; + char identifier[128]; + char name[512]; int value; } CCLDeviceInfo; diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 16697c08b2b..0fad2ac5618 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -48,7 +48,11 @@ class CyclesRender(bpy.types.RenderEngine): # final render def update(self, data, scene): - engine.create(self, data, scene) + if not self.session: + engine.create(self, data, scene) + else: + engine.reset(self, data, scene) + engine.update(self, data, scene) def render(self, scene): diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index e4f80cb4d5d..ca5cbee9325 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -61,6 +61,13 @@ def render(engine): _cycles.render(engine.session) +def reset(engine, data, scene): + import _cycles + data = data.as_pointer() + scene = scene.as_pointer() + _cycles.reset(engine.session, data, scene) + + def update(engine, data, scene): import _cycles _cycles.sync(engine.session) diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py index dd7a555c2a8..82b48973ca1 100644 --- a/intern/cycles/blender/addon/enums.py +++ b/intern/cycles/blender/addon/enums.py @@ -57,7 +57,7 @@ aperture_types = ( panorama_types = ( ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"), - ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ignore the sensor dimensions"), - ('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, take sensor dimensions into consideration. For fulldomes use it with a square sensor ratio", + ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"), + ('FISHEYE_EQUISOLID', "Fisheye Equisolid", + "Similar to most fisheye modern lens, takes sensor dimensions into consideration"), ) - diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py index aac1e2422b9..79ce3df20c3 100644 --- a/intern/cycles/blender/addon/osl.py +++ b/intern/cycles/blender/addon/osl.py @@ -79,12 +79,13 @@ def update_script_node(node, report): if script.is_in_memory or script.is_dirty or script.is_modified or not os.path.exists(osl_path): # write text datablock contents to temporary file - osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=True) + osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=False) osl_file.write(script.as_string()) - osl_file.flush() + osl_file.close() + ok, oso_path = osl_compile(osl_file.name, report) oso_file_remove = False - osl_file.close() + os.remove(osl_file.name) else: # compile text datablock from disk directly ok, oso_path = osl_compile(osl_path, report) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 9cc58e65bef..ba931469e8a 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -216,6 +216,10 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.label(text="Viewport:") sub.prop(cscene, "preview_start_resolution") + sub = col.column(align=True) + sub.label(text="Final Render:") + sub.prop(rd, "use_persistent_data", text="Persistent Images") + class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): bl_label = "Layers" @@ -953,7 +957,7 @@ def draw_device(self, context): elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL': layout.prop(cscene, "device") - if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'None'): + if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'): layout.prop(cscene, "shading_system") @@ -1022,6 +1026,8 @@ def get_panels(): bpy.types.TEXTURE_PT_voxeldata, bpy.types.TEXTURE_PT_pointdensity, bpy.types.TEXTURE_PT_pointdensity_turbulence, + bpy.types.TEXTURE_PT_mapping, + bpy.types.TEXTURE_PT_influence, bpy.types.PARTICLE_PT_context_particles, bpy.types.PARTICLE_PT_emission, bpy.types.PARTICLE_PT_hair_dynamics, diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index af16e210301..0cbd2a0291f 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -56,15 +56,16 @@ struct BlenderCamera { float sensor_width; float sensor_height; - float border_left; - float border_right; - float border_bottom; - float border_top; + int full_width; + int full_height; + + BoundBox2D border; + BoundBox2D pano_viewplane; Transform matrix; }; -static void blender_camera_init(BlenderCamera *bcam) +static void blender_camera_init(BlenderCamera *bcam, BL::Scene b_scene) { memset(bcam, 0, sizeof(BlenderCamera)); @@ -75,8 +76,16 @@ static void blender_camera_init(BlenderCamera *bcam) bcam->sensor_height = 18.0f; bcam->sensor_fit = BlenderCamera::AUTO; bcam->shuttertime = 1.0f; - bcam->border_right = 1.0f; - bcam->border_top = 1.0f; + bcam->border.right = 1.0f; + bcam->border.top = 1.0f; + bcam->pano_viewplane.right = 1.0f; + bcam->pano_viewplane.top = 1.0f; + + /* render resolution */ + BL::RenderSettings r = b_scene.render(); + + bcam->full_width = (int)(r.resolution_x()*r.resolution_percentage()/100); + bcam->full_height = (int)(r.resolution_y()*r.resolution_percentage()/100); } static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) @@ -199,7 +208,7 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type) } static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, - float *left, float *right, float *bottom, float *top, float *aspectratio, float *sensor_size) + BoundBox2D *viewplane, float *aspectratio, float *sensor_size) { /* dimensions */ float xratio = width*bcam->pixelaspect.x; @@ -207,10 +216,9 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, /* compute x/y aspect and ratio */ float xaspect, yaspect; - - /* sensor fitting */ bool horizontal_fit; + /* sensor fitting */ if(bcam->sensor_fit == BlenderCamera::AUTO) { horizontal_fit = (xratio > yratio); *sensor_size = bcam->sensor_width; @@ -244,32 +252,26 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, if(bcam->type == CAMERA_PANORAMA) { /* set viewplane */ - *left = 0.0f; - *right = 1.0f; - *bottom = 0.0f; - *top = 1.0f; + *viewplane = bcam->pano_viewplane; } else { /* set viewplane */ - *left = -xaspect; - *right = xaspect; - *bottom = -yaspect; - *top = yaspect; + viewplane->left = -xaspect; + viewplane->right = xaspect; + viewplane->bottom = -yaspect; + viewplane->top = yaspect; /* zoom for 3d camera view */ - *left *= bcam->zoom; - *right *= bcam->zoom; - *bottom *= bcam->zoom; - *top *= bcam->zoom; + *viewplane = (*viewplane) * bcam->zoom; /* modify viewplane with camera shift and 3d camera view offset */ float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); - *left += dx; - *right += dx; - *bottom += dy; - *top += dy; + viewplane->left += dx; + viewplane->right += dx; + viewplane->bottom += dy; + viewplane->top += dy; } } @@ -281,11 +283,37 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int /* viewplane */ blender_camera_viewplane(bcam, width, height, - &cam->left, &cam->right, &cam->bottom, &cam->top, &aspectratio, &sensor_size); + &cam->viewplane, &aspectratio, &sensor_size); - /* sensor */ - cam->sensorwidth = bcam->sensor_width; - cam->sensorheight = bcam->sensor_height; + /* panorama sensor */ + if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) { + float fit_xratio = bcam->full_width*bcam->pixelaspect.x; + float fit_yratio = bcam->full_height*bcam->pixelaspect.y; + bool horizontal_fit; + float sensor_size; + + if(bcam->sensor_fit == BlenderCamera::AUTO) { + horizontal_fit = (fit_xratio > fit_yratio); + sensor_size = bcam->sensor_width; + } + else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) { + horizontal_fit = true; + sensor_size = bcam->sensor_width; + } + else { /* vertical */ + horizontal_fit = false; + sensor_size = bcam->sensor_height; + } + + if(horizontal_fit) { + cam->sensorwidth = sensor_size; + cam->sensorheight = sensor_size * fit_yratio / fit_xratio; + } + else { + cam->sensorwidth = sensor_size * fit_xratio / fit_yratio; + cam->sensorheight = sensor_size; + } + } /* clipping distances */ cam->nearclip = bcam->nearclip; @@ -314,10 +342,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->shuttertime = bcam->shuttertime; /* border */ - cam->border_left = bcam->border_left; - cam->border_right = bcam->border_right; - cam->border_bottom = bcam->border_bottom; - cam->border_top = bcam->border_top; + cam->border = bcam->border; /* set update flag */ if(cam->modified(prevcam)) @@ -329,7 +354,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int void BlenderSync::sync_camera(BL::Object b_override, int width, int height) { BlenderCamera bcam; - blender_camera_init(&bcam); + blender_camera_init(&bcam, b_scene); /* pixel aspect */ BL::RenderSettings r = b_scene.render(); @@ -340,10 +365,10 @@ void BlenderSync::sync_camera(BL::Object b_override, int width, int height) /* border */ if(r.use_border()) { - bcam.border_left = r.border_min_x(); - bcam.border_right = r.border_max_x(); - bcam.border_bottom = r.border_min_y(); - bcam.border_top = r.border_max_y(); + bcam.border.left = r.border_min_x(); + bcam.border.right = r.border_max_x(); + bcam.border.bottom = r.border_min_y(); + bcam.border.top = r.border_max_y(); } /* camera object */ @@ -381,6 +406,9 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion) /* Sync 3D View Camera */ +static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box); + static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false) { /* 3d view parameters */ @@ -396,14 +424,25 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: if(b_ob) { blender_camera_from_object(bcam, b_ob, skip_panorama); - /* magic zoom formula */ - bcam->zoom = (float)b_rv3d.view_camera_zoom(); - bcam->zoom = (1.41421f + bcam->zoom/50.0f); - bcam->zoom *= bcam->zoom; - bcam->zoom = 2.0f/bcam->zoom; + if(!skip_panorama && bcam->type == CAMERA_PANORAMA) { + /* in panorama camera view, we map viewplane to camera border */ + BoundBox2D view_box, cam_box; - /* offset */ - bcam->offset = get_float2(b_rv3d.view_camera_offset()); + blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); + + bcam->pano_viewplane = view_box.make_relative_to(cam_box); + } + else { + /* magic zoom formula */ + bcam->zoom = (float)b_rv3d.view_camera_zoom(); + bcam->zoom = (1.41421f + bcam->zoom/50.0f); + bcam->zoom *= bcam->zoom; + bcam->zoom = 2.0f/bcam->zoom; + + /* offset */ + bcam->offset = get_float2(b_rv3d.view_camera_offset()); + } } } else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) { @@ -427,6 +466,34 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix())); } +static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box) +{ +// BL::RenderSettings r = b_scene.render(); /* UNUSED */ + BoundBox2D cam, view; + float view_aspect, cam_aspect, sensor_size; + + /* get viewport viewplane */ + BlenderCamera view_bcam; + blender_camera_init(&view_bcam, b_scene); + blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); + + blender_camera_viewplane(&view_bcam, width, height, + &view, &view_aspect, &sensor_size); + + /* get camera viewplane */ + BlenderCamera cam_bcam; + blender_camera_init(&cam_bcam, b_scene); + blender_camera_from_object(&cam_bcam, b_ob, true); + + blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height, + &cam, &cam_aspect, &sensor_size); + + /* return */ + *view_box = view * (1.0f/view_aspect); + *cam_box = cam * (1.0f/cam_aspect); +} + static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { @@ -442,10 +509,10 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp * assume viewport has got correctly clamped border already */ if(b_v3d.use_render_border()) { - bcam->border_left = b_v3d.render_border_min_x(); - bcam->border_right = b_v3d.render_border_max_x(); - bcam->border_bottom = b_v3d.render_border_min_y(); - bcam->border_top = b_v3d.render_border_max_y(); + bcam->border.left = b_v3d.render_border_min_x(); + bcam->border.right = b_v3d.render_border_max_x(); + bcam->border.bottom = b_v3d.render_border_min_y(); + bcam->border.top = b_v3d.render_border_max_y(); return; } @@ -458,66 +525,26 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp if(!b_ob) return; - bcam->border_left = r.border_min_x(); - bcam->border_right = r.border_max_x(); - bcam->border_bottom = r.border_min_y(); - bcam->border_top = r.border_max_y(); + bcam->border.left = r.border_min_x(); + bcam->border.right = r.border_max_x(); + bcam->border.bottom = r.border_min_y(); + bcam->border.top = r.border_max_y(); - float cam_left, cam_right, cam_bottom, cam_top; - float view_left, view_right, view_bottom, view_top; - float view_aspect, cam_aspect, sensor_size; + /* determine camera viewport subset */ + BoundBox2D view_box, cam_box; - /* get viewport viewplane */ - BlenderCamera view_bcam; - blender_camera_init(&view_bcam); - blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); - - blender_camera_viewplane(&view_bcam, width, height, - &view_left, &view_right, &view_bottom, &view_top, &view_aspect, &sensor_size); - - view_left /= view_aspect; - view_right /= view_aspect; - view_bottom /= view_aspect; - view_top /= view_aspect; - - /* get camera viewplane */ - BlenderCamera cam_bcam; - blender_camera_init(&cam_bcam); - blender_camera_from_object(&cam_bcam, b_ob, true); - - width = (int)(r.resolution_x()*r.resolution_percentage()/100); - height = (int)(r.resolution_y()*r.resolution_percentage()/100); - - blender_camera_viewplane(&cam_bcam, width, height, - &cam_left, &cam_right, &cam_bottom, &cam_top, &cam_aspect, &sensor_size); - - cam_left /= cam_aspect; - cam_right /= cam_aspect; - cam_bottom /= cam_aspect; - cam_top /= cam_aspect; + blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); /* determine viewport subset matching camera border */ - float tmp_left = ((cam_left - view_left) / (view_right - view_left)); - float tmp_right = ((cam_right - view_left) / (view_right - view_left)); - float tmp_bottom = ((cam_bottom - view_bottom) / (view_top - view_bottom)); - float tmp_top = ((cam_top - view_bottom) / (view_top - view_bottom)); - - bcam->border_left = tmp_left + bcam->border_left*(tmp_right - tmp_left); - bcam->border_right = tmp_left + bcam->border_right*(tmp_right - tmp_left); - bcam->border_bottom = tmp_bottom + bcam->border_bottom*(tmp_top - tmp_bottom); - bcam->border_top = tmp_bottom + bcam->border_top*(tmp_top - tmp_bottom); - - /* clamp */ - bcam->border_left = clamp(bcam->border_left, 0.0f, 1.0f); - bcam->border_right = clamp(bcam->border_right, 0.0f, 1.0f); - bcam->border_bottom = clamp(bcam->border_bottom, 0.0f, 1.0f); - bcam->border_top = clamp(bcam->border_top, 0.0f, 1.0f); + cam_box = cam_box.make_relative_to(view_box); + bcam->border = cam_box.subset(bcam->border).clamp(); } void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { BlenderCamera bcam; - blender_camera_init(&bcam); + blender_camera_init(&bcam, b_scene); blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height); blender_camera_border(&bcam, b_scene, b_v3d, b_rv3d, width, height); @@ -539,10 +566,10 @@ BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b if(use_border) { /* border render */ - params.full_x = cam->border_left*width; - params.full_y = cam->border_bottom*height; - params.width = (int)(cam->border_right*width) - params.full_x; - params.height = (int)(cam->border_top*height) - params.full_y; + params.full_x = cam->border.left*width; + params.full_y = cam->border.bottom*height; + params.width = (int)(cam->border.right*width) - params.full_x; + params.height = (int)(cam->border.top*height) - params.full_y; /* survive in case border goes out of view or becomes too small */ params.width = max(params.width, 1); diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 0e13479a761..c9748756d43 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -116,7 +116,7 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign); } -static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector& nverts) +static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector& nverts, bool need_sign, bool active_render) { /* setup userdata */ MikkUserData userdata(b_mesh, b_layer, nverts.size()); @@ -140,22 +140,57 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la /* compute tangents */ genTangSpaceDefault(&context); - /* create attribute */ - /* todo: create float4 attribute for sign */ - Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("tangent")); + /* create tangent attributes */ + Attribute *attr; + ustring name = ustring((string(b_layer.name().c_str()) + ".tangent").c_str()); + + if(active_render) + attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name); + else + attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER); + float3 *tangent = attr->data_float3(); - for (int i = 0; i < nverts.size(); i++) { + /* create bitangent sign attribute */ + float *tangent_sign = NULL; + + if(need_sign) { + Attribute *attr_sign; + ustring name_sign = ustring((string(b_layer.name().c_str()) + ".tangent_sign").c_str()); + + if(active_render) + attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign); + else + attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER); + + tangent_sign = attr_sign->data_float(); + } + + for(int i = 0; i < nverts.size(); i++) { tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]); tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]); tangent += 3; + if(tangent_sign) { + tangent_sign[0] = userdata.tangent[i*4 + 0].w; + tangent_sign[1] = userdata.tangent[i*4 + 1].w; + tangent_sign[2] = userdata.tangent[i*4 + 2].w; + tangent_sign += 3; + } + if(nverts[i] == 4) { tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]); tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]); tangent += 3; + + if(tangent_sign) { + tangent_sign[0] = userdata.tangent[i*4 + 0].w; + tangent_sign[1] = userdata.tangent[i*4 + 2].w; + tangent_sign[2] = userdata.tangent[i*4 + 3].w; + tangent_sign += 3; + } } } } @@ -233,48 +268,49 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< BL::Mesh::tessface_uv_textures_iterator l; for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { - AttributeStandard std = (l->active_render())? ATTR_STD_UV: ATTR_STD_NONE; + bool active_render = l->active_render(); + AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; ustring name = ustring(l->name().c_str()); - if(!(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std))) - continue; + /* UV map */ + if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { + Attribute *attr; - Attribute *attr; + if(active_render) + attr = mesh->attributes.add(std, name); + else + attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER); - if(l->active_render()) - attr = mesh->attributes.add(std, name); - else - attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER); + BL::MeshTextureFaceLayer::data_iterator t; + float3 *fdata = attr->data_float3(); + size_t i = 0; - BL::MeshTextureFaceLayer::data_iterator t; - float3 *fdata = attr->data_float3(); - size_t i = 0; - - for(l->data.begin(t); t != l->data.end(); ++t, ++i) { - fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv2()); - fdata[2] = get_float3(t->uv3()); - fdata += 3; - - if(nverts[i] == 4) { + for(l->data.begin(t); t != l->data.end(); ++t, ++i) { fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv3()); - fdata[2] = get_float3(t->uv4()); + fdata[1] = get_float3(t->uv2()); + fdata[2] = get_float3(t->uv3()); fdata += 3; + + if(nverts[i] == 4) { + fdata[0] = get_float3(t->uv1()); + fdata[1] = get_float3(t->uv3()); + fdata[2] = get_float3(t->uv4()); + fdata += 3; + } } } - } - } - /* create texcoord-based tangent attributes */ - if(mesh->need_attribute(scene, ATTR_STD_TANGENT)) { - BL::Mesh::tessface_uv_textures_iterator l; + /* UV tangent */ + std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE; + name = ustring((string(l->name().c_str()) + ".tangent").c_str()); - for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { - if(!l->active_render()) - continue; + if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { + std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE; + name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); + bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)); - mikk_compute_tangents(b_mesh, *l, mesh, nverts); + mikk_compute_tangents(b_mesh, *l, mesh, nverts, need_sign, active_render); + } } } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 1b920249733..38f27bcf2af 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -86,11 +86,11 @@ static uint object_ray_visibility(BL::Object b_ob) /* Light */ -void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm) +void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm) { /* test if we need to sync */ Light *light; - ObjectKey key(b_parent, b_index, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob); if(!light_map.sync(&light, b_ob, b_parent, key)) return; @@ -196,23 +196,24 @@ void BlenderSync::sync_background_light() /* Object */ -void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, int particle_id) +Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion) { BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); /* light is handled separately */ if(object_is_light(b_ob)) { if(!motion) - sync_light(b_parent, b_index, b_ob, tfm); - return; + sync_light(b_parent, persistent_id, b_ob, tfm); + + return NULL; } /* only interested in object that we can create meshes from */ if(!object_is_mesh(b_ob)) - return; + return NULL; /* key to lookup object */ - ObjectKey key(b_parent, b_index, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob); Object *object; /* motion vector case */ @@ -234,7 +235,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject sync_mesh_motion(b_ob, object->mesh, motion); } - return; + return object; } /* test if we need to sync */ @@ -248,13 +249,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject /* mesh sync */ object->mesh = sync_mesh(b_ob, object_updated); + /* sspecial case not tracked by object update flags */ if(use_holdout != object->use_holdout) { object->use_holdout = use_holdout; scene->object_manager->tag_update(scene); + object_updated = true; } - /* object sync */ - /* transform comparison should not be needed, but duplis don't work perfect + /* object sync + * transform comparison should not be needed, but duplis don't work perfect * in the depsgraph and may not signal changes, so this is a workaround */ if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) { object->name = b_ob.name().c_str(); @@ -264,7 +267,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->motion.post = tfm; object->use_motion = false; - object->random_id = hash_int_2d(hash_string(object->name.c_str()), b_index); + /* random number */ + object->random_id = hash_string(object->name.c_str()); + + if(persistent_id) { + for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++) + object->random_id = hash_int_2d(object->random_id, persistent_id[i]); + } + else + object->random_id = hash_int_2d(object->random_id, 0); /* visibility flags for both parent */ object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL; @@ -273,6 +284,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->random_id ^= hash_int(hash_string(b_parent.name().c_str())); } + /* make holdout objects on excluded layer invisible for non-camera rays */ + if(use_holdout && (layer_flag & render_layer.exclude_layer)) + object->visibility &= ~(PATH_RAY_ALL - PATH_RAY_CAMERA); + /* camera flag is not actually used, instead is tested * against render layer flags */ if(object->visibility & PATH_RAY_CAMERA) { @@ -289,10 +304,17 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->dupli_uv = make_float2(0.0f, 0.0f); } - object->particle_id = particle_id; - object->tag_update(scene); } + + return object; +} + +static bool object_dupli_hide_original(BL::Object::dupli_type_enum dupli_type) +{ + return (dupli_type == BL::Object::dupli_type_VERTS || + dupli_type == BL::Object::dupli_type_FACES || + dupli_type == BL::Object::dupli_type_FRAMES); } /* Object Loop */ @@ -314,7 +336,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) /* object loop */ BL::Scene::objects_iterator b_ob; BL::Scene b_sce = b_scene; - int particle_offset = 1; /* first particle is dummy for regular, non-instanced objects */ + + /* global particle index counter */ + int particle_id = 1; bool cancel = false; @@ -327,16 +351,14 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) if(!hide) { progress.set_sync_status("Synchronizing object", (*b_ob).name()); - int num_particles = object_count_particles(*b_ob); - if(b_ob->is_duplicator()) { - hide = true; /* duplicators hidden by default */ + /* duplicators hidden by default */ + hide = true; /* dupli objects */ b_ob->dupli_list_create(b_scene, 2); BL::Object::dupli_list_iterator b_dup; - int b_index = 0; for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) { Transform tfm = get_transform(b_dup->matrix()); @@ -345,7 +367,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) bool emitter_hide = false; if(b_dup_ob.is_duplicator()) { - emitter_hide = true; /* duplicators hidden by default */ + /* duplicators hidden by default, except dupliframes which duplicate self */ + if(b_dup_ob.dupli_type() != BL::Object::dupli_type_FRAMES) + emitter_hide = true; /* check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; @@ -354,33 +378,54 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) emitter_hide = false; } + /* hide original object for duplis */ + BL::Object parent = b_dup_ob.parent(); + if(parent && object_dupli_hide_original(parent.dupli_type())) + if(b_dup->type() == BL::DupliObject::type_GROUP) + dup_hide = true; + if(!(b_dup->hide() || dup_hide || emitter_hide)) { - sync_object(*b_ob, b_index, *b_dup, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset); + /* the persistent_id allows us to match dupli objects + * between frames and updates */ + BL::Array persistent_id = b_dup->persistent_id(); + + /* sync object and mesh or light data */ + Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion); + + /* sync possible particle data, note particle_id + * starts counting at 1, first is dummy particle */ + if(!motion && object && sync_dupli_particle(*b_ob, *b_dup, object)) { + if(particle_id != object->particle_id) { + object->particle_id = particle_id; + scene->object_manager->tag_update(scene); + } + + particle_id++; + } + } - - ++b_index; } b_ob->dupli_list_clear(); } - /* sync particles and check if we should render or hide particle emitter */ + /* check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { - if(!motion) - sync_particles(*b_ob, *b_psys); + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) if(b_psys->settings().use_render_emitter()) hide = false; - } + + /* hide original object for duplis */ + BL::Object parent = b_ob->parent(); + if(parent && object_dupli_hide_original(parent.dupli_type())) + hide = true; if(!hide) { /* object itself */ Transform tfm = get_transform(b_ob->matrix_world()); - sync_object(*b_ob, 0, PointerRNA_NULL, tfm, ob_layer, motion, 0); + sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion); } - - particle_offset += num_particles; } cancel = progress.get_cancel(); diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index c4c6d2f79a3..769cd9f532d 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -17,6 +17,7 @@ */ #include "mesh.h" +#include "object.h" #include "particles.h" #include "blender_sync.h" @@ -28,170 +29,57 @@ CCL_NAMESPACE_BEGIN /* Utilities */ - -/* Particles Sync */ - -bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys) +bool BlenderSync::sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object) { - /* Particle data is only needed for - * a) Billboard render mode if object's own material uses particle info - * b) object/group render mode if any dupli object's material uses particle info - * - * Note: Meshes have to be synced at this point! - */ - bool need_update = false; - - switch (b_psys.settings().render_type()) { - /* XXX not implemented yet! - * billboards/strands would become part of the mesh data (?), - * so the mesh attributes would store whether particle info is required. - */ - #if 0 - case BL::ParticleSettings::render_type_BILLBOARD: - case BL::ParticleSettings::render_type_PATH: { /* for strand rendering */ - BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - break; - } - #endif - - case BL::ParticleSettings::render_type_OBJECT: { - BL::Object b_dupli_ob = b_psys.settings().dupli_object(); - if(b_dupli_ob) { - BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - } - break; - } - - case BL::ParticleSettings::render_type_GROUP: { - BL::Group b_dupli_group = b_psys.settings().dupli_group(); - if(b_dupli_group) { - BL::Group::objects_iterator b_gob; - for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) { - BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - } - } - break; - } - - default: - /* avoid compiler warning */ - break; + /* test if this dupli was generated from a particle sytem */ + BL::ParticleSystem b_psys = b_dup.particle_system(); + if(!b_psys) + return false; + + /* test if we need particle data */ + if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE)) + return false; + + /* don't handle child particles yet */ + BL::Array persistent_id = b_dup.persistent_id(); + + if(persistent_id[0] >= b_psys.particles.length()) + return false; + + /* find particle system */ + ParticleSystemKey key(b_ob, persistent_id); + ParticleSystem *psys; + + bool first_use = !particle_system_map.is_used(key); + bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key); + + /* no update needed? */ + if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update) + return true; + + /* first time used in this sync loop? clear and tag update */ + if(first_use) { + psys->particles.clear(); + psys->tag_update(scene); } - - return need_update; -} -static bool use_particle_system(BL::ParticleSystem b_psys) -{ - /* only use duplicator particles? disabled particle info for - * halo and billboard to reduce particle count. - * Probably not necessary since particles don't contain a huge amount - * of data compared to other textures. - */ - #if 0 - int render_type = b_psys->settings().render_type(); - return (render_type == BL::ParticleSettings::render_type_OBJECT - || render_type == BL::ParticleSettings::render_type_GROUP); - #endif + /* add particle */ + BL::Particle b_pa = b_psys.particles[persistent_id[0]]; + Particle pa; + pa.index = persistent_id[0]; + pa.age = b_scene.frame_current() - b_pa.birth_time(); + pa.lifetime = b_pa.lifetime(); + pa.location = get_float3(b_pa.location()); + pa.rotation = get_float4(b_pa.rotation()); + pa.size = b_pa.size(); + pa.velocity = get_float3(b_pa.velocity()); + pa.angular_velocity = get_float3(b_pa.angular_velocity()); + + psys->particles.push_back(pa); + + /* return that this object has particle data */ return true; } -static bool use_particle(BL::Particle b_pa, bool preview, bool show_unborn, bool use_dead) -{ - return b_pa.is_exist() && (!preview || b_pa.is_visible()) && - (b_pa.alive_state() != BL::Particle::alive_state_UNBORN || show_unborn) && - (b_pa.alive_state() != BL::Particle::alive_state_DEAD || use_dead); -} - -static int psys_count_particles(BL::ParticleSystem b_psys, bool preview) -{ - BL::ParticleSystem::particles_iterator b_pa; - bool show_unborn = b_psys.settings().show_unborn(); - bool use_dead = b_psys.settings().use_dead(); - int num = 0; - - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) - if(use_particle(*b_pa, preview, show_unborn, use_dead)) - ++num; - - return num; -} - -int BlenderSync::object_count_particles(BL::Object b_ob) -{ - BL::Object::particle_systems_iterator b_psys; - int num = 0; - - for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) - if(use_particle_system(*b_psys)) - num += psys_count_particles(*b_psys, preview); - - return num; -} - -void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys) -{ - /* depending on settings the psys may not even be rendered */ - if(!use_particle_system(b_psys)) - return; - - /* key to lookup particle system */ - ParticleSystemKey key(b_ob, b_psys); - ParticleSystem *psys; - - /* test if we need to sync */ - bool object_updated = false; - - if(particle_system_map.sync(&psys, b_ob, b_ob, key)) - object_updated = true; - - bool need_update = psys_need_update(b_psys); - - if(object_updated || need_update) { - bool show_unborn = b_psys.settings().show_unborn(); - bool use_dead = b_psys.settings().use_dead(); - - int num = psys_count_particles(b_psys, preview); - psys->particles.clear(); - psys->particles.reserve(num); - - BL::ParticleSystem::particles_iterator b_pa; - int index = 0; - - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { - if(use_particle(*b_pa, preview, show_unborn, use_dead)) { - Particle pa; - - pa.index = index; - pa.age = b_scene.frame_current() - b_pa->birth_time(); - pa.lifetime = b_pa->lifetime(); - pa.location = get_float3(b_pa->location()); - pa.rotation = get_float4(b_pa->rotation()); - pa.size = b_pa->size(); - pa.velocity = get_float3(b_pa->velocity()); - pa.angular_velocity = get_float3(b_pa->angular_velocity()); - - psys->particles.push_back(pa); - } - - ++index; - } - - psys->tag_update(scene); - } -} - CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index c047805c6ae..d164920ceff 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -146,6 +146,32 @@ static PyObject *draw_func(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject *reset_func(PyObject *self, PyObject *args) +{ + PyObject *pysession, *pydata, *pyscene; + + if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pyscene)) + return NULL; + + BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); + + PointerRNA dataptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr); + BL::BlendData b_data(dataptr); + + PointerRNA sceneptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr); + BL::Scene b_scene(sceneptr); + + Py_BEGIN_ALLOW_THREADS + + session->reset_session(b_data, b_scene); + + Py_END_ALLOW_THREADS + + Py_RETURN_NONE; +} + static PyObject *sync_func(PyObject *self, PyObject *value) { Py_BEGIN_ALLOW_THREADS @@ -217,6 +243,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float default_float = 0.0f; int default_int = 0; + std::string default_string = ""; if(param->isclosure) { socket_type = BL::NodeSocket::type_SHADER; @@ -252,6 +279,13 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) if(param->validdefault) default_float = param->fdefault[0]; } + else if(param->type.basetype == TypeDesc::STRING) { + socket_type = BL::NodeSocket::type_STRING; + if(param->validdefault) + default_string = param->sdefault[0]; + } + else + continue; } else continue; @@ -286,6 +320,10 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr); b_vector_sock.default_value(default_float4); } + else if(socket_type == BL::NodeSocket::type_STRING) { + BL::NodeSocketStringNone b_string_sock(b_sock.ptr); + b_string_sock.default_value(default_string); + } } used_sockets.insert(b_sock.ptr.data); @@ -342,6 +380,7 @@ static PyMethodDef methods[] = { {"render", render_func, METH_O, ""}, {"draw", draw_func, METH_VARARGS, ""}, {"sync", sync_func, METH_O, ""}, + {"reset", reset_func, METH_VARARGS, ""}, #ifdef WITH_OSL {"osl_update_node", osl_update_node_func, METH_VARARGS, ""}, {"osl_compile", osl_compile_func, METH_VARARGS, ""}, @@ -379,14 +418,23 @@ static CCLDeviceInfo *compute_device_list(DeviceType type) if(info.type == type || (info.type == DEVICE_MULTI && info.multi_devices[0].type == type)) { - CCLDeviceInfo cinfo = {info.id.c_str(), info.description.c_str(), i++}; + CCLDeviceInfo cinfo; + + strncpy(cinfo.identifier, info.id.c_str(), sizeof(cinfo.identifier)); + cinfo.identifier[info.id.length()] = '\0'; + + strncpy(cinfo.name, info.description.c_str(), sizeof(cinfo.name)); + cinfo.name[info.description.length()] = '\0'; + + cinfo.value = i++; + device_list.push_back(cinfo); } } /* null terminate */ if(!device_list.empty()) { - CCLDeviceInfo cinfo = {NULL, NULL, 0}; + CCLDeviceInfo cinfo = {"", "", 0}; device_list.push_back(cinfo); } } diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 01bd5f013e3..b8ed942f5b6 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -109,9 +109,53 @@ void BlenderSession::create_session() session->reset(buffer_params, session_params.samples); } +void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) +{ + b_data = b_data_; + b_scene = b_scene_; + + SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); + SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); + + width = b_engine.resolution_x(); + height = b_engine.resolution_y(); + + if(scene->params.modified(scene_params) || + session->params.modified(session_params)) + { + /* if scene or session parameters changed, it's easier to simply re-create + * them rather than trying to distinguish which settings need to be updated + */ + + delete session; + + create_session(); + + return; + } + + session->progress.reset(); + scene->reset(); + + /* peak memory usage should show current render peak, not peak for all renders + * made by this render session + */ + session->stats.mem_peak = session->stats.mem_used; + + /* sync object should be re-created */ + sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); + sync->sync_data(b_v3d, b_engine.camera_override()); + sync->sync_camera(b_engine.camera_override(), width, height); + + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height); + session->reset(buffer_params, session_params.samples); +} + void BlenderSession::free_session() { - delete sync; + if(sync) + delete sync; + delete session; } @@ -304,6 +348,15 @@ void BlenderSession::render() /* clear callback */ session->write_render_tile_cb = NULL; session->update_render_tile_cb = NULL; + + /* free all memory used (host and device), so we wouldn't leave render + * engine with extra memory allocated + */ + + session->device_free(); + + delete sync; + sync = NULL; } void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only) @@ -465,8 +518,8 @@ void BlenderSession::get_progress(float& progress, double& total_time) sample = session->progress.get_sample(); samples_per_tile = session->params.samples; - if(samples_per_tile) - progress = ((float)sample/(float)(tile_total * samples_per_tile)); + if(samples_per_tile && tile_total) + progress = ((float)sample / (float)(tile_total * samples_per_tile)); else progress = 0.0; } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index d52e0103bbf..7f3973ae873 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -46,6 +46,8 @@ public: void create_session(); void free_session(); + void reset_session(BL::BlendData b_data, BL::Scene b_scene); + /* offline render */ void render(); diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 9e3380c6f8e..c9380d8d58b 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -90,6 +90,8 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) return SHADER_SOCKET_COLOR; case BL::NodeSocket::type_SHADER: return SHADER_SOCKET_CLOSURE; + case BL::NodeSocket::type_STRING: + return SHADER_SOCKET_STRING; case BL::NodeSocket::type_BOOLEAN: case BL::NodeSocket::type_MESH: @@ -98,7 +100,7 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) } } -static void set_default_value(ShaderInput *input, BL::NodeSocket sock) +static void set_default_value(ShaderInput *input, BL::NodeSocket sock, BL::BlendData b_data, BL::ID b_id) { /* copy values for non linked inputs */ switch(input->type) { @@ -124,6 +126,11 @@ static void set_default_value(ShaderInput *input, BL::NodeSocket sock) input->set(get_float3(vec_sock.default_value())); break; } + case SHADER_SOCKET_STRING: { + BL::NodeSocketStringNone string_sock(sock); + input->set((ustring)blender_absolute_path(b_data, b_id, string_sock.default_value())); + break; + } case SHADER_SOCKET_CLOSURE: break; } @@ -173,6 +180,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen case BL::ShaderNode::type_OUTPUT: break; case BL::ShaderNode::type_SQUEEZE: break; case BL::ShaderNode::type_TEXTURE: break; + case BL::ShaderNode::type_FRAME: break; /* handled outside this function */ case BL::ShaderNode::type_GROUP: break; /* existing blender nodes */ @@ -366,6 +374,23 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = glass; break; } + case BL::ShaderNode::type_BSDF_REFRACTION: { + BL::ShaderNodeBsdfRefraction b_refraction_node(b_node); + RefractionBsdfNode *refraction = new RefractionBsdfNode(); + switch(b_refraction_node.distribution()) { + case BL::ShaderNodeBsdfRefraction::distribution_SHARP: + refraction->distribution = ustring("Sharp"); + break; + case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN: + refraction->distribution = ustring("Beckmann"); + break; + case BL::ShaderNodeBsdfRefraction::distribution_GGX: + refraction->distribution = ustring("GGX"); + break; + } + node = refraction; + break; + } case BL::ShaderNode::type_BSDF_TRANSLUCENT: { node = new TranslucentBsdfNode(); break; @@ -382,6 +407,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = new EmissionNode(); break; } + case BL::ShaderNode::type_AMBIENT_OCCLUSION: { + node = new AmbientOcclusionNode(); + break; + } case BL::ShaderNode::type_VOLUME_ISOTROPIC: { node = new IsotropicVolumeNode(); break; @@ -416,7 +445,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } case BL::ShaderNode::type_SCRIPT: { #ifdef WITH_OSL - if(scene->params.shadingsystem != SceneParams::OSL) + if(!scene->shader_manager->use_osl()) break; /* create script node */ @@ -435,7 +464,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) { script_node->input_names.push_back(ustring(b_input->name())); ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(b_input->type())); - set_default_value(input, *b_input); + set_default_value(input, *b_input, b_data, b_ntree); } BL::Node::outputs_iterator b_output; @@ -471,8 +500,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::Image b_image(b_image_node.image()); ImageTextureNode *image = new ImageTextureNode(); /* todo: handle generated/builtin images */ - if(b_image && b_image.source() != BL::Image::source_MOVIE) + if(b_image && b_image.source() != BL::Image::source_MOVIE) { image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); + image->animated = b_image_node.image_user().use_auto_refresh(); + } image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; image->projection_blend = b_image_node.projection_blend(); @@ -484,8 +515,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::ShaderNodeTexEnvironment b_env_node(b_node); BL::Image b_image(b_env_node.image()); EnvironmentTextureNode *env = new EnvironmentTextureNode(); - if(b_image && b_image.source() != BL::Image::source_MOVIE) + if(b_image && b_image.source() != BL::Image::source_MOVIE) { env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); + env->animated = b_env_node.image_user().use_auto_refresh(); + } env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping()); @@ -573,6 +606,23 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = sky; break; } + case BL::ShaderNode::type_NORMAL_MAP: { + BL::ShaderNodeNormalMap b_normal_map_node(b_node); + NormalMapNode *nmap = new NormalMapNode(); + nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()]; + nmap->attribute = b_normal_map_node.uv_map(); + node = nmap; + break; + } + case BL::ShaderNode::type_TANGENT: { + BL::ShaderNodeTangent b_tangent_node(b_node); + TangentNode *tangent = new TangentNode(); + tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()]; + tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()]; + tangent->attribute = b_tangent_node.uv_map(); + node = tangent; + break; + } } if(node && node != graph->output()) @@ -687,7 +737,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); /* default input values of the group node */ - set_default_value(proxy->inputs[0], *b_input); + set_default_value(proxy->inputs[0], *b_input, b_data, b_group_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { @@ -701,7 +751,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); /* default input values of internal, unlinked group outputs */ - set_default_value(proxy->inputs[0], b_output->group_socket()); + set_default_value(proxy->inputs[0], b_output->group_socket(), b_data, b_group_ntree); } add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap); @@ -721,7 +771,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha assert(input); /* copy values for non linked inputs */ - set_default_value(input, *b_input); + set_default_value(input, *b_input, b_data, b_ntree); } } } @@ -775,7 +825,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha /* Sync Materials */ -void BlenderSync::sync_materials() +void BlenderSync::sync_materials(bool update_all) { shader_map.set_default(scene->shaders[scene->default_surface]); @@ -786,7 +836,7 @@ void BlenderSync::sync_materials() Shader *shader; /* test if we need to sync */ - if(shader_map.sync(&shader, *b_mat)) { + if(shader_map.sync(&shader, *b_mat) || update_all) { ShaderGraph *graph = new ShaderGraph(); shader->name = b_mat->name().c_str(); @@ -822,14 +872,14 @@ void BlenderSync::sync_materials() /* Sync World */ -void BlenderSync::sync_world() +void BlenderSync::sync_world(bool update_all) { Background *background = scene->background; Background prevbackground = *background; BL::World b_world = b_scene.world(); - if(world_recalc || b_world.ptr.data != world_map) { + if(world_recalc || update_all || b_world.ptr.data != world_map) { Shader *shader = scene->shaders[scene->default_background]; ShaderGraph *graph = new ShaderGraph(); @@ -876,7 +926,7 @@ void BlenderSync::sync_world() /* Sync Lamps */ -void BlenderSync::sync_lamps() +void BlenderSync::sync_lamps(bool update_all) { shader_map.set_default(scene->shaders[scene->default_light]); @@ -887,7 +937,7 @@ void BlenderSync::sync_lamps() Shader *shader; /* test if we need to sync */ - if(shader_map.sync(&shader, *b_lamp)) { + if(shader_map.sync(&shader, *b_lamp) || update_all) { ShaderGraph *graph = new ShaderGraph(); /* create nodes */ @@ -926,11 +976,20 @@ void BlenderSync::sync_lamps() void BlenderSync::sync_shaders() { + /* for auto refresh images */ + bool auto_refresh_update = false; + + if(preview) { + ImageManager *image_manager = scene->image_manager; + int frame = b_scene.frame_current(); + auto_refresh_update = image_manager->set_animation_frame_update(frame); + } + shader_map.pre_sync(); - sync_world(); - sync_lamps(); - sync_materials(); + sync_world(auto_refresh_update); + sync_lamps(auto_refresh_update); + sync_materials(auto_refresh_update); /* false = don't delete unused shaders, not supported */ shader_map.post_sync(false); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index c63f72c68c6..d0e8b508df6 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -179,12 +179,14 @@ void BlenderSync::sync_integrator() integrator->sample_clamp = get_float(cscene, "sample_clamp"); #ifdef __CAMERA_MOTION__ - if(integrator->motion_blur != r.use_motion_blur()) { - scene->object_manager->tag_update(scene); - scene->camera->tag_update(); - } + if(!preview) { + if(integrator->motion_blur != r.use_motion_blur()) { + scene->object_manager->tag_update(scene); + scene->camera->tag_update(); + } - integrator->motion_blur = (!preview && r.use_motion_blur()); + integrator->motion_blur = r.use_motion_blur(); + } #endif integrator->diffuse_samples = get_int(cscene, "diffuse_samples"); @@ -241,6 +243,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) render_layer.use_localview = (b_v3d.local_view() ? true : false); render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview); render_layer.layer = render_layer.scene_layer; + render_layer.exclude_layer = 0; render_layer.holdout_layer = 0; render_layer.material_override = PointerRNA_NULL; render_layer.use_background = true; @@ -258,10 +261,16 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) { if((!layer && first_layer) || (layer && b_rlay->name() == layer)) { render_layer.name = b_rlay->name(); - render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude()); - render_layer.layer = get_layer(b_rlay->layers()); + render_layer.holdout_layer = get_layer(b_rlay->layers_zmask()); + render_layer.exclude_layer = get_layer(b_rlay->layers_exclude()); + + render_layer.scene_layer = get_layer(b_scene.layers()) & ~render_layer.exclude_layer; + render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer; + + render_layer.layer = get_layer(b_rlay->layers()); render_layer.layer |= render_layer.holdout_layer; + render_layer.material_override = b_rlay->material_override(); render_layer.use_background = b_rlay->use_sky(); render_layer.use_viewport_visibility = false; @@ -277,6 +286,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) { + BL::RenderSettings r = b_scene.render(); SceneParams params; PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); int shadingsystem = RNA_enum_get(&cscene, "shading_system"); @@ -294,6 +304,8 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits"); params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false; + params.persistent_images = (background)? r.use_persistent_data(): false; + return params; } @@ -379,7 +391,10 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.start_resolution = get_int(cscene, "preview_start_resolution"); /* other parameters */ - params.threads = b_scene.render().threads(); + if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED) + params.threads = b_scene.render().threads(); + else + params.threads = 0; params.cancel_timeout = get_float(cscene, "debug_cancel_timeout"); params.reset_timeout = get_float(cscene, "debug_reset_timeout"); diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 36cd5e684a7..d3d21fbdf72 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -42,6 +42,7 @@ class Film; class Light; class Mesh; class Object; +class ParticleSystem; class Scene; class Shader; class ShaderGraph; @@ -67,33 +68,33 @@ public: private: /* sync */ - void sync_lamps(); - void sync_materials(); + void sync_lamps(bool update_all); + void sync_materials(bool update_all); void sync_objects(BL::SpaceView3D b_v3d, int motion = 0); void sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override); void sync_film(); void sync_integrator(); void sync_view(); - void sync_world(); + void sync_world(bool update_all); void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer); void sync_shaders(); void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); Mesh *sync_mesh(BL::Object b_ob, bool object_updated); - void sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, int particle_id); - void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm); + Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion); + void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm); void sync_background_light(); void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion); void sync_camera_motion(BL::Object b_ob, int motion); - void sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys); + + /* particles */ + bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object); /* util */ void find_shader(BL::ID id, vector& used_shaders, int default_shader); bool BKE_object_is_modified(BL::Object b_ob); bool object_is_mesh(BL::Object b_ob); bool object_is_light(BL::Object b_ob); - bool psys_need_update(BL::ParticleSystem b_psys); - int object_count_particles(BL::Object b_ob); /* variables */ BL::RenderEngine b_engine; @@ -115,7 +116,8 @@ private: struct RenderLayerInfo { RenderLayerInfo() - : scene_layer(0), layer(0), holdout_layer(0), + : scene_layer(0), layer(0), + holdout_layer(0), exclude_layer(0), material_override(PointerRNA_NULL), use_background(true), use_viewport_visibility(false), @@ -126,6 +128,7 @@ private: uint scene_layer; uint layer; uint holdout_layer; + uint exclude_layer; BL::Material material_override; bool use_background; bool use_viewport_visibility; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index df1e99882b8..0a9f2dd06aa 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -284,6 +284,12 @@ public: return recalc; } + bool is_used(const K& key) + { + T *data = find(key); + return (data) ? used_set.find(data) != used_set.end() : false; + } + void used(T *data) { /* tag data as still in use */ @@ -343,27 +349,63 @@ protected: /* Object Key */ +enum { OBJECT_PERSISTENT_ID_SIZE = 8 }; + struct ObjectKey { void *parent; - int index; + int id[OBJECT_PERSISTENT_ID_SIZE]; void *ob; - ObjectKey(void *parent_, int index_, void *ob_) - : parent(parent_), index(index_), ob(ob_) {} + ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_) + : parent(parent_), ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } bool operator<(const ObjectKey& k) const - { return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); } + { + if(ob < k.ob) { + return true; + } + else if(ob == k.ob) { + if(parent < k.parent) + return true; + else if(parent == k.parent) + return memcmp(id, k.id, sizeof(id)) < 0; + } + + return false; + } }; +/* Particle System Key */ + struct ParticleSystemKey { void *ob; - void *psys; + int id[OBJECT_PERSISTENT_ID_SIZE]; - ParticleSystemKey(void *ob_, void *psys_) - : ob(ob_), psys(psys_) {} + ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) + : ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } bool operator<(const ParticleSystemKey& k) const - { return (ob < k.ob && psys < k.psys); } + { + /* first id is particle index, we don't compare that */ + if(ob < k.ob) + return true; + else if(ob == k.ob) + return memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0; + + return false; + } }; CCL_NAMESPACE_END diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 332d3d74715..790049898ff 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -17,33 +17,6 @@ else() set(CYCLES_GLEW_LIBRARY extern_glew) endif() -########################################################################### -# Partio - -if(WITH_CYCLES_PARTIO) - - set(CYCLES_PARTIO "" CACHE PATH "Path to Partio installation") - - message(STATUS "CYCLES_PARTIO = ${CYCLES_PARTIO}") - - find_library(PARTIO_LIBRARIES NAMES partio PATHS ${CYCLES_PARTIO}/lib) - find_path(PARTIO_INCLUDES Partio.h ${CYCLES_PARTIO}/include) - - find_package(ZLIB) - - if(PARTIO_INCLUDES AND PARTIO_LIBRARIES AND ZLIB_LIBRARIES) - list(APPEND PARTIO_LIBRARIES ${ZLIB_LIBRARIES}) - set(PARTIO_FOUND TRUE) - message(STATUS "PARTIO includes = ${PARTIO_INCLUDES}") - message(STATUS "PARTIO library = ${PARTIO_LIBRARIES}") - else() - message(STATUS "PARTIO not found") - endif() - - include_directories(${PARTIO_INCLUDES}) - -endif() - ########################################################################### # CUDA diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 550da2982a3..1248b42b738 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -78,13 +78,13 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w glDisable(GL_BLEND); } -Device *Device::create(DeviceInfo& info, Stats &stats, bool background, int threads) +Device *Device::create(DeviceInfo& info, Stats &stats, bool background) { Device *device; switch(info.type) { case DEVICE_CPU: - device = device_cpu_create(info, stats, threads); + device = device_cpu_create(info, stats); break; #ifdef WITH_CUDA case DEVICE_CUDA: @@ -189,18 +189,6 @@ vector& Device::available_devices() { static vector devices; static bool devices_init = false; - static double device_update_time = 0.0; - - /* only update device list if we're not actively rendering already, things - * could go very wrong if a device suddenly becomes (un)available. also do - * it only every 5 seconds. it not super cpu intensive but don't want to do - * it on every redraw. */ - if(devices_init) { - if(!TaskScheduler::active() && (time_dt() > device_update_time + 5.0)) { - devices.clear(); - devices_init = false; - } - } if(!devices_init) { #ifdef WITH_CUDA @@ -224,7 +212,6 @@ vector& Device::available_devices() #endif devices_init = true; - device_update_time = time_dt(); } return devices; diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 95da0a89833..9840687b76a 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -134,7 +134,7 @@ public: virtual int device_number(Device *sub_device) { return 0; } /* static */ - static Device *create(DeviceInfo& info, Stats &stats, bool background = true, int threads = 0); + static Device *create(DeviceInfo& info, Stats &stats, bool background = true); static DeviceType type_from_string(const char *name); static string string_from_type(DeviceType type); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 519c458ffdf..a1d7706a34e 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -23,9 +23,12 @@ #include "device_intern.h" #include "kernel.h" +#include "kernel_compat_cpu.h" #include "kernel_types.h" +#include "kernel_globals.h" #include "osl_shader.h" +#include "osl_globals.h" #include "buffers.h" @@ -43,11 +46,16 @@ class CPUDevice : public Device { public: TaskPool task_pool; - KernelGlobals *kg; + KernelGlobals kernel_globals; +#ifdef WITH_OSL + OSLGlobals osl_globals; +#endif - CPUDevice(Stats &stats, int threads_num) : Device(stats) + CPUDevice(Stats &stats) : Device(stats) { - kg = kernel_globals_create(); +#ifdef WITH_OSL + kernel_globals.osl = &osl_globals; +#endif /* do now to avoid thread issues */ system_cpu_support_optimized(); @@ -56,7 +64,6 @@ public: ~CPUDevice() { task_pool.stop(); - kernel_globals_free(kg); } bool support_advanced_shading() @@ -95,12 +102,12 @@ public: void const_copy_to(const char *name, void *host, size_t size) { - kernel_const_copy(kg, name, host, size); + kernel_const_copy(&kernel_globals, name, host, size); } void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic) { - kernel_tex_copy(kg, name, mem.data_pointer, mem.data_width, mem.data_height); + kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height); mem.device_pointer = mem.data_pointer; stats.mem_alloc(mem.memory_size()); @@ -116,7 +123,7 @@ public: void *osl_memory() { #ifdef WITH_OSL - return kernel_osl_memory(kg); + return &osl_globals; #else return NULL; #endif @@ -148,9 +155,10 @@ public: return; } + KernelGlobals kg = kernel_globals; + #ifdef WITH_OSL - if(kernel_osl_use(kg)) - OSLShader::thread_init(kg); + OSLShader::thread_init(&kg, &kernel_globals, &osl_globals); #endif RenderTile tile; @@ -171,7 +179,7 @@ public: for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { - kernel_cpu_optimized_path_trace(kg, render_buffer, rng_state, + kernel_cpu_optimized_path_trace(&kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); } } @@ -192,7 +200,7 @@ public: for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { - kernel_cpu_path_trace(kg, render_buffer, rng_state, + kernel_cpu_path_trace(&kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); } } @@ -212,8 +220,7 @@ public: } #ifdef WITH_OSL - if(kernel_osl_use(kg)) - OSLShader::thread_free(kg); + OSLShader::thread_free(&kg); #endif } @@ -223,7 +230,7 @@ public: if(system_cpu_support_optimized()) { for(int y = task.y; y < task.y + task.h; y++) for(int x = task.x; x < task.x + task.w; x++) - kernel_cpu_optimized_tonemap(kg, (uchar4*)task.rgba, (float*)task.buffer, + kernel_cpu_optimized_tonemap(&kernel_globals, (uchar4*)task.rgba, (float*)task.buffer, task.sample, task.resolution, x, y, task.offset, task.stride); } else @@ -231,22 +238,23 @@ public: { for(int y = task.y; y < task.y + task.h; y++) for(int x = task.x; x < task.x + task.w; x++) - kernel_cpu_tonemap(kg, (uchar4*)task.rgba, (float*)task.buffer, + kernel_cpu_tonemap(&kernel_globals, (uchar4*)task.rgba, (float*)task.buffer, task.sample, task.resolution, x, y, task.offset, task.stride); } } void thread_shader(DeviceTask& task) { + KernelGlobals kg = kernel_globals; + #ifdef WITH_OSL - if(kernel_osl_use(kg)) - OSLShader::thread_init(kg); + OSLShader::thread_init(&kg, &kernel_globals, &osl_globals); #endif #ifdef WITH_OPTIMIZED_KERNEL if(system_cpu_support_optimized()) { for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) { - kernel_cpu_optimized_shader(kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); + kernel_cpu_optimized_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); if(task_pool.cancelled()) break; @@ -256,7 +264,7 @@ public: #endif { for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) { - kernel_cpu_shader(kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); + kernel_cpu_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); if(task_pool.cancelled()) break; @@ -264,8 +272,7 @@ public: } #ifdef WITH_OSL - if(kernel_osl_use(kg)) - OSLShader::thread_free(kg); + OSLShader::thread_free(&kg); #endif } @@ -274,7 +281,7 @@ public: /* split task into smaller ones, more than number of threads for uneven * workloads where some parts of the image render slower than others */ list tasks; - task.split(tasks, TaskScheduler::num_threads()+1); + task.split(tasks, TaskScheduler::num_threads()); foreach(DeviceTask& task, tasks) task_pool.push(new CPUDeviceTask(this, task)); @@ -291,9 +298,9 @@ public: } }; -Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads) +Device *device_cpu_create(DeviceInfo& info, Stats &stats) { - return new CPUDevice(stats, threads); + return new CPUDevice(stats); } void device_cpu_info(vector& devices) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index d797c0f09ca..14f8cfa8767 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -60,7 +60,7 @@ public: return (CUdeviceptr)mem; } - const char *cuda_error_string(CUresult result) + static const char *cuda_error_string(CUresult result) { switch(result) { case CUDA_SUCCESS: return "No errors"; @@ -915,12 +915,21 @@ Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background) void device_cuda_info(vector& devices) { + CUresult result; int count = 0; - if(cuInit(0) != CUDA_SUCCESS) + result = cuInit(0); + if(result != CUDA_SUCCESS) { + if(result != CUDA_ERROR_NO_DEVICE) + fprintf(stderr, "CUDA cuInit: %s\n", CUDADevice::cuda_error_string(result)); return; - if(cuDeviceGetCount(&count) != CUDA_SUCCESS) + } + + result = cuDeviceGetCount(&count); + if(result != CUDA_SUCCESS) { + fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", CUDADevice::cuda_error_string(result)); return; + } vector display_devices; diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h index 02fbac6860e..b49ebba3e8b 100644 --- a/intern/cycles/device/device_intern.h +++ b/intern/cycles/device/device_intern.h @@ -23,7 +23,7 @@ CCL_NAMESPACE_BEGIN class Device; -Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads); +Device *device_cpu_create(DeviceInfo& info, Stats &stats); Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background); Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background); Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address); diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp index c85e182d629..b3f02deaf6f 100644 --- a/intern/cycles/device/device_task.cpp +++ b/intern/cycles/device/device_task.cpp @@ -101,7 +101,7 @@ void DeviceTask::update_progress(RenderTile &rtile) if(update_tile_sample) { double current_time = time_dt(); - if (current_time - last_update_time >= 1.0f) { + if (current_time - last_update_time >= 1.0) { update_tile_sample(rtile); last_update_time = current_time; diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 82b0605ab6b..5a570328948 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -51,6 +51,7 @@ set(SRC_CLOSURE_HEADERS closure/bsdf_diffuse.h closure/bsdf_microfacet.h closure/bsdf_oren_nayar.h + closure/bsdf_phong_ramp.h closure/bsdf_reflection.h closure/bsdf_refraction.h closure/bsdf_transparent.h diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript index 14890164a42..730f758194e 100644 --- a/intern/cycles/kernel/SConscript +++ b/intern/cycles/kernel/SConscript @@ -32,16 +32,17 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: kernel_file = os.path.join(source_dir, "kernel.cu") util_dir = os.path.join(source_dir, "../util") svm_dir = os.path.join(source_dir, "../svm") + closure_dir = os.path.join(source_dir, "../closure") # nvcc flags nvcc_flags = "-m%s" % (bits) nvcc_flags += " --cubin --ptxas-options=\"-v\" --maxrregcount=24" nvcc_flags += " --opencc-options -OPT:Olimit=0" nvcc_flags += " -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -DNVCC" - nvcc_flags += " -I \"%s\" -I \"%s\"" % (util_dir, svm_dir) + nvcc_flags += " -I \"%s\" -I \"%s\" -I \"%s\"" % (util_dir, svm_dir, closure_dir) # dependencies - dependencies = ['kernel.cu'] + kernel.Glob('*.h') + kernel.Glob('../util/*.h') + kernel.Glob('svm/*.h') + dependencies = ['kernel.cu'] + kernel.Glob('*.h') + kernel.Glob('../util/*.h') + kernel.Glob('svm/*.h') + kernel.Glob('closure/*.h') last_cubin_file = None # add command for each cuda architecture diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h new file mode 100644 index 00000000000..575a798aed4 --- /dev/null +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -0,0 +1,140 @@ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2012, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __BSDF_PHONG_RAMP_H__ +#define __BSDF_PHONG_RAMP_H__ + +CCL_NAMESPACE_BEGIN + +__device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float3 colors[8], float pos) +{ + int MAXCOLORS = 8; + + float npos = pos * (float)(MAXCOLORS - 1); + int ipos = (int)npos; + if (ipos >= (MAXCOLORS - 1)) + return colors[MAXCOLORS - 1]; + float offset = npos - (float)ipos; + return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset; +} + +__device int bsdf_phong_ramp_setup(ShaderClosure *sc) +{ + sc->type = CLOSURE_BSDF_PHONG_RAMP_ID; + return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; +} + +__device void bsdf_phong_ramp_blur(ShaderClosure *sc, float roughness) +{ +} + +__device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf) +{ + float m_exponent = sc->data0; + float cosNI = dot(sc->N, omega_in); + float cosNO = dot(sc->N, I); + + if (cosNI > 0 && cosNO > 0) { + // reflect the view vector + float3 R = (2 * cosNO) * sc->N - I; + float cosRI = dot(R, omega_in); + if (cosRI > 0) { + float cosp = powf(cosRI, m_exponent); + float common = 0.5f * (float) M_1_PI_F * cosp; + float out = cosNI * (m_exponent + 2) * common; + *pdf = (m_exponent + 1) * common; + return bsdf_phong_ramp_get_color(sc, colors, cosp) * out; + } + } + + return make_float3(0.0f, 0.0f, 0.0f); +} + +__device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf) +{ + return make_float3(0.0f, 0.0f, 0.0f); +} + +__device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colors[8], float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +{ + float cosNO = dot(sc->N, I); + float m_exponent = sc->data0; + + if (cosNO > 0) { + // reflect the view vector + float3 R = (2 * cosNO) * sc->N - I; + +#ifdef __RAY_DIFFERENTIALS__ + *domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx; + *domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->N - dIdy; +#endif + + float3 T, B; + make_orthonormals (R, &T, &B); + float phi = 2 * M_PI_F * randu; + float cosTheta = powf(randv, 1 / (m_exponent + 1)); + float sinTheta2 = 1 - cosTheta * cosTheta; + float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; + *omega_in = (cosf(phi) * sinTheta) * T + + (sinf(phi) * sinTheta) * B + + ( cosTheta) * R; + if (dot(Ng, *omega_in) > 0.0f) + { + // common terms for pdf and eval + float cosNI = dot(sc->N, *omega_in); + // make sure the direction we chose is still in the right hemisphere + if (cosNI > 0) + { + float cosp = powf(cosTheta, m_exponent); + float common = 0.5f * M_1_PI_F * cosp; + *pdf = (m_exponent + 1) * common; + float out = cosNI * (m_exponent + 2) * common; + *eval = bsdf_phong_ramp_get_color(sc, colors, cosp) * out; + +#ifdef __RAY_DIFFERENTIALS__ + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // exponent but the exact relationship is complex and + // requires more ops than are practical. + *domega_in_dx *= 10; + *domega_in_dy *= 10; +#endif + } + } + } + return LABEL_REFLECT|LABEL_GLOSSY; +} + + +CCL_NAMESPACE_END + +#endif /* __BSDF_PHONG_RAMP_H__ */ diff --git a/intern/cycles/kernel/closure/bsdf_ward.h b/intern/cycles/kernel/closure/bsdf_ward.h index 9c81548a2c3..dbddcf20dba 100644 --- a/intern/cycles/kernel/closure/bsdf_ward.h +++ b/intern/cycles/kernel/closure/bsdf_ward.h @@ -68,7 +68,10 @@ __device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I, float cosNO = dot(N, I); float cosNI = dot(N, omega_in); - if(cosNI > 0 && cosNO > 0) { + if(cosNI > 0.0f && cosNO > 0.0f) { + cosNO = max(cosNO, 1e-4f); + cosNI = max(cosNI, 1e-4f); + // get half vector and get x,y basis on the surface for anisotropy float3 H = normalize(omega_in + I); // normalize needed for pdf float3 X, Y; @@ -103,7 +106,7 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa float3 T = sc->T; float cosNO = dot(N, I); - if(cosNO > 0) { + if(cosNO > 0.0f) { // get x,y basis on the surface for anisotropy float3 X, Y; make_orthonormals_tangent(N, T, &X, &Y); @@ -165,6 +168,9 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa if(dot(Ng, *omega_in) > 0) { float cosNI = dot(N, *omega_in); if(cosNI > 0) { + cosNO = max(cosNO, 1e-4f); + cosNI = max(cosNI, 1e-4f); + // eq. 9 float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); float denom = 4 * M_PI_F * m_ax * m_ay * oh * dotn * dotn * dotn; diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp index 62d79bdd946..d760e63a290 100644 --- a/intern/cycles/kernel/kernel.cpp +++ b/intern/cycles/kernel/kernel.cpp @@ -29,38 +29,6 @@ CCL_NAMESPACE_BEGIN -/* Globals */ - -KernelGlobals *kernel_globals_create() -{ - KernelGlobals *kg = new KernelGlobals(); -#ifdef WITH_OSL - kg->osl.use = false; -#endif - return kg; -} - -void kernel_globals_free(KernelGlobals *kg) -{ - delete kg; -} - -/* OSL */ - -#ifdef WITH_OSL - -void *kernel_osl_memory(KernelGlobals *kg) -{ - return (void*)&kg->osl; -} - -bool kernel_osl_use(KernelGlobals *kg) -{ - return kg->osl.use; -} - -#endif - /* Memory Copy */ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size) diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 2f2314c9a8b..d99beb8905a 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -301,10 +301,6 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) __device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp) { - #ifdef __OSL__ - using std::isfinite; - #endif - float sum = fabsf((*L_sum).x) + fabsf((*L_sum).y) + fabsf((*L_sum).z); if(!isfinite(sum)) { diff --git a/intern/cycles/kernel/kernel_attribute.h b/intern/cycles/kernel/kernel_attribute.h index 2774f5e924b..b7ad731c883 100644 --- a/intern/cycles/kernel/kernel_attribute.h +++ b/intern/cycles/kernel/kernel_attribute.h @@ -19,13 +19,6 @@ #ifndef __KERNEL_ATTRIBUTE_CL__ #define __KERNEL_ATTRIBUTE_CL__ -#include "util_types.h" - -#ifdef __OSL__ -#include -#include "util_attribute.h" -#endif - CCL_NAMESPACE_BEGIN /* note: declared in kernel.h, have to add it here because kernel.h is not available */ @@ -33,20 +26,9 @@ bool kernel_osl_use(KernelGlobals *kg); __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id) { - #ifdef __OSL__ - if (kernel_osl_use(kg)) { - /* for OSL, a hash map is used to lookup the attribute by name. */ - OSLGlobals::AttributeMap &attr_map = kg->osl.attribute_map[sd->object]; - ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id))); - OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); - if (it != attr_map.end()) { - const OSLGlobals::Attribute &osl_attr = it->second; - /* return result */ - return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset; - } - else - return (int)ATTR_STD_NOT_FOUND; + if (kg->osl) { + return OSLShader::find_attribute(kg, sd, id); } else #endif diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 1b2fe8c56ee..97d37a8b3f4 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -65,7 +65,7 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float #ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) - transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); + transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time); #endif ray->P = transform_point(&cameratoworld, ray->P); @@ -108,7 +108,7 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa #ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) - transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); + transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time); #endif ray->P = transform_point(&cameratoworld, ray->P); @@ -182,7 +182,7 @@ __device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float ra #ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) - transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); + transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time); #endif ray->P = transform_point(&cameratoworld, ray->P); @@ -229,5 +229,20 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo camera_sample_panorama(kg, raster_x, raster_y, lens_u, lens_v, ray); } +/* Utilities */ + +__device_inline float camera_distance(KernelGlobals *kg, float3 P) +{ + Transform cameratoworld = kernel_data.cam.cameratoworld; + float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + + if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) { + float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z); + return fabsf(dot((P - camP), camD)); + } + else + return len(P - camP); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h index 1e56c11ab90..529b7b8768f 100644 --- a/intern/cycles/kernel/kernel_globals.h +++ b/intern/cycles/kernel/kernel_globals.h @@ -18,14 +18,6 @@ /* Constant Globals */ -#ifdef __KERNEL_CPU__ - -#ifdef __OSL__ -#include "osl_globals.h" -#endif - -#endif - CCL_NAMESPACE_BEGIN /* On the CPU, we pass along the struct KernelGlobals to nearly everywhere in @@ -35,6 +27,12 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_CPU__ +#ifdef __OSL__ +struct OSLGlobals; +struct OSLThreadData; +struct OSLShadingSystem; +#endif + #define MAX_BYTE_IMAGES 512 #define MAX_FLOAT_IMAGES 5 @@ -51,7 +49,9 @@ typedef struct KernelGlobals { #ifdef __OSL__ /* On the CPU, we also have the OSL globals here. Most data structures are shared * with SVM, the difference is in the shaders and object/mesh attributes. */ - OSLGlobals osl; + OSLGlobals *osl; + OSLShadingSystem *osl_ss; + OSLThreadData *osl_tdata; #endif } KernelGlobals; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 2791b3abbb6..97ae2d3db87 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -350,10 +350,9 @@ __device int light_distribution_sample(KernelGlobals *kg, float randt) } } - first = max(0, first-1); - kernel_assert(first >= 0 && first < kernel_data.integrator.num_distribution); - - return first; + /* clamping should not be needed but float rounding errors seem to + * make this fail on rare occasions */ + return clamp(first-1, 0, kernel_data.integrator.num_distribution-1); } /* Generic Light */ diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 112bfbb86b5..2b38544e527 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -23,9 +23,8 @@ enum ObjectTransform { OBJECT_INVERSE_TRANSFORM = 3, OBJECT_PROPERTIES = 6, OBJECT_TRANSFORM_MOTION_PRE = 8, - OBJECT_TRANSFORM_MOTION_MID = 12, - OBJECT_TRANSFORM_MOTION_POST = 16, - OBJECT_DUPLI = 20 + OBJECT_TRANSFORM_MOTION_POST = 12, + OBJECT_DUPLI = 16 }; __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type) @@ -44,24 +43,19 @@ __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, #ifdef __OBJECT_MOTION__ __device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time) { - MotionTransform motion; + DecompMotionTransform motion; int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE; - motion.pre.x = kernel_tex_fetch(__objects, offset + 0); - motion.pre.y = kernel_tex_fetch(__objects, offset + 1); - motion.pre.z = kernel_tex_fetch(__objects, offset + 2); - motion.pre.w = kernel_tex_fetch(__objects, offset + 3); + motion.mid.x = kernel_tex_fetch(__objects, offset + 0); + motion.mid.y = kernel_tex_fetch(__objects, offset + 1); + motion.mid.z = kernel_tex_fetch(__objects, offset + 2); + motion.mid.w = kernel_tex_fetch(__objects, offset + 3); - motion.mid.x = kernel_tex_fetch(__objects, offset + 4); - motion.mid.y = kernel_tex_fetch(__objects, offset + 5); - motion.mid.z = kernel_tex_fetch(__objects, offset + 6); - motion.mid.w = kernel_tex_fetch(__objects, offset + 7); - - motion.post.x = kernel_tex_fetch(__objects, offset + 8); - motion.post.y = kernel_tex_fetch(__objects, offset + 9); - motion.post.z = kernel_tex_fetch(__objects, offset + 10); - motion.post.w = kernel_tex_fetch(__objects, offset + 11); + motion.pre_x = kernel_tex_fetch(__objects, offset + 4); + motion.pre_y = kernel_tex_fetch(__objects, offset + 5); + motion.post_x = kernel_tex_fetch(__objects, offset + 6); + motion.post_y = kernel_tex_fetch(__objects, offset + 7); Transform tfm; transform_motion_interpolate(&tfm, &motion, time); diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 42733d691e0..7f8b611ba14 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -52,9 +52,7 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float if(!(path_flag & PATH_RAY_TRANSPARENT)) { if(sample == 0) { if(flag & PASS_DEPTH) { - Transform tfm = kernel_data.cam.worldtocamera; - float depth = len(transform_point(&tfm, sd->P)); - + float depth = camera_distance(kg, sd->P); kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth); } if(flag & PASS_OBJECT_ID) { diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 817f254a5e5..3588b09c790 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -16,10 +16,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifdef __OSL__ +#include "osl_shader.h" +#endif + #include "kernel_differential.h" #include "kernel_montecarlo.h" #include "kernel_projection.h" #include "kernel_object.h" +#include "kernel_attribute.h" +#include "kernel_projection.h" #include "kernel_triangle.h" #ifdef __QBVH__ #include "kernel_qbvh.h" @@ -326,15 +332,18 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { + if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { /* todo: solve correlation */ float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U); float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V); + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { Ray light_ray; @@ -347,10 +356,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor; + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(&L, throughput, ao_bsdf, ao_shadow, state.bounce); - } } } #endif @@ -423,7 +430,12 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, /* setup ray */ ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng); ray.D = bsdf_omega_in; - ray.t = FLT_MAX; + + if(state.bounce == 0) + ray.t -= sd.ray_length; /* clipping works through transparent */ + else + ray.t = FLT_MAX; + #ifdef __RAY_DIFFERENTIALS__ ray.dP = sd.dP; ray.dD = bsdf_domega_in; @@ -503,15 +515,18 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { + if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { /* todo: solve correlation */ float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U); float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V); + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { Ray light_ray; @@ -524,10 +539,8 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor; + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(L, throughput, ao_bsdf, ao_shadow, state.bounce); - } } } #endif @@ -706,10 +719,12 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { + if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { int num_samples = kernel_data.integrator.ao_samples; float num_samples_inv = 1.0f/num_samples; float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); for(int j = 0; j < num_samples; j++) { /* todo: solve correlation */ @@ -719,7 +734,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { Ray light_ray; @@ -732,10 +747,8 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*ao_factor; + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(&L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce); - } } } } @@ -885,6 +898,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam path_state_next(kg, &state, LABEL_TRANSPARENT); ray.P = ray_offset(sd.P, -sd.Ng); + ray.t -= sd.ray_length; /* clipping works through transparent */ } float3 L_sum = path_radiance_sum(kg, &L); diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h index 64747bcb42e..6516b9e4d82 100644 --- a/intern/cycles/kernel/kernel_projection.h +++ b/intern/cycles/kernel/kernel_projection.h @@ -98,7 +98,7 @@ __device float3 fisheye_to_direction(float u, float v, float fov) return make_float3(0.0f, 0.0f, 0.0f); float phi = acosf((r != 0.0f)? u/r: 0.0f); - float theta = asinf(r) * (fov / M_PI_F); + float theta = r * fov * 0.5f; if(v < 0.0f) phi = -phi; diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 86886a6a231..98a7ec59d7b 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -26,10 +26,6 @@ * */ -#ifdef __OSL__ -#include "osl_shader.h" -#endif - #include "closure/bsdf.h" #include "closure/emissive.h" #include "closure/volume.h" @@ -61,7 +57,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::init(kg, sd); #endif @@ -147,7 +143,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, int shader, int object, int prim, float u, float v, float t, float time) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::init(kg, sd); #endif @@ -278,7 +274,7 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::init(kg, sd); #endif @@ -387,7 +383,7 @@ __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd, bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass); #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) return _shader_bsdf_multi_eval_osl(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); else #endif @@ -444,7 +440,7 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, *pdf = 0.0f; #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); else #endif @@ -456,7 +452,7 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, if(sd->num_closure > 1) { float sweight = sc->sample_weight; #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) _shader_bsdf_multi_eval_osl(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); else #endif @@ -483,7 +479,7 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd, *pdf = 0.0f; #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); else #endif @@ -503,7 +499,7 @@ __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughnes if(CLOSURE_IS_BSDF(sc->type)) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::bsdf_blur(sc, roughness); else #endif @@ -599,6 +595,44 @@ __device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd) #endif } +__device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N) +{ +#ifdef __MULTI_CLOSURE__ + float3 eval = make_float3(0.0f, 0.0f, 0.0f); + + *N = make_float3(0.0f, 0.0f, 0.0f); + + for(int i = 0; i< sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + + if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { + eval += sc->weight*ao_factor; + *N += sc->N*average(sc->weight); + } + if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) { + eval += sc->weight; + *N += sd->N*average(sc->weight); + } + } + + if(is_zero(*N)) + *N = sd->N; + else + *N = normalize(*N); + + return eval; +#else + *N = sd->N; + + if(CLOSURE_IS_BSDF_DIFFUSE(sd->closure.type)) + return sd->closure.weight*ao_factor; + else if(CLOSURE_IS_AMBIENT_OCCLUSION(sd->closure.type)) + return sd->closure.weight; + else + return make_float3(0.0f, 0.0f, 0.0f); +#endif +} + /* Emission */ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) @@ -612,7 +646,7 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) if(CLOSURE_IS_EMISSION(sc->type)) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) eval += OSLShader::emissive_eval(sd, sc)*sc->weight; else #endif @@ -656,7 +690,7 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::eval_surface(kg, sd, randb, path_flag); else #endif @@ -664,7 +698,7 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, #ifdef __SVM__ svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag); #else - bsdf_diffuse_setup(sd, &sd->closure); + bsdf_diffuse_setup(&sd->closure); sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f); #endif } @@ -675,7 +709,7 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, __device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) return OSLShader::eval_background(kg, sd, path_flag); else #endif @@ -721,7 +755,7 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd, if(CLOSURE_IS_VOLUME(sc->type)) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) eval += OSLShader::volume_eval_phase(sc, omega_in, omega_out); else #endif @@ -742,7 +776,7 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd, { #ifdef __SVM__ #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::eval_volume(kg, sd, randb, path_flag); else #endif @@ -757,7 +791,7 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd) /* this will modify sd->P */ #ifdef __SVM__ #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::eval_displacement(kg, sd); else #endif @@ -813,7 +847,7 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) __device void shader_release(KernelGlobals *kg, ShaderData *sd) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::release(kg, sd); #endif } diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index e39ae1d4fbc..0db447289c8 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -16,9 +16,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "kernel_attribute.h" -#include "kernel_projection.h" - CCL_NAMESPACE_BEGIN /* Point on triangle for Moller-Trumbore triangles */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 98d998351a7..e3a766e56b1 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -29,7 +29,7 @@ CCL_NAMESPACE_BEGIN /* constants */ -#define OBJECT_SIZE 22 +#define OBJECT_SIZE 18 #define LIGHT_SIZE 4 #define FILTER_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256 @@ -102,6 +102,7 @@ CCL_NAMESPACE_BEGIN #define __IMAGE_TEXTURES__ #define __EXTRA_NODES__ #define __HOLDOUT__ +#define __NORMAL_MAP__ #endif #ifdef __KERNEL_ADV_SHADING__ @@ -111,13 +112,10 @@ CCL_NAMESPACE_BEGIN #define __BACKGROUND_MIS__ #define __AO__ #define __CAMERA_MOTION__ - -#ifndef __KERNEL_CUDA__ +#define __ANISOTROPIC__ #define __OBJECT_MOTION__ #endif -#endif - //#define __SOBOL_FULL_SCREEN__ /* Shader Evaluation */ @@ -368,15 +366,17 @@ typedef struct ShaderClosure { float sample_weight; #endif -#ifdef __OSL__ - void *prim; -#endif float data0; float data1; float3 N; +#ifdef __ANISOTROPIC__ float3 T; +#endif +#ifdef __OSL__ + void *prim; +#endif } ShaderClosure; /* Shader Data @@ -393,16 +393,18 @@ enum ShaderDataFlag { SD_BSDF_GLOSSY = 16, /* have glossy bsdf */ SD_HOLDOUT = 32, /* have holdout closure? */ SD_VOLUME = 64, /* have volume closure? */ + SD_AO = 128, /* have ao closure? */ /* shader flags */ - SD_SAMPLE_AS_LIGHT = 128, /* direct light sample */ - SD_HAS_SURFACE_TRANSPARENT = 256, /* has surface transparency */ - SD_HAS_VOLUME = 512, /* has volume shader */ - SD_HOMOGENEOUS_VOLUME = 1024, /* has homogeneous volume */ + SD_SAMPLE_AS_LIGHT = 256, /* direct light sample */ + SD_HAS_SURFACE_TRANSPARENT = 512, /* has surface transparency */ + SD_HAS_VOLUME = 1024, /* has volume shader */ + SD_HOMOGENEOUS_VOLUME = 2048, /* has homogeneous volume */ /* object flags */ - SD_HOLDOUT_MASK = 2048, /* holdout for camera rays */ - SD_OBJECT_MOTION = 4096 /* has object motion blur */ + SD_HOLDOUT_MASK = 4096, /* holdout for camera rays */ + SD_OBJECT_MOTION = 8192, /* has object motion blur */ + SD_TRANSFORM_APPLIED = 16384 /* vertices have transform applied */ }; typedef struct ShaderData { diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index 8938b16a48f..1b1bb558bc9 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -14,6 +14,7 @@ set(INC_SYS set(SRC background.cpp + bsdf_phong_ramp.cpp emissive.cpp osl_closures.cpp osl_services.cpp diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript new file mode 100644 index 00000000000..d4b42d2becb --- /dev/null +++ b/intern/cycles/kernel/osl/SConscript @@ -0,0 +1,27 @@ +#!/usr/bin/python + +Import('env') + +defs = [] +incs = [] +cxxflags = Split(env['CXXFLAGS']) + +sources = env.Glob('*.cpp') + +incs.extend('. .. ../svm ../../render ../../util ../../device'.split()) +incs.append(env['BF_OIIO_INC']) +incs.append(env['BF_BOOST_INC']) +incs.append(env['BF_OSL_INC']) +incs.append(env['BF_OPENEXR_INC'].split()) + +defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {') +defs.append('CCL_NAMESPACE_END=}') +defs.append('WITH_OSL') + +if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + cxxflags.append('-DBOOST_NO_RTTI -DBOOST_NO_TYPEID'.split()) + incs.append(env['BF_PTHREADS_INC']) +else: + cxxflags.append('-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID'.split()) + +env.BlenderLib ('cycles_kernel_osl', sources, incs, defs, libtype=['intern'], priority=[10], cxx_compileflags=cxxflags) diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp index b6e9473b7bf..eed4446cddc 100644 --- a/intern/cycles/kernel/osl/background.cpp +++ b/intern/cycles/kernel/osl/background.cpp @@ -73,6 +73,22 @@ public: void print_on(std::ostream &out) const { out << name() << " ()"; } }; +/// ambient occlusion closure +/// +/// We only have a ambient occlusion closure for the shaders +/// to return a color in ambient occlusion shaders. No methods, +/// only the weight is taking into account +/// +class AmbientOcclusionClosure : public ClosurePrimitive { +public: + AmbientOcclusionClosure () : ClosurePrimitive((ClosurePrimitive::Category)AmbientOcclusion) {} + + void setup() {}; + size_t memsize() const { return sizeof(*this); } + const char *name() const { return "ambient_occlusion"; } + void print_on(std::ostream &out) const { out << name() << " ()"; } +}; + ClosureParam *closure_background_params() { static ClosureParam params[] = { @@ -94,5 +110,16 @@ ClosureParam *closure_holdout_params() CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure) +ClosureParam *closure_ambient_occlusion_params() +{ + static ClosureParam params[] = { + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(AmbientOcclusionClosure) + }; + return params; +} + +CLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure) + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp new file mode 100644 index 00000000000..fb144be7e50 --- /dev/null +++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp @@ -0,0 +1,115 @@ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +#include "osl_closures.h" + +#include "kernel_types.h" +#include "closure/bsdf_phong_ramp.h" + +CCL_NAMESPACE_BEGIN + +using namespace OSL; + +class PhongRampClosure : public CBSDFClosure { +public: + PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY) {} + Color3 colors[8]; + float3 fcolors[8]; + + size_t memsize() const { return sizeof(*this); } + const char *name() const { return "phong_ramp"; } + + void setup() + { + sc.N = TO_FLOAT3(N); + m_shaderdata_flag = bsdf_phong_ramp_setup(&sc); + + for(int i = 0; i < 8; i++) + fcolors[i] = TO_FLOAT3(colors[i]); + } + + bool mergeable(const ClosurePrimitive *other) const + { + return false; + } + + void blur(float roughness) + { + bsdf_phong_ramp_blur(&sc, roughness); + } + + void print_on(std::ostream &out) const + { + out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; + } + + float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const + { + return bsdf_phong_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf); + } + + float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const + { + return bsdf_phong_ramp_eval_transmit(&sc, fcolors, omega_out, omega_in, &pdf); + } + + int sample(const float3 &Ng, + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, + float randu, float randv, + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, + float &pdf, float3 &eval) const + { + return bsdf_phong_ramp_sample(&sc, fcolors, Ng, omega_out, domega_out_dx, domega_out_dy, + randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf); + } +}; + +ClosureParam *closure_bsdf_phong_ramp_params() +{ + static ClosureParam params[] = { + CLOSURE_VECTOR_PARAM(PhongRampClosure, N), + CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0), + CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(PhongRampClosure) + }; + return params; +} + +CLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure) + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 73e96643df7..f95859d237d 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -48,6 +48,7 @@ #include "closure/bsdf_diffuse.h" #include "closure/bsdf_microfacet.h" #include "closure/bsdf_oren_nayar.h" +#include "closure/bsdf_phong_ramp.h" #include "closure/bsdf_reflection.h" #include "closure/bsdf_refraction.h" #include "closure/bsdf_transparent.h" @@ -152,8 +153,9 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O ss->register_closure(name, id, params, prepare, generic_closure_setup, generic_closure_compare); } -void OSLShader::register_closures(OSL::ShadingSystem *ss) +void OSLShader::register_closures(OSLShadingSystem *ss_) { + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)ss_; int id = 0; register_closure(ss, "diffuse", id++, @@ -190,6 +192,10 @@ void OSLShader::register_closures(OSL::ShadingSystem *ss) closure_background_params(), closure_background_prepare); register_closure(ss, "holdout", id++, closure_holdout_params(), closure_holdout_prepare); + register_closure(ss, "ambient_occlusion", id++, + closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare); + register_closure(ss, "phong_ramp", id++, + closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 574cb685db5..2d91b37be7e 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -46,10 +46,18 @@ CCL_NAMESPACE_BEGIN OSL::ClosureParam *closure_emission_params(); OSL::ClosureParam *closure_background_params(); OSL::ClosureParam *closure_holdout_params(); +OSL::ClosureParam *closure_ambient_occlusion_params(); +OSL::ClosureParam *closure_bsdf_phong_ramp_params(); void closure_emission_prepare(OSL::RendererServices *, int id, void *data); void closure_background_prepare(OSL::RendererServices *, int id, void *data); void closure_holdout_prepare(OSL::RendererServices *, int id, void *data); +void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data); +void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); + +enum { + AmbientOcclusion = 100 +}; #define CLOSURE_PREPARE(name, classname) \ void name(RendererServices *, int id, void *data) \ @@ -58,6 +66,8 @@ void name(RendererServices *, int id, void *data) \ new (data) classname(); \ } +#define CLOSURE_PREPARE_STATIC(name, classname) static CLOSURE_PREPARE(name, classname) + #define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) #define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) #define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) @@ -69,26 +79,26 @@ public: ShaderClosure sc; OSL::Vec3 N, T; - CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), - m_scattering_label(scattering), m_shaderdata_flag(0) { } - ~CBSDFClosure() { } + CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), + m_scattering_label(scattering), m_shaderdata_flag(0) { } + ~CBSDFClosure() { } - int scattering() const { return m_scattering_label; } - int shaderdata_flag() const { return m_shaderdata_flag; } + int scattering() const { return m_scattering_label; } + int shaderdata_flag() const { return m_shaderdata_flag; } ClosureType shaderclosure_type() const { return sc.type; } - virtual void blur(float roughness) = 0; - virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; - virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + virtual void blur(float roughness) = 0; + virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; - virtual int sample(const float3 &Ng, - const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, - float randu, float randv, - float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, - float &pdf, float3 &eval) const = 0; + virtual int sample(const float3 &Ng, + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, + float randu, float randv, + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, + float &pdf, float3 &eval) const = 0; protected: - int m_scattering_label; + int m_scattering_label; int m_shaderdata_flag; }; @@ -143,7 +153,7 @@ public: \ } \ }; \ \ -ClosureParam *bsdf_##lower##_params() \ +static ClosureParam *bsdf_##lower##_params() \ { \ static ClosureParam params[] = { @@ -156,7 +166,7 @@ ClosureParam *bsdf_##lower##_params() \ return params; \ } \ \ -CLOSURE_PREPARE(bsdf_##lower##_prepare, Upper##Closure) +CLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 8cbbfc8dbb1..1a2a210de88 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -22,22 +22,35 @@ #ifdef WITH_OSL #include +#include #include "util_map.h" #include "util_param.h" #include "util_thread.h" #include "util_vector.h" +#ifndef WIN32 +using std::isfinite; +#endif + CCL_NAMESPACE_BEGIN class OSLRenderServices; struct OSLGlobals { - /* use */ + OSLGlobals() + { + ss = NULL; + ts = NULL; + services = NULL; + use = false; + } + bool use; /* shading system */ OSL::ShadingSystem *ss; + OSL::TextureSystem *ts; OSLRenderServices *services; /* shader states */ @@ -59,14 +72,13 @@ struct OSLGlobals { vector attribute_map; ObjectNameMap object_name_map; + vector object_names; +}; - /* thread key for thread specific data lookup */ - struct ThreadData { - OSL::ShaderGlobals globals; - OSL::PerThreadInfo *thread_info; - }; - - static tls_ptr(ThreadData, thread_data); +/* thread key for thread specific data lookup */ +struct OSLThreadData { + OSL::ShaderGlobals globals; + OSL::PerThreadInfo *thread_info; }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index ac26fc1c18d..b584a54b1b7 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -22,6 +22,8 @@ #include "object.h" #include "scene.h" +#include "osl_closures.h" +#include "osl_globals.h" #include "osl_services.h" #include "osl_shader.h" @@ -30,8 +32,16 @@ #include "kernel_compat_cpu.h" #include "kernel_globals.h" +#include "kernel_montecarlo.h" +#include "kernel_projection.h" +#include "kernel_differential.h" #include "kernel_object.h" +#include "kernel_bvh.h" +#include "kernel_attribute.h" +#include "kernel_projection.h" #include "kernel_triangle.h" +#include "kernel_accumulate.h" +#include "kernel_shader.h" CCL_NAMESPACE_BEGIN @@ -46,6 +56,34 @@ ustring OSLRenderServices::u_camera("camera"); ustring OSLRenderServices::u_screen("screen"); ustring OSLRenderServices::u_raster("raster"); ustring OSLRenderServices::u_ndc("NDC"); +ustring OSLRenderServices::u_object_location("object:location"); +ustring OSLRenderServices::u_object_index("object:index"); +ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated"); +ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv"); +ustring OSLRenderServices::u_material_index("material:index"); +ustring OSLRenderServices::u_object_random("object:random"); +ustring OSLRenderServices::u_particle_index("particle:index"); +ustring OSLRenderServices::u_particle_age("particle:age"); +ustring OSLRenderServices::u_particle_lifetime("particle:lifetime"); +ustring OSLRenderServices::u_particle_location("particle:location"); +ustring OSLRenderServices::u_particle_rotation("particle:rotation"); +ustring OSLRenderServices::u_particle_size("particle:size"); +ustring OSLRenderServices::u_particle_velocity("particle:velocity"); +ustring OSLRenderServices::u_particle_angular_velocity("particle:angular_velocity"); +ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices"); +ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices"); +ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices"); +ustring OSLRenderServices::u_geom_name("geom:name"); +ustring OSLRenderServices::u_path_ray_length("path:ray_length"); +ustring OSLRenderServices::u_trace("trace"); +ustring OSLRenderServices::u_hit("hit"); +ustring OSLRenderServices::u_hitdist("hitdist"); +ustring OSLRenderServices::u_N("N"); +ustring OSLRenderServices::u_Ng("Ng"); +ustring OSLRenderServices::u_P("P"); +ustring OSLRenderServices::u_I("I"); +ustring OSLRenderServices::u_u("u"); +ustring OSLRenderServices::u_v("v"); ustring OSLRenderServices::u_empty; OSLRenderServices::OSLRenderServices() @@ -73,7 +111,12 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr if (object != ~0) { #ifdef __OBJECT_MOTION__ - Transform tfm = object_fetch_transform_motion_test(kg, object, time, NULL); + Transform tfm; + + if(time == sd->time) + tfm = sd->ob_tfm; + else + tfm = object_fetch_transform_motion_test(kg, object, time, NULL); #else Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); #endif @@ -99,7 +142,11 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform if (object != ~0) { #ifdef __OBJECT_MOTION__ Transform itfm; - object_fetch_transform_motion_test(kg, object, time, &itfm); + + if(time == sd->time) + itfm = sd->ob_itfm; + else + object_fetch_transform_motion_test(kg, object, time, &itfm); #else Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); #endif @@ -282,7 +329,7 @@ bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, return false; } -static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) +static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) { if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) @@ -302,8 +349,10 @@ static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v fval[7] = f[2].y; fval[8] = f[2].z; } + + return true; } - else { + else if(type == TypeDesc::TypeFloat) { float *fval = (float *)val; fval[0] = average(f[0]); @@ -311,10 +360,25 @@ static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v fval[1] = average(f[1]); fval[2] = average(f[2]); } + + return true; } + + return false; } -static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) +static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void *val) +{ + float3 fv[3]; + + fv[0] = f; + fv[1] = make_float3(0.0f, 0.0f, 0.0f); + fv[2] = make_float3(0.0f, 0.0f, 0.0f); + + return set_attribute_float3(fv, type, derivatives, val); +} + +static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) { if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) @@ -333,8 +397,10 @@ static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi fval[7] = f[2]; fval[8] = f[2]; } + + return true; } - else { + else if(type == TypeDesc::TypeFloat) { float *fval = (float *)val; fval[0] = f[0]; @@ -342,7 +408,22 @@ static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi fval[1] = f[1]; fval[2] = f[2]; } + + return true; } + + return false; +} + +static bool set_attribute_float(float f, TypeDesc type, bool derivatives, void *val) +{ + float fv[3]; + + fv[0] = f; + fv[1] = 0.0f; + fv[2] = 0.0f; + + return set_attribute_float(fv, type, derivatives, val); } static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val) @@ -362,6 +443,23 @@ static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val) return false; } +static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, void *val) +{ + if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) { + ustring *sval = (ustring *)val; + sval[0] = str; + + if (derivatives) { + sval[1] = OSLRenderServices::u_empty; + sval[2] = OSLRenderServices::u_empty; + } + + return true; + } + + return false; +} + static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, void *val) { if(type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) { @@ -394,20 +492,18 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS const TypeDesc& type, bool derivatives, void *val) { if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || - attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) + attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { float3 fval[3]; fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - set_attribute_float3(fval, type, derivatives, val); - return true; + return set_attribute_float3(fval, type, derivatives, val); } else if (attr.type == TypeDesc::TypeFloat) { float fval[3]; fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - set_attribute_float(fval, type, derivatives, val); - return true; + return set_attribute_float(fval, type, derivatives, val); } else { return false; @@ -423,147 +519,110 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat memset((char *)val + datasize, 0, datasize * 2); } -static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, - TypeDesc type, bool derivatives, void *val) +bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val) { - /* todo: turn this into hash table + callback once */ + /* todo: turn this into hash table? */ /* Object Attributes */ - if (name == "object:location") { - float3 fval[3]; - fval[0] = object_location(kg, sd); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + if (name == u_object_location) { + float3 f = object_location(kg, sd); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "object:index") { - float fval[3]; - fval[0] = object_pass_id(kg, sd->object); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == u_object_index) { + float f = object_pass_id(kg, sd->object); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "geom:dupli_generated") { - float3 fval[3]; - fval[0] = object_dupli_generated(kg, sd->object); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + else if (name == u_geom_dupli_generated) { + float3 f = object_dupli_generated(kg, sd->object); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "geom:dupli_uv") { - float3 fval[3]; - fval[0] = object_dupli_uv(kg, sd->object); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + else if (name == u_geom_dupli_uv) { + float3 f = object_dupli_uv(kg, sd->object); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "material:index") { - float fval[3]; - fval[0] = shader_pass_id(kg, sd); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == u_material_index) { + float f = shader_pass_id(kg, sd); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "object:random") { - float fval[3]; - fval[0] = object_random_number(kg, sd->object); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == u_object_random) { + float f = object_random_number(kg, sd->object); + return set_attribute_float(f, type, derivatives, val); } /* Particle Attributes */ - else if (name == "particle:index") { - float fval[3]; + else if (name == u_particle_index) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_index(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_index(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "particle:age") { - float fval[3]; + else if (name == u_particle_age) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_age(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_age(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "particle:lifetime") { - float fval[3]; + else if (name == u_particle_lifetime) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_lifetime(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f= particle_lifetime(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "particle:location") { - float3 fval[3]; + else if (name == u_particle_location) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_location(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_location(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); } #if 0 /* unsupported */ - else if (name == "particle:rotation") { - float4 fval[3]; + else if (name == u_particle_rotation) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_rotation(kg, particle_id); - fval[1] = fval[2] = make_float4(0.0, 0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float4(fval, type, derivatives, val); - return true; + float4 f = particle_rotation(kg, particle_id); + return set_attribute_float4(f, type, derivatives, val); } #endif - else if (name == "particle:size") { - float fval[3]; + else if (name == u_particle_size) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_size(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_size(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "particle:velocity") { - float3 fval[3]; + else if (name == u_particle_velocity) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_velocity(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_velocity(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "particle:angular_velocity") { - float3 fval[3]; + else if (name == u_particle_angular_velocity) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_angular_velocity(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_angular_velocity(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "geom:numpolyvertices") { + else if (name == u_geom_numpolyvertices) { return set_attribute_int(3, type, derivatives, val); } - else if (name == "geom:trianglevertices" || name == "geom:polyvertices") { + else if (name == u_geom_trianglevertices || name == u_geom_polyvertices) { float3 P[3]; triangle_vertices(kg, sd->prim, P); - object_position_transform(kg, sd, &P[0]); - object_position_transform(kg, sd, &P[1]); - object_position_transform(kg, sd, &P[2]); + + if(!(sd->flag & SD_TRANSFORM_APPLIED)) { + object_position_transform(kg, sd, &P[0]); + object_position_transform(kg, sd, &P[1]); + object_position_transform(kg, sd, &P[2]); + } + return set_attribute_float3_3(P, type, derivatives, val); } + else if(name == u_geom_name) { + ustring object_name = kg->osl->object_names[sd->object]; + return set_attribute_string(object_name, type, derivatives, val); + } else return false; } -static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, - TypeDesc type, bool derivatives, void *val) +bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val) { /* Ray Length */ - if (name == "path:ray_length") { - float fval[3]; - fval[0] = sd->ray_length; - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + if (name == u_path_ray_length) { + float f = sd->ray_length; + return set_attribute_float(f, type, derivatives, val); } else @@ -580,9 +639,9 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri /* lookup of attribute on another object */ if (object_name != u_empty) { - OSLGlobals::ObjectNameMap::iterator it = kg->osl.object_name_map.find(object_name); + OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name); - if (it == kg->osl.object_name_map.end()) + if (it == kg->osl->object_name_map.end()) return false; object = it->second; @@ -593,7 +652,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri } /* find attribute on object */ - OSLGlobals::AttributeMap& attribute_map = kg->osl.attribute_map[object]; + OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object]; OSLGlobals::AttributeMap::iterator it = attribute_map.find(name); if (it != attribute_map.end()) { @@ -634,6 +693,80 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderst return false; /* never called by OSL */ } +bool OSLRenderServices::texture(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, + float s, float t, float dsdx, float dtdx, + float dsdy, float dtdy, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl->ts; + bool status = ts->texture(filename, options, s, t, dsdx, dtdx, dsdy, dtdy, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + } + + return status; +} + +bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &P, + const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, + const OSL::Vec3 &dPdz, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl->ts; + bool status = ts->texture3d(filename, options, P, dPdx, dPdy, dPdz, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + + } + + return status; +} + +bool OSLRenderServices::environment(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl->ts; + bool status = ts->environment(filename, options, R, dRdx, dRdy, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + } + + return status; +} + +bool OSLRenderServices::get_texture_info(ustring filename, int subimage, + ustring dataname, + TypeDesc datatype, void *data) +{ + OSL::TextureSystem *ts = kernel_globals->osl->ts; + return ts->get_texture_info(filename, subimage, dataname, datatype, data); +} + int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er, float radius, int max_points, bool sort, size_t *out_indices, float *out_distances, int derivs_offset) @@ -647,4 +780,107 @@ int OSLRenderServices::pointcloud_get(ustring filename, size_t *indices, int cou return 0; } +bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg, + const OSL::Vec3 &P, const OSL::Vec3 &dPdx, + const OSL::Vec3 &dPdy, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) +{ + /* todo: options.shader support, maybe options.traceset */ + ShaderData *sd = (ShaderData *)(sg->renderstate); + + /* setup ray */ + Ray ray; + + ray.P = TO_FLOAT3(P); + ray.D = TO_FLOAT3(R); + ray.t = (options.maxdist == 1.0e30)? FLT_MAX: options.maxdist - options.mindist; + ray.time = sd->time; + + if(options.mindist == 0.0f) { + /* avoid self-intersections */ + if(ray.P == sd->P) { + bool transmit = (dot(sd->Ng, ray.D) < 0.0f); + ray.P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng); + } + } + else { + /* offset for minimum distance */ + ray.P += options.mindist*ray.D; + } + + /* ray differentials */ + ray.dP.dx = TO_FLOAT3(dPdx); + ray.dP.dy = TO_FLOAT3(dPdy); + ray.dD.dx = TO_FLOAT3(dRdx); + ray.dD.dy = TO_FLOAT3(dRdy); + + /* allocate trace data */ + TraceData *tracedata = new TraceData(); + tracedata->ray = ray; + tracedata->setup = false; + + if(sg->tracedata) + delete (TraceData*)sg->tracedata; + sg->tracedata = tracedata; + + /* raytrace */ + return scene_intersect(kernel_globals, &ray, ~0, &tracedata->isect); +} + + +bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, + TypeDesc type, void *val, bool derivatives) +{ + TraceData *tracedata = (TraceData*)sg->tracedata; + + if(source == u_trace && tracedata) { + if(name == u_hit) { + return set_attribute_int((tracedata->isect.prim != ~0), type, derivatives, val); + } + else if(tracedata->isect.prim != ~0) { + if(name == u_hitdist) { + float f[3] = {tracedata->isect.t, 0.0f, 0.0f}; + return set_attribute_float(f, type, derivatives, val); + } + else { + KernelGlobals *kg = kernel_globals; + ShaderData *sd = &tracedata->sd; + + if(!tracedata->setup) { + /* lazy shader data setup */ + shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray); + tracedata->setup = true; + } + + if(name == u_N) { + return set_attribute_float3(sd->N, type, derivatives, val); + } + else if(name == u_Ng) { + return set_attribute_float3(sd->Ng, type, derivatives, val); + } + else if(name == u_P) { + float3 f[3] = {sd->P, sd->dP.dx, sd->dP.dy}; + return set_attribute_float3(f, type, derivatives, val); + } + else if(name == u_I) { + float3 f[3] = {sd->I, sd->dI.dx, sd->dI.dy}; + return set_attribute_float3(f, type, derivatives, val); + } + else if(name == u_u) { + float f[3] = {sd->u, sd->du.dx, sd->du.dy}; + return set_attribute_float(f, type, derivatives, val); + } + else if(name == u_v) { + float f[3] = {sd->v, sd->dv.dx, sd->dv.dy}; + return set_attribute_float(f, type, derivatives, val); + } + + return get_attribute(sd, derivatives, u_empty, type, name, val); + } + } + } + + return false; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index fa32d47a89f..e687700b383 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -76,8 +76,42 @@ public: int pointcloud_get(ustring filename, size_t *indices, int count, ustring attr_name, TypeDesc attr_type, void *out_data); -private: - KernelGlobals *kernel_globals; + bool trace(TraceOpt &options, OSL::ShaderGlobals *sg, + const OSL::Vec3 &P, const OSL::Vec3 &dPdx, + const OSL::Vec3 &dPdy, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy); + + bool getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, + TypeDesc type, void *val, bool derivatives); + + bool texture(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, + float s, float t, float dsdx, float dtdx, + float dsdy, float dtdy, float *result); + + bool texture3d(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &P, + const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, + const OSL::Vec3 &dPdz, float *result); + + bool environment(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result); + + bool get_texture_info(ustring filename, int subimage, + ustring dataname, TypeDesc datatype, void *data); + + static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val); + static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val); + + struct TraceData { + Ray ray; + Intersection isect; + ShaderData sd; + bool setup; + }; static ustring u_distance; static ustring u_index; @@ -85,7 +119,38 @@ private: static ustring u_screen; static ustring u_raster; static ustring u_ndc; + static ustring u_object_location; + static ustring u_object_index; + static ustring u_geom_dupli_generated; + static ustring u_geom_dupli_uv; + static ustring u_material_index; + static ustring u_object_random; + static ustring u_particle_index; + static ustring u_particle_age; + static ustring u_particle_lifetime; + static ustring u_particle_location; + static ustring u_particle_rotation; + static ustring u_particle_size; + static ustring u_particle_velocity; + static ustring u_particle_angular_velocity; + static ustring u_geom_numpolyvertices; + static ustring u_geom_trianglevertices; + static ustring u_geom_polyvertices; + static ustring u_geom_name; + static ustring u_path_ray_length; + static ustring u_trace; + static ustring u_hit; + static ustring u_hitdist; + static ustring u_N; + static ustring u_Ng; + static ustring u_P; + static ustring u_I; + static ustring u_u; + static ustring u_v; static ustring u_empty; + +private: + KernelGlobals *kernel_globals; }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 8b71ac30ab6..32712b25e92 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -22,42 +22,56 @@ #include "kernel_object.h" #include "osl_closures.h" +#include "osl_globals.h" #include "osl_services.h" #include "osl_shader.h" +#include "util_attribute.h" #include "util_foreach.h" #include CCL_NAMESPACE_BEGIN -tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data); - /* Threads */ -void OSLShader::thread_init(KernelGlobals *kg) +void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OSLGlobals *osl_globals) { - OSL::ShadingSystem *ss = kg->osl.ss; + /* no osl used? */ + if(!osl_globals->use) { + kg->osl = NULL; + return; + } - OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData(); + /* per thread kernel data init*/ + kg->osl = osl_globals; + kg->osl->services->thread_init(kernel_globals); + + OSL::ShadingSystem *ss = kg->osl->ss; + OSLThreadData *tdata = new OSLThreadData(); memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals)); tdata->thread_info = ss->create_thread_info(); - tls_set(kg->osl.thread_data, tdata); - - kg->osl.services->thread_init(kg); + kg->osl_ss = (OSLShadingSystem*)ss; + kg->osl_tdata = tdata; } void OSLShader::thread_free(KernelGlobals *kg) { - OSL::ShadingSystem *ss = kg->osl.ss; + if(!kg->osl) + return; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; ss->destroy_thread_info(tdata->thread_info); delete tdata; + + kg->osl = NULL; + kg->osl_ss = NULL; + kg->osl_tdata = NULL; } /* Globals */ @@ -83,6 +97,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, globals->dPdu = TO_VEC3(sd->dPdu); globals->dPdv = TO_VEC3(sd->dPdv); globals->surfacearea = (sd->object == ~0) ? 1.0f : object_surface_area(kg, sd->object); + globals->time = sd->time; /* booleans */ globals->raytype = path_flag; /* todo: add our own ray types */ @@ -93,6 +108,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, /* shader data to be used in services callbacks */ globals->renderstate = sd; + globals->tracedata = NULL; /* hacky, we leave it to services to fetch actual object matrix */ globals->shader2common = sd; @@ -134,13 +150,15 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, /* sample weight */ float sample_weight = fabsf(average(weight)); - sd->flag |= bsdf->shaderdata_flag(); - sc.sample_weight = sample_weight; sc.type = bsdf->shaderclosure_type(); + sc.N = bsdf->sc.N; /* needed for AO */ /* add */ - sd->closure[sd->num_closure++] = sc; + if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) { + sd->closure[sd->num_closure++] = sc; + sd->flag |= bsdf->shaderdata_flag(); + } break; } case OSL::ClosurePrimitive::Emissive: { @@ -154,9 +172,26 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sc.type = CLOSURE_EMISSION_ID; /* flag */ - sd->flag |= SD_EMISSION; + if(sd->num_closure < MAX_CLOSURE) { + sd->closure[sd->num_closure++] = sc; + sd->flag |= SD_EMISSION; + } + break; + } + case AmbientOcclusion: { + if (sd->num_closure == MAX_CLOSURE) + return; - sd->closure[sd->num_closure++] = sc; + /* sample weight */ + float sample_weight = fabsf(average(weight)); + + sc.sample_weight = sample_weight; + sc.type = CLOSURE_AMBIENT_OCCLUSION_ID; + + if(sd->num_closure < MAX_CLOSURE) { + sd->closure[sd->num_closure++] = sc; + sd->flag |= SD_AO; + } break; } case OSL::ClosurePrimitive::Holdout: @@ -165,8 +200,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sc.sample_weight = 0.0f; sc.type = CLOSURE_HOLDOUT_ID; - sd->flag |= SD_HOLDOUT; - sd->closure[sd->num_closure++] = sc; + + if(sd->num_closure < MAX_CLOSURE) { + sd->closure[sd->num_closure++] = sc; + sd->flag |= SD_HOLDOUT; + } break; case OSL::ClosurePrimitive::BSSRDF: case OSL::ClosurePrimitive::Debug: @@ -191,8 +229,8 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { /* gather pointers */ - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; @@ -202,8 +240,12 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int /* execute shader for this point */ int shader = sd->shader & SHADER_MASK; - if (kg->osl.surface_state[shader]) - ss->execute(*ctx, *(kg->osl.surface_state[shader]), *globals); + if (kg->osl->surface_state[shader]) + ss->execute(*ctx, *(kg->osl->surface_state[shader]), *globals); + + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; /* flatten closure tree */ sd->num_closure = 0; @@ -248,8 +290,8 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) { /* gather pointers */ - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; @@ -257,8 +299,12 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader for this point */ - if (kg->osl.background_state) - ss->execute(*ctx, *(kg->osl.background_state), *globals); + if (kg->osl->background_state) + ss->execute(*ctx, *(kg->osl->background_state), *globals); + + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; /* return background color immediately */ if (globals->Ci) @@ -296,7 +342,8 @@ static void flatten_volume_closure_tree(ShaderData *sd, sc.type = CLOSURE_VOLUME_ID; /* add */ - sd->closure[sd->num_closure++] = sc; + if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) + sd->closure[sd->num_closure++] = sc; break; } case OSL::ClosurePrimitive::Holdout: @@ -324,8 +371,8 @@ static void flatten_volume_closure_tree(ShaderData *sd, void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { /* gather pointers */ - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; @@ -335,8 +382,12 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int /* execute shader */ int shader = sd->shader & SHADER_MASK; - if (kg->osl.volume_state[shader]) - ss->execute(*ctx, *(kg->osl.volume_state[shader]), *globals); + if (kg->osl->volume_state[shader]) + ss->execute(*ctx, *(kg->osl->volume_state[shader]), *globals); + + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; if (globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); @@ -347,8 +398,8 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) { /* gather pointers */ - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; @@ -358,8 +409,12 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) /* execute shader */ int shader = sd->shader & SHADER_MASK; - if (kg->osl.displacement_state[shader]) - ss->execute(*ctx, *(kg->osl.displacement_state[shader]), *globals); + if (kg->osl->displacement_state[shader]) + ss->execute(*ctx, *(kg->osl->displacement_state[shader]), *globals); + + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; /* get back position */ sd->P = TO_FLOAT3(globals->P); @@ -367,15 +422,15 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) void OSLShader::init(KernelGlobals *kg, ShaderData *sd) { - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; sd->osl_ctx = ss->get_context(tdata->thread_info); } void OSLShader::release(KernelGlobals *kg, ShaderData *sd) { - OSL::ShadingSystem *ss = kg->osl.ss; + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; ss->release_context((OSL::ShadingContext *)sd->osl_ctx); } @@ -433,5 +488,23 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_ return TO_FLOAT3(volume_eval) * sc->weight; } +/* Attributes */ + +int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id) +{ + /* for OSL, a hash map is used to lookup the attribute by name. */ + OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[sd->object]; + ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id))); + OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); + + if (it != attr_map.end()) { + const OSLGlobals::Attribute &osl_attr = it->second; + /* return result */ + return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset; + } + else + return (int)ATTR_STD_NOT_FOUND; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index 9ff31e9160b..e614f240dc1 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -31,33 +31,27 @@ * This means no thread state must be passed along in the kernel itself. */ -#include -#include - #include "kernel_types.h" -#include "util_map.h" -#include "util_param.h" -#include "util_vector.h" - CCL_NAMESPACE_BEGIN -namespace OSL = ::OSL; - -class OSLRenderServices; class Scene; + struct ShaderClosure; struct ShaderData; struct differential3; struct KernelGlobals; +struct OSLGlobals; +struct OSLShadingSystem; + class OSLShader { public: /* init */ - static void register_closures(OSL::ShadingSystem *ss); + static void register_closures(OSLShadingSystem *ss); /* per thread data */ - static void thread_init(KernelGlobals *kg); + static void thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OSLGlobals *osl_globals); static void thread_free(KernelGlobals *kg); /* eval */ @@ -82,6 +76,9 @@ public: /* release */ static void init(KernelGlobals *kg, ShaderData *sd); static void release(KernelGlobals *kg, ShaderData *sd); + + /* attributes */ + static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id); }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 00ab52a1d13..f7fec62fd6d 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -3,9 +3,11 @@ set(SRC_OSL node_add_closure.osl + node_ambient_occlusion.osl node_attribute.osl node_background.osl node_brick_texture.osl + node_brightness.osl node_bump.osl node_camera.osl node_checker_texture.osl @@ -21,35 +23,37 @@ set(SRC_OSL node_environment_texture.osl node_fresnel.osl node_gamma.osl - node_gradient_texture.osl - node_brightness.osl node_geometry.osl node_glass_bsdf.osl node_glossy_bsdf.osl + node_gradient_texture.osl node_holdout.osl node_hsv.osl node_image_texture.osl node_invert.osl node_layer_weight.osl - node_light_path.osl node_light_falloff.osl + node_light_path.osl node_magic_texture.osl node_mapping.osl node_math.osl node_mix.osl node_mix_closure.osl node_musgrave_texture.osl - node_normal.osl node_noise_texture.osl + node_normal.osl + node_normal_map.osl node_object_info.osl node_output_displacement.osl node_output_surface.osl node_output_volume.osl node_particle_info.osl + node_refraction_bsdf.osl node_rgb_ramp.osl node_separate_rgb.osl node_set_normal.osl node_sky_texture.osl + node_tangent.osl node_texture_coordinate.osl node_translucent_bsdf.osl node_transparent_bsdf.osl @@ -85,7 +89,7 @@ foreach(_file ${SRC_OSL}) list(APPEND SRC_OSO ${_OSO_FILE} ) - + unset(_OSL_FILE) unset(_OSO_FILE) endforeach() diff --git a/intern/cycles/kernel/shaders/SConscript b/intern/cycles/kernel/shaders/SConscript new file mode 100644 index 00000000000..36b86d7b4f6 --- /dev/null +++ b/intern/cycles/kernel/shaders/SConscript @@ -0,0 +1,42 @@ +#!/usr/bin/python +import sys +import os +import Blender as B + +def normpath(path): + return os.path.abspath(os.path.normpath(path)) + +Import ('env') + +oso_files = [] + +if env['WITH_BF_CYCLES_OSL']: + shaders = env.Clone() + + # osl compiler + osl_compiler = File(env.subst(env['BF_OSL_COMPILER'])).abspath + + # build directory + root_build_dir = normpath(env['BF_BUILDDIR']) + build_dir = os.path.join(root_build_dir, 'intern/cycles/kernel/shaders') + + # source directories and files + source_dir = Dir('.').srcnode().path + + # dependencies + dependencies = shaders.Glob('*.h') + + for f in os.listdir(source_dir): + if f.endswith('.osl'): + osl_file = os.path.join(source_dir, f) + oso_file = os.path.join(build_dir, f.replace('.osl', '.oso')) + + command = "%s -O2 -I%s -o %s %s" % (osl_compiler, source_dir, oso_file, osl_file) + + shaders.Command(oso_file, f, command) + shaders.Depends(oso_file, [f] + dependencies) + + oso_files.append(oso_file) + + +Return('oso_files') diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl new file mode 100644 index 00000000000..b9423344e73 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl @@ -0,0 +1,28 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_ambient_occlusion( + normal NormalIn = N, + color Color = color(0.8, 0.8, 0.8), + output closure color AO = ambient_occlusion()) +{ + AO = Color * ambient_occlusion(); +} + diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl index 478d9457001..b1f2a35789f 100644 --- a/intern/cycles/kernel/shaders/node_brick_texture.osl +++ b/intern/cycles/kernel/shaders/node_brick_texture.osl @@ -58,6 +58,8 @@ float brick(point p, float mortar_size, float bias, } shader node_brick_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Offset = 0.5, int OffsetFrequency = 2, float Squash = 1.0, @@ -74,10 +76,15 @@ shader node_brick_texture( output float Fac = 0.0, output color Color = color(0.2, 0.2, 0.2)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + float tint = 0.0; color Col = Color1; - Fac = brick(Vector * Scale, MortarSize, Bias, BrickWidth, RowHeight, + Fac = brick(p * Scale, MortarSize, Bias, BrickWidth, RowHeight, Offset, OffsetFrequency, Squash, SquashFrequency, tint); if (Fac != 1.0) { diff --git a/intern/cycles/kernel/shaders/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl index 8e9f5c9c796..b263d815566 100644 --- a/intern/cycles/kernel/shaders/node_brightness.osl +++ b/intern/cycles/kernel/shaders/node_brightness.osl @@ -20,32 +20,15 @@ shader node_brightness( color ColorIn = color(0.8, 0.8, 0.8), - float Brightness = 0.0, + float Bright = 0.0, float Contrast = 0.0, output color ColorOut = color(0.8, 0.8, 0.8)) { - float delta = Contrast * (1.0 / 200.0); - float a = 1.0 - delta * 2.0; - float b; + float a = 1.0 + Contrast; + float b = Bright - Contrast*0.5; - /* input value is a percentage */ - float bright_factor = Brightness / 100.0; - - /* - * The algorithm is by Werner D. Streidt - * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c - */ - - if (Contrast > 0.0) { - a = (a < 0.0 ? 1.0 / a : 0.0); - b = a * (bright_factor - delta); - } - else { - delta *= -1.0; - b = a * (bright_factor + delta); - } - - ColorOut = a * ColorIn + b; + ColorOut[0] = max(a*ColorIn[0] + b, 0.0); + ColorOut[1] = max(a*ColorIn[1] + b, 0.0); + ColorOut[2] = max(a*ColorIn[2] + b, 0.0); } diff --git a/intern/cycles/kernel/shaders/node_checker_texture.osl b/intern/cycles/kernel/shaders/node_checker_texture.osl index 577caf308ff..eed56f4453a 100644 --- a/intern/cycles/kernel/shaders/node_checker_texture.osl +++ b/intern/cycles/kernel/shaders/node_checker_texture.osl @@ -40,6 +40,8 @@ float checker(point p) } shader node_checker_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Scale = 5.0, point Vector = P, color Color1 = color(0.8, 0.8, 0.8), @@ -47,7 +49,12 @@ shader node_checker_texture( output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { - Fac = checker(Vector * Scale); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = checker(p * Scale); if (Fac == 1.0) { Color = Color1; } diff --git a/intern/cycles/kernel/shaders/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl index 2884c772414..ea488c9ce4c 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_color.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl @@ -20,6 +20,7 @@ shader node_convert_from_color( color Color = color(0.0, 0.0, 0.0), + output string String = "", output float Val = 0.0, output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), @@ -27,7 +28,7 @@ shader node_convert_from_color( output normal Normal = normal(0.0, 0.0, 0.0)) { Val = Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722; - ValInt = (int)(Color[0]*0.2126 + Color[1]*0.7152 + Color[2]*0.0722); + ValInt = (int)(Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722); Vector = vector(Color[0], Color[1], Color[2]); Point = point(Color[0], Color[1], Color[2]); Normal = normal(Color[0], Color[1], Color[2]); diff --git a/intern/cycles/kernel/shaders/node_convert_from_float.osl b/intern/cycles/kernel/shaders/node_convert_from_float.osl index 4466fbae3a6..a20b491c91d 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_float.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl @@ -20,6 +20,7 @@ shader node_convert_from_float( float Val = 0.0, + output string String = "", output int ValInt = 0, output color Color = color(0.0, 0.0, 0.0), output vector Vector = vector(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_convert_from_int.osl b/intern/cycles/kernel/shaders/node_convert_from_int.osl index 060d4184fa6..911b4928db8 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_int.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl @@ -20,6 +20,7 @@ shader node_convert_from_int( int ValInt = 0, + output string String = "", output float Val = 0.0, output color Color = color(0.0, 0.0, 0.0), output vector Vector = vector(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_convert_from_normal.osl b/intern/cycles/kernel/shaders/node_convert_from_normal.osl index 32ef430d93b..1add7400a22 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_normal.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl @@ -20,6 +20,7 @@ shader node_convert_from_normal( normal Normal = normal(0.0, 0.0, 0.0), + output string String = "", output float Val = 0.0, output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_convert_from_point.osl b/intern/cycles/kernel/shaders/node_convert_from_point.osl index a9435c8abf4..8a315828c55 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_point.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl @@ -20,6 +20,7 @@ shader node_convert_from_point( point Point = point(0.0, 0.0, 0.0), + output string String = "", output float Val = 0.0, output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_convert_from_string.osl b/intern/cycles/kernel/shaders/node_convert_from_string.osl new file mode 100644 index 00000000000..f40535ac7a3 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_convert_from_string.osl @@ -0,0 +1,31 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_convert_from_string( + string String = "", + output color Color = color(0.0, 0.0, 0.0), + output float Val = 0.0, + output int ValInt = 0, + output vector Vector = vector(0.0, 0.0, 0.0), + output point Point = point(0.0, 0.0, 0.0), + output normal Normal = normal(0.0, 0.0, 0.0)) +{ +} + diff --git a/intern/cycles/kernel/shaders/node_convert_from_vector.osl b/intern/cycles/kernel/shaders/node_convert_from_vector.osl index 4516f92c753..ae9f97414d5 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_vector.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl @@ -20,6 +20,7 @@ shader node_convert_from_vector( vector Vector = vector(0.0, 0.0, 0.0), + output string String = "", output float Val = 0.0, output int ValInt = 0, output color Color = color(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl index bad62e56ab4..7da336a53f0 100644 --- a/intern/cycles/kernel/shaders/node_environment_texture.osl +++ b/intern/cycles/kernel/shaders/node_environment_texture.osl @@ -19,14 +19,52 @@ #include "stdosl.h" #include "node_color.h" +vector environment_texture_direction_to_equirectangular(vector dir) +{ + float u = -atan2(dir[1], dir[0]) / (2.0 * M_PI) + 0.5; + float v = atan2(dir[2], hypot(dir[0], dir[1])) / M_PI + 0.5; + + return vector(u, v, 0.0); +} + +vector environment_texture_direction_to_mirrorball(vector dir) +{ + dir[1] -= 1.0; + + float div = 2.0 * sqrt(max(-0.5 * dir[1], 0.0)); + if (div > 0.0) + dir /= div; + + float u = 0.5 * (dir[0] + 1.0); + float v = 0.5 * (dir[2] + 1.0); + + return vector(u, v, 0.0); +} + shader node_environment_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), vector Vector = P, string filename = "", + string projection = "Equirectangular", string color_space = "sRGB", output color Color = color(0.0, 0.0, 0.0), output float Alpha = 1.0) { - Color = (color)environment(filename, Vector, "alpha", Alpha); + vector p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + p = normalize(p); + + if (projection == "Equirectangular") + p = environment_texture_direction_to_equirectangular(p); + else + p = environment_texture_direction_to_mirrorball(p); + + /* todo: use environment for better texture filtering of equirectangular */ + Color = (color)texture(filename, p[0], 1.0 - p[1], "wrap", "periodic", "alpha", Alpha); if (color_space == "sRGB") Color = color_srgb_to_scene_linear(Color); diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl index 953c5d1fa2b..d1c11b70081 100644 --- a/intern/cycles/kernel/shaders/node_geometry.osl +++ b/intern/cycles/kernel/shaders/node_geometry.osl @@ -47,26 +47,22 @@ shader node_geometry( } /* first try to get tangent attribute */ - vector T; + point generated; - if (getattribute("geom:tangent", T)) { - /* ensure orthogonal and normalized (interpolation breaks it) */ + /* try to create spherical tangent from generated coordinates */ + if (getattribute("geom:generated", generated)) { + matrix project = matrix(0.0, 1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.5, -0.5, 0.0, 1.0); + + vector T = transform(project, generated); T = transform("object", "world", T); Tangent = cross(Normal, normalize(cross(T, Normal))); } else { - point generated; - - /* try to create spherical tangent from generated coordinates */ - if (getattribute("geom:generated", generated)) { - T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0); - T = transform("object", "world", T); - Tangent = cross(Normal, normalize(cross(T, Normal))); - } - else { - /* otherwise use surface derivatives */ - Tangent = normalize(dPdu); - } + /* otherwise use surface derivatives */ + Tangent = normalize(dPdu); } } diff --git a/intern/cycles/kernel/shaders/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl index ae7cfa51f59..8d862dbad67 100644 --- a/intern/cycles/kernel/shaders/node_gradient_texture.osl +++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl @@ -63,12 +63,19 @@ float gradient(point p, string type) } shader node_gradient_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "Linear", point Vector = P, output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { - Fac = gradient(Vector, Type); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = gradient(p, Type); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/shaders/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl index 8fd7a1612e8..0f4bedfb0f8 100644 --- a/intern/cycles/kernel/shaders/node_hsv.osl +++ b/intern/cycles/kernel/shaders/node_hsv.osl @@ -27,7 +27,6 @@ shader node_hsv( color ColorIn = color(0.0, 0.0, 0.0), output color ColorOut = color(0.0, 0.0, 0.0)) { - float t = clamp(Fac, 0.0, 1.0); color Color = rgb_to_hsv(ColorIn); // remember: fmod doesn't work for negative numbers @@ -38,6 +37,6 @@ shader node_hsv( Color = hsv_to_rgb(Color); - ColorOut = mix(Color, ColorIn, t); + ColorOut = mix(ColorIn, Color, Fac); } diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl index 6393605e6b5..99074672a6a 100644 --- a/intern/cycles/kernel/shaders/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -30,6 +30,8 @@ color image_texture_lookup(string filename, string color_space, float u, float v } shader node_image_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), point Vector = P, string filename = "", string color_space = "sRGB", @@ -38,8 +40,13 @@ shader node_image_texture( output color Color = color(0.0, 0.0, 0.0), output float Alpha = 1.0) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + if (projection == "Flat") { - Color = image_texture_lookup(filename, color_space, Vector[0], Vector[1], Alpha); + Color = image_texture_lookup(filename, color_space, p[0], p[1], Alpha); } else if (projection == "Box") { /* object space normal */ @@ -61,26 +68,26 @@ shader node_image_texture( vector weight = vector(0.0, 0.0, 0.0); float blend = projection_blend; - float limit = 0.5*(1.0 + blend); + float limit = 0.5 * (1.0 + blend); /* first test for corners with single texture */ - if (Nob[0] > limit*(Nob[0] + Nob[1]) && Nob[0] > limit*(Nob[0] + Nob[2])) { + if (Nob[0] > limit * (Nob[0] + Nob[1]) && Nob[0] > limit * (Nob[0] + Nob[2])) { weight[0] = 1.0; } - else if (Nob[1] > limit*(Nob[0] + Nob[1]) && Nob[1] > limit*(Nob[1] + Nob[2])) { + else if (Nob[1] > limit * (Nob[0] + Nob[1]) && Nob[1] > limit * (Nob[1] + Nob[2])) { weight[1] = 1.0; } - else if (Nob[2] > limit*(Nob[0] + Nob[2]) && Nob[2] > limit*(Nob[1] + Nob[2])) { + else if (Nob[2] > limit * (Nob[0] + Nob[2]) && Nob[2] > limit * (Nob[1] + Nob[2])) { weight[2] = 1.0; } else if (blend > 0.0) { /* in case of blending, test for mixes between two textures */ - if (Nob[2] < (1.0 - limit)*(Nob[1] + Nob[0])) { + if (Nob[2] < (1.0 - limit) * (Nob[1] + Nob[0])) { weight[0] = Nob[0] / (Nob[0] + Nob[1]); weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); weight[1] = 1.0 - weight[0]; } - else if (Nob[0] < (1.0 - limit)*(Nob[1] + Nob[2])) { + else if (Nob[0] < (1.0 - limit) * (Nob[1] + Nob[2])) { weight[1] = Nob[1] / (Nob[1] + Nob[2]); weight[1] = clamp((weight[1] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); weight[2] = 1.0 - weight[1]; @@ -104,16 +111,16 @@ shader node_image_texture( float tmp_alpha; if (weight[0] > 0.0) { - Color += weight[0]*image_texture_lookup(filename, color_space, Vector[1], Vector[2], tmp_alpha); - Alpha += weight[0]*tmp_alpha; + Color += weight[0] * image_texture_lookup(filename, color_space, p[1], p[2], tmp_alpha); + Alpha += weight[0] * tmp_alpha; } if (weight[1] > 0.0) { - Color += weight[1]*image_texture_lookup(filename, color_space, Vector[0], Vector[2], tmp_alpha); - Alpha += weight[1]*tmp_alpha; + Color += weight[1] * image_texture_lookup(filename, color_space, p[0], p[2], tmp_alpha); + Alpha += weight[1] * tmp_alpha; } if (weight[2] > 0.0) { - Color += weight[2]*image_texture_lookup(filename, color_space, Vector[1], Vector[0], tmp_alpha); - Alpha += weight[2]*tmp_alpha; + Color += weight[2] * image_texture_lookup(filename, color_space, p[1], p[0], tmp_alpha); + Alpha += weight[2] * tmp_alpha; } } } diff --git a/intern/cycles/kernel/shaders/node_light_falloff.osl b/intern/cycles/kernel/shaders/node_light_falloff.osl index 7ffa6fe0ffb..a9d41604361 100644 --- a/intern/cycles/kernel/shaders/node_light_falloff.osl +++ b/intern/cycles/kernel/shaders/node_light_falloff.osl @@ -30,7 +30,7 @@ shader node_light_falloff( getattribute("path:ray_length", ray_length); if (Smooth > 0.0) { - float squared = ray_length*ray_length; + float squared = ray_length * ray_length; strength *= squared / (Smooth + squared); } @@ -38,9 +38,9 @@ shader node_light_falloff( Quadratic = strength; /* Linear */ - Linear = (strength*ray_length); + Linear = (strength * ray_length); /* Constant */ - Constant = (strength*ray_length*ray_length); + Constant = (strength * ray_length * ray_length); } diff --git a/intern/cycles/kernel/shaders/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl index e464b83bc9e..b81a30499b2 100644 --- a/intern/cycles/kernel/shaders/node_magic_texture.osl +++ b/intern/cycles/kernel/shaders/node_magic_texture.osl @@ -93,12 +93,19 @@ color magic(point p, int n, float distortion) } shader node_magic_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), int Depth = 2, float Distortion = 5.0, float Scale = 5.0, point Vector = P, output color Color = color(0.0, 0.0, 0.0)) { - Color = magic(Vector * Scale, Depth, Distortion); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Color = magic(p * Scale, Depth, Distortion); } diff --git a/intern/cycles/kernel/shaders/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl index 2e720edfc7e..92df043b39d 100644 --- a/intern/cycles/kernel/shaders/node_mapping.osl +++ b/intern/cycles/kernel/shaders/node_mapping.osl @@ -20,9 +20,17 @@ shader node_mapping( matrix Matrix = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + point mapping_min = point(0.0, 0.0, 0.0), + point mapping_max = point(0.0, 0.0, 0.0), + int use_minmax = 0, point VectorIn = point(0.0, 0.0, 0.0), output point VectorOut = point(0.0, 0.0, 0.0)) { - VectorOut = transform(Matrix, VectorIn); + point p = transform(Matrix, VectorIn); + + if(use_minmax) + p = min(max(mapping_min, p), mapping_max); + + VectorOut = p; } diff --git a/intern/cycles/kernel/shaders/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl index 69e68e5ed15..b2af36230f8 100644 --- a/intern/cycles/kernel/shaders/node_mix.osl +++ b/intern/cycles/kernel/shaders/node_mix.osl @@ -272,7 +272,7 @@ color node_mix_clamp(color col) color outcol = col; outcol[0] = clamp(col[0], 0.0, 1.0); - outcol[1] = clamp(col[2], 0.0, 1.0); + outcol[1] = clamp(col[1], 0.0, 1.0); outcol[2] = clamp(col[2], 0.0, 1.0); return outcol; diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl index 71461b8fd79..afdbca27a3f 100644 --- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl +++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl @@ -187,6 +187,8 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, /* Shader */ shader node_musgrave_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "fBM", float Dimension = 2.0, float Lacunarity = 1.0, @@ -204,7 +206,12 @@ shader node_musgrave_texture( string Basis = "Perlin"; float intensity = 1.0; - point p = Vector * Scale; + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + p = p * Scale; if (Type == "Multifractal") Fac = intensity * noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); diff --git a/intern/cycles/kernel/shaders/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl index 227b2bf8cea..0a379491781 100644 --- a/intern/cycles/kernel/shaders/node_noise_texture.osl +++ b/intern/cycles/kernel/shaders/node_noise_texture.osl @@ -43,6 +43,8 @@ float noise(point p, string basis, float distortion, float detail, float fac, co } shader node_noise_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Distortion = 0.0, float Scale = 5.0, float Detail = 2.0, @@ -50,7 +52,12 @@ shader node_noise_texture( output float Fac = 0.0, output color Color = color(0.2, 0.2, 0.2)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + string Basis = "Perlin"; - Fac = noise(Vector * Scale, Basis, Distortion, Detail, Fac, Color); + Fac = noise(p * Scale, Basis, Distortion, Detail, Fac, Color); } diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl new file mode 100644 index 00000000000..dc25eb8539f --- /dev/null +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -0,0 +1,52 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_normal_map( + normal NormalIn = N, + float Strength = 1.0, + color Color = color(0.5, 0.5, 1.0), + string space = "Tangent", + string attr_name = "geom:tangent", + string attr_sign_name = "geom:tangent_sign", + output normal Normal = NormalIn) +{ + color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5); + + if (space == "Tangent") { + vector tangent; + float tangent_sign; + + getattribute(attr_name, tangent); + getattribute(attr_sign_name, tangent_sign); + + tangent = transform("object", "world", tangent); + + vector B = tangent_sign * cross(NormalIn, tangent); + Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * NormalIn); + } + else if (space == "Object") + Normal = normalize(transform("object", "world", vector(mcolor))); + else if (space == "World") + Normal = normalize(vector(mcolor)); + + if (Strength != 1.0) + Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0)); +} + diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl new file mode 100644 index 00000000000..0cf9d460c6e --- /dev/null +++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl @@ -0,0 +1,39 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_refraction_bsdf( + color Color = color(0.8, 0.8, 0.8), + string distribution = "Sharp", + float Roughness = 0.2, + float IOR = 1.45, + normal Normal = N, + output closure color BSDF = diffuse(Normal)) +{ + float f = max(IOR, 1.0 + 1e-5); + float eta = backfacing() ? 1.0 / f: f; + + if (distribution == "Sharp") + BSDF = Color * refraction(Normal, eta); + else if (distribution == "Beckmann") + BSDF = Color * microfacet_beckmann_refraction(Normal, Roughness, eta); + else if (distribution == "GGX") + BSDF = Color * microfacet_ggx_refraction(Normal, Roughness, eta); +} + diff --git a/intern/cycles/kernel/shaders/node_rgb_ramp.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl index a128ebbd1cf..0df11bb38de 100644 --- a/intern/cycles/kernel/shaders/node_rgb_ramp.osl +++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl @@ -29,7 +29,10 @@ shader node_rgb_ramp( { float f = clamp(Fac, 0.0, 1.0) * (RAMP_TABLE_SIZE - 1); + /* clamp int as well in case of NaN */ int i = (int)f; + if (i < 0) i = 0; + if (i >= RAMP_TABLE_SIZE) i = RAMP_TABLE_SIZE - 1; float t = f - (float)i; Color = ramp_color[i]; diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl index 932fb1e2f17..24a63c78458 100644 --- a/intern/cycles/kernel/shaders/node_sky_texture.osl +++ b/intern/cycles/kernel/shaders/node_sky_texture.osl @@ -43,9 +43,9 @@ color xyY_to_xyz(float x, float y, float Y) color xyz_to_rgb(float x, float y, float z) { - return color(3.240479 * x + -1.537150 * y + -0.498535 * z, - -0.969256 * x + 1.875991 * y + 0.041556 * z, - 0.055648 * x + -0.204043 * y + 1.057311 * z); + return color( 3.240479 * x + -1.537150 * y + -0.498535 * z, + -0.969256 * x + 1.875991 * y + 0.041556 * z, + 0.055648 * x + -0.204043 * y + 1.057311 * z); } float sky_angle_between(float thetav, float phiv, float theta, float phi) @@ -149,14 +149,21 @@ void precompute_sunsky(vector dir, float turbidity, output KernelSunSky sunsky) } shader node_sky_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), vector Vector = P, vector sun_direction = vector(0, 0, 1), float turbidity = 2.2, output color Color = color(0.0, 0.0, 0.0)) { + vector p = Vector; + + if (use_mapping) + p = transform(mapping, p); + KernelSunSky sunsky; precompute_sunsky(sun_direction, turbidity, sunsky); - Color = sky_xyz_radiance(sunsky, Vector); + Color = sky_xyz_radiance(sunsky, p); } diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl new file mode 100644 index 00000000000..731af89231a --- /dev/null +++ b/intern/cycles/kernel/shaders/node_tangent.osl @@ -0,0 +1,50 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_tangent( + normal NormalIn = N, + string attr_name = "geom:tangent", + string direction_type = "Radial", + string axis = "Z", + output normal Tangent = normalize(dPdu)) +{ + vector T; + + if (direction_type == "UV Map") { + getattribute(attr_name, T); + } + else if (direction_type == "Radial") { + point generated; + + if (!getattribute("geom:generated", generated)) + generated = P; + + if (axis == "X") + T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5)); + else if (axis == "Y") + T = vector(-(generated[2] - 0.5), 0.0, (generated[0] - 0.5)); + else + T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0); + } + + T = transform("object", "world", T); + Tangent = cross(NormalIn, normalize(cross(T, NormalIn))); +} + diff --git a/intern/cycles/kernel/shaders/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl index 791838dfffe..37460bcfc98 100644 --- a/intern/cycles/kernel/shaders/node_texture_coordinate.osl +++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl @@ -56,7 +56,7 @@ shader node_texture_coordinate( Camera = transform("camera", P); Window = transform("NDC", P); Normal = transform("world", "object", NormalIn); - Reflection = reflect(I, NormalIn); + Reflection = -reflect(I, NormalIn); } if (bump_offset == "dx") { @@ -77,5 +77,7 @@ shader node_texture_coordinate( Camera += Dy(Camera); Window += Dy(Window); } + + Window[2] = 0.0; } diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl index a44df00a267..43f8ecc666a 100644 --- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl +++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl @@ -22,17 +22,24 @@ /* Voronoi */ shader node_voronoi_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Coloring = "Intensity", float Scale = 5.0, point Vector = P, output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + /* compute distance and point coordinate of 4 nearest neighbours */ float da[4]; point pa[4]; - voronoi(Vector * Scale, "Distance Squared", 1.0, da, pa); + voronoi(p * Scale, "Distance Squared", 1.0, da, pa); /* Colored output */ if (Coloring == "Intensity") { diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl index 03a0477038e..82ce15ab9b6 100644 --- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl @@ -30,20 +30,20 @@ shader node_ward_bsdf( /* rotate tangent around normal */ vector T = Tangent; - if(Rotation != 0.0) + if (Rotation != 0.0) T = rotate(T, Rotation*2.0*M_PI, point(0.0, 0.0, 0.0), Normal); /* compute roughness */ float RoughnessU, RoughnessV; float aniso = clamp(Anisotropy, -0.99, 0.99); - if(aniso < 0.0) { - RoughnessU = Roughness*(1.0 + aniso); - RoughnessV = Roughness/(1.0 + aniso); + if (aniso < 0.0) { + RoughnessU = Roughness / (1.0 + aniso); + RoughnessV = Roughness * (1.0 + aniso); } else { - RoughnessU = Roughness/(1.0 - aniso); - RoughnessV = Roughness*(1.0 - aniso); + RoughnessU = Roughness * (1.0 - aniso); + RoughnessV = Roughness / (1.0 - aniso); } BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl index 79b8a8885d1..6648cd06278 100644 --- a/intern/cycles/kernel/shaders/node_wave_texture.osl +++ b/intern/cycles/kernel/shaders/node_wave_texture.osl @@ -46,6 +46,8 @@ float wave(point p, float scale, string type, float detail, float distortion, fl } shader node_wave_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "Bands", float Scale = 5.0, float Distortion = 0.0, @@ -55,7 +57,12 @@ shader node_wave_texture( output float Fac = 0.0, output color Color = color (0.0, 0.0, 0.0)) { - Fac = wave(Vector, Scale, Type, Detail, Distortion, DetailScale); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = wave(p, Scale, Type, Detail, Distortion, DetailScale); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index 4237291c7a4..24c3a50e6f6 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -433,6 +433,7 @@ string concat (string a, string b, string c, string d, string e, string f) { closure color diffuse(normal N) BUILTIN; closure color oren_nayar(normal N, float sigma) BUILTIN; +closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN; closure color translucent(normal N) BUILTIN; closure color reflection(normal N) BUILTIN; closure color refraction(normal N, float eta) BUILTIN; @@ -446,6 +447,7 @@ closure color ashikhmin_velvet(normal N, float sigma) BUILTIN; closure color emission() BUILTIN; closure color background() BUILTIN; closure color holdout() BUILTIN; +closure color ambient_occlusion() BUILTIN; // Renderer state int raytype (string typename) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 698ef5016f0..9c79886fdca 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -215,6 +215,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_CLOSURE_HOLDOUT: svm_node_closure_holdout(sd, stack, node); break; + case NODE_CLOSURE_AMBIENT_OCCLUSION: + svm_node_closure_ambient_occlusion(sd, stack, node); + break; case NODE_CLOSURE_VOLUME: svm_node_closure_volume(kg, sd, stack, node, path_flag); break; @@ -398,6 +401,16 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_LIGHT_FALLOFF: svm_node_light_falloff(sd, stack, node); break; +#endif +#ifdef __ANISOTROPIC__ + case NODE_TANGENT: + svm_node_tangent(kg, sd, stack, node); + break; +#endif +#ifdef __NORMAL_MAP__ + case NODE_NORMAL_MAP: + svm_node_normal_map(kg, sd, stack, node); + break; #endif case NODE_END: default: diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h index 7e38ac84bf1..49466c07a97 100644 --- a/intern/cycles/kernel/svm/svm_brick.h +++ b/intern/cycles/kernel/svm/svm_brick.h @@ -28,9 +28,9 @@ __device_noinline float brick_noise(int n) /* fast integer noise */ return 0.5f * ((float)nn / 1073741824.0f); } -__device_noinline float svm_brick(float3 p, float scale, float mortar_size, float bias, +__device_noinline float2 svm_brick(float3 p, float scale, float mortar_size, float bias, float brick_width, float row_height, float offset_amount, int offset_frequency, - float squash_amount, int squash_frequency, float *tint) + float squash_amount, int squash_frequency) { p *= scale; @@ -50,11 +50,12 @@ __device_noinline float svm_brick(float3 p, float scale, float mortar_size, floa x = (p.x+offset) - brick_width*bricknum; y = p.y - row_height*rownum; - *tint = clamp((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f); + return make_float2( + clamp((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f), - return (x < mortar_size || y < mortar_size || + (x < mortar_size || y < mortar_size || x > (brick_width - mortar_size) || - y > (row_height - mortar_size)) ? 1.0f : 0.0f; + y > (row_height - mortar_size)) ? 1.0f : 0.0f); } __device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) @@ -70,8 +71,6 @@ __device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack /* RNA properties */ uint offset_frequency, squash_frequency; - float tint = 0.0f; - decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &mortar_offset); decode_node_uchar4(node.z, &scale_offset, &mortar_size_offset, &bias_offset, &brick_width_offset); decode_node_uchar4(node.w, &row_height_offset, &color_offset, &fac_offset, NULL); @@ -92,9 +91,11 @@ __device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack float offset_amount = __int_as_float(node3.z); float squash_amount = __int_as_float(node3.w); - float f = svm_brick(co, scale, mortar_size, bias, brick_width, row_height, - offset_amount, offset_frequency, squash_amount, squash_frequency, - &tint); + float2 f2 = svm_brick(co, scale, mortar_size, bias, brick_width, row_height, + offset_amount, offset_frequency, squash_amount, squash_frequency); + + float tint = f2.x; + float f = f2.y; if(f != 1.0f) { float facm = 1.0f - tint; diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h index 07c20231d54..07927fe5691 100644 --- a/intern/cycles/kernel/svm/svm_bsdf.h +++ b/intern/cycles/kernel/svm/svm_bsdf.h @@ -19,11 +19,12 @@ #include "../closure/bsdf_ashikhmin_velvet.h" #include "../closure/bsdf_diffuse.h" #include "../closure/bsdf_oren_nayar.h" +#include "../closure/bsdf_phong_ramp.h" #include "../closure/bsdf_microfacet.h" #include "../closure/bsdf_reflection.h" #include "../closure/bsdf_refraction.h" #include "../closure/bsdf_transparent.h" -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ #include "../closure/bsdf_ward.h" #endif #include "../closure/bsdf_westin.h" @@ -44,6 +45,10 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); @@ -70,7 +75,7 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa label = bsdf_microfacet_beckmann_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); @@ -110,6 +115,9 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con case CLOSURE_BSDF_OREN_NAYAR_ID: eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf); break; @@ -130,7 +138,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf); break; @@ -179,7 +187,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf); break; @@ -213,6 +221,9 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness) case CLOSURE_BSDF_OREN_NAYAR_ID: bsdf_oren_nayar_blur(sc, roughness); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + bsdf_phong_ramp_blur(sc, roughness); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: bsdf_translucent_blur(sc, roughness); break; @@ -233,7 +244,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness) case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: bsdf_microfacet_beckmann_blur(sc, roughness); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: bsdf_ward_blur(sc, roughness); break; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 11ce3b7c5d1..b5bd2b42cb4 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -20,9 +20,9 @@ CCL_NAMESPACE_BEGIN /* Closure Nodes */ -__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) +__device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) { - if(type == CLOSURE_BSDF_REFRACTION_ID) { + if(type == CLOSURE_BSDF_SHARP_GLASS_ID) { if(refract) { sc->data0 = eta; sd->flag |= bsdf_refraction_setup(sc); @@ -30,7 +30,7 @@ __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, else sd->flag |= bsdf_reflection_setup(sc); } - else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) { sc->data0 = roughness; sc->data1 = eta; @@ -50,25 +50,41 @@ __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, } } -__device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd) +__device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, ClosureType type, float mix_weight) { #ifdef __MULTI_CLOSURE__ ShaderClosure *sc = &sd->closure[sd->num_closure]; - if(sd->num_closure < MAX_CLOSURE) + if(sd->num_closure < MAX_CLOSURE) { + sc->weight *= mix_weight; + sc->type = type; sd->num_closure++; + return sc; + } - return sc; + return NULL; #else return &sd->closure; #endif } -__device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mix_weight) +__device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float mix_weight) { #ifdef __MULTI_CLOSURE__ - sc->weight *= mix_weight; - sc->sample_weight = fabsf(average(sc->weight)); + ShaderClosure *sc = &sd->closure[sd->num_closure]; + float3 weight = sc->weight * mix_weight; + float sample_weight = fabsf(average(weight)); + + if(sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) { + sc->weight = weight; + sc->sample_weight = sample_weight; + sd->num_closure++; + return sc; + } + + return NULL; +#else + return &sd->closure; #endif } @@ -101,33 +117,39 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st switch(type) { case CLOSURE_BSDF_DIFFUSE_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - float roughness = param1; + if(sc) { + sc->N = N; - if(roughness == 0.0f) { - sd->flag |= bsdf_diffuse_setup(sc); - } - else { - sc->data0 = roughness; - sd->flag |= bsdf_oren_nayar_setup(sc); + float roughness = param1; + + if(roughness == 0.0f) { + sd->flag |= bsdf_diffuse_setup(sc); + } + else { + sc->data0 = roughness; + sd->flag |= bsdf_oren_nayar_setup(sc); + } } break; } case CLOSURE_BSDF_TRANSLUCENT_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - svm_node_closure_set_mix_weight(sc, mix_weight); - sd->flag |= bsdf_translucent_setup(sc); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + + if(sc) { + sc->N = N; + sd->flag |= bsdf_translucent_setup(sc); + } break; } case CLOSURE_BSDF_TRANSPARENT_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - svm_node_closure_set_mix_weight(sc, mix_weight); - sd->flag |= bsdf_transparent_setup(sc); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + + if(sc) { + sc->N = N; + sd->flag |= bsdf_transparent_setup(sc); + } break; } case CLOSURE_BSDF_REFLECTION_ID: @@ -137,18 +159,20 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - sc->data0 = param1; - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - /* setup bsdf */ - if(type == CLOSURE_BSDF_REFLECTION_ID) - sd->flag |= bsdf_reflection_setup(sc); - else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) - sd->flag |= bsdf_microfacet_beckmann_setup(sc); - else - sd->flag |= bsdf_microfacet_ggx_setup(sc); + if(sc) { + sc->N = N; + sc->data0 = param1; + + /* setup bsdf */ + if(type == CLOSURE_BSDF_REFLECTION_ID) + sd->flag |= bsdf_reflection_setup(sc); + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) + sd->flag |= bsdf_microfacet_beckmann_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_setup(sc); + } break; } @@ -158,6 +182,33 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st #ifdef __CAUSTICS_TRICKS__ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; +#endif + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + + if(sc) { + sc->N = N; + sc->data0 = param1; + + float eta = fmaxf(param2, 1.0f + 1e-5f); + sc->data1 = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; + + /* setup bsdf */ + if(type == CLOSURE_BSDF_REFRACTION_ID) + sd->flag |= bsdf_refraction_setup(sc); + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + } + + break; + } + case CLOSURE_BSDF_SHARP_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: { +#ifdef __CAUSTICS_TRICKS__ + if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) + break; #endif /* index of refraction */ float eta = fmaxf(param2, 1.0f + 1e-5f); @@ -170,78 +221,89 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st #ifdef __MULTI_CLOSURE__ /* reflection */ - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - + ShaderClosure *sc = &sd->closure[sd->num_closure]; float3 weight = sc->weight; float sample_weight = sc->sample_weight; - svm_node_closure_set_mix_weight(sc, mix_weight*fresnel); - svm_node_glossy_setup(sd, sc, type, eta, roughness, false); + sc = svm_node_closure_get_bsdf(sd, mix_weight*fresnel); + + if(sc) { + sc->N = N; + svm_node_glass_setup(sd, sc, type, eta, roughness, false); + } /* refraction */ - sc = svm_node_closure_get(sd); - sc->N = N; - + sc = &sd->closure[sd->num_closure]; sc->weight = weight; sc->sample_weight = sample_weight; - svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel)); - svm_node_glossy_setup(sd, sc, type, eta, roughness, true); + sc = svm_node_closure_get_bsdf(sd, mix_weight*(1.0f - fresnel)); + + if(sc) { + sc->N = N; + svm_node_glass_setup(sd, sc, type, eta, roughness, true); + } #else - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - bool refract = (randb > fresnel); - - svm_node_closure_set_mix_weight(sc, mix_weight); - svm_node_glossy_setup(sd, sc, type, eta, roughness, refract); + if(sc) { + sc->N = N; + bool refract = (randb > fresnel); + svm_node_glass_setup(sd, sc, type, eta, roughness, refract); + } #endif break; } -#ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: { #ifdef __CAUSTICS_TRICKS__ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - sc->T = stack_load_float3(stack, data_node.z); - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - /* rotate tangent */ - float rotation = stack_load_float(stack, data_node.w); + if(sc) { + sc->N = N; - if(rotation != 0.0f) - sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); +#ifdef __ANISOTROPIC__ + sc->T = stack_load_float3(stack, data_node.z); - /* compute roughness */ - float roughness = param1; - float anisotropy = clamp(param2, -0.99f, 0.99f); + /* rotate tangent */ + float rotation = stack_load_float(stack, data_node.w); - if(anisotropy < 0.0f) { - sc->data0 = roughness*(1.0f + anisotropy); - sc->data1 = roughness/(1.0f + anisotropy); + if(rotation != 0.0f) + sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); + + /* compute roughness */ + float roughness = param1; + float anisotropy = clamp(param2, -0.99f, 0.99f); + + if(anisotropy < 0.0f) { + sc->data0 = roughness/(1.0f + anisotropy); + sc->data1 = roughness*(1.0f + anisotropy); + } + else { + sc->data0 = roughness*(1.0f - anisotropy); + sc->data1 = roughness/(1.0f - anisotropy); + } + + sd->flag |= bsdf_ward_setup(sc); +#else + sd->flag |= bsdf_diffuse_setup(sc); +#endif } - else { - sc->data0 = roughness/(1.0f - anisotropy); - sc->data1 = roughness*(1.0f - anisotropy); - } - - sd->flag |= bsdf_ward_setup(sc); break; } -#endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - /* sigma */ - sc->data0 = clamp(param1, 0.0f, 1.0f); - sd->flag |= bsdf_ashikhmin_velvet_setup(sc); + if(sc) { + sc->N = N; + + /* sigma */ + sc->data0 = clamp(param1, 0.0f, 1.0f); + sd->flag |= bsdf_ashikhmin_velvet_setup(sc); + } break; } default: @@ -270,19 +332,21 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float * switch(type) { case CLOSURE_VOLUME_TRANSPARENT_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - float density = param1; - sd->flag |= volume_transparent_setup(sc, density); + if(sc) { + float density = param1; + sd->flag |= volume_transparent_setup(sc, density); + } break; } case CLOSURE_VOLUME_ISOTROPIC_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - float density = param1; - sd->flag |= volume_isotropic_setup(sc, density); + if(sc) { + float density = param1; + sd->flag |= volume_isotropic_setup(sc, density); + } break; } default: @@ -301,15 +365,10 @@ __device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node if(mix_weight == 0.0f) return; - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight *= mix_weight; - sc->type = CLOSURE_EMISSION_ID; + svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, mix_weight); } - else { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->type = CLOSURE_EMISSION_ID; - } - + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, 1.0f); #else ShaderClosure *sc = &sd->closure; sc->type = CLOSURE_EMISSION_ID; @@ -329,15 +388,10 @@ __device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 no if(mix_weight == 0.0f) return; - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight *= mix_weight; - sc->type = CLOSURE_BACKGROUND_ID; + svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, mix_weight); } - else { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->type = CLOSURE_BACKGROUND_ID; - } - + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, 1.0f); #else ShaderClosure *sc = &sd->closure; sc->type = CLOSURE_BACKGROUND_ID; @@ -355,15 +409,10 @@ __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node) if(mix_weight == 0.0f) return; - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight = make_float3(mix_weight, mix_weight, mix_weight); - sc->type = CLOSURE_HOLDOUT_ID; - } - else { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight = make_float3(1.0f, 1.0f, 1.0f); - sc->type = CLOSURE_HOLDOUT_ID; + svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, mix_weight); } + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, 1.0f); #else ShaderClosure *sc = &sd->closure; sc->type = CLOSURE_HOLDOUT_ID; @@ -372,12 +421,36 @@ __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node) sd->flag |= SD_HOLDOUT; } +__device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node) +{ +#ifdef __MULTI_CLOSURE__ + uint mix_weight_offset = node.y; + + if(stack_valid(mix_weight_offset)) { + float mix_weight = stack_load_float(stack, mix_weight_offset); + + if(mix_weight == 0.0f) + return; + + svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, mix_weight); + } + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, 1.0f); +#else + ShaderClosure *sc = &sd->closure; + sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; +#endif + + sd->flag |= SD_AO; +} + /* Closure Nodes */ __device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight) { #ifdef __MULTI_CLOSURE__ - sd->closure[sd->num_closure].weight = weight; + if(sd->num_closure < MAX_CLOSURE) + sd->closure[sd->num_closure].weight = weight; #else sd->closure.weight = weight; #endif diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 8e772f849c7..c4d03c1f948 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -29,29 +29,18 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, case NODE_GEOM_N: data = sd->N; break; #ifdef __DPDU__ case NODE_GEOM_T: { - /* first try to get tangent attribute */ - int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_TANGENT): ATTR_STD_NOT_FOUND; + /* try to create spherical tangent from generated coordinates */ + int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND; if(attr_offset != ATTR_STD_NOT_FOUND) { - /* ensure orthogonal and normalized (interpolation breaks it) */ - data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); + data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); object_normal_transform(kg, sd, &data); data = cross(sd->N, normalize(cross(data, sd->N)));; } else { - /* try to create spherical tangent from generated coordinates */ - int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND; - - if(attr_offset != ATTR_STD_NOT_FOUND) { - data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); - data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f); - object_normal_transform(kg, sd, &data); - data = cross(sd->N, normalize(cross(data, sd->N)));; - } - else { - /* otherwise use surface derivatives */ - data = normalize(sd->dPdu); - } + /* otherwise use surface derivatives */ + data = normalize(sd->dPdu); } break; diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h index bce11d62923..26b6141ee3f 100644 --- a/intern/cycles/kernel/svm/svm_hsv.h +++ b/intern/cycles/kernel/svm/svm_hsv.h @@ -110,7 +110,7 @@ __device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, uint color = rgb_to_hsv(color); - // remember: fmod doesn't work for negative numbers + /* remember: fmod doesn't work for negative numbers here */ color.x += hue + 0.5f; color.x = fmod(color.x, 1.0f); color.y *= sat; diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h index e39c7a4ba6c..db3b8d3f763 100644 --- a/intern/cycles/kernel/svm/svm_math.h +++ b/intern/cycles/kernel/svm/svm_math.h @@ -38,6 +38,21 @@ __device float safe_acosf(float a) return acosf(a); } +__device float compatible_powf(float x, float y) +{ + /* GPU pow doesn't accept negative x, do manual checks here */ + if(x < 0.0f) { + if(fmod(-y, 2.0f) == 0.0f) + return powf(-x, y); + else + return -powf(-x, y); + } + else if(x == 0.0f) + return 0.0f; + + return powf(x, y); +} + __device float safe_powf(float a, float b) { if(b == 0.0f) @@ -47,7 +62,7 @@ __device float safe_powf(float a, float b) if(a < 0.0f && b != (int)b) return 0.0f; - return powf(a, b); + return compatible_powf(a, b); } __device float safe_logf(float a, float b) diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h index 55c2b3f6af4..c64413cbe84 100644 --- a/intern/cycles/kernel/svm/svm_ramp.h +++ b/intern/cycles/kernel/svm/svm_ramp.h @@ -25,7 +25,8 @@ __device float4 rgb_ramp_lookup(KernelGlobals *kg, int offset, float f) { f = clamp(f, 0.0f, 1.0f)*(RAMP_TABLE_SIZE-1); - int i = (int)f; + /* clamp int as well in case of NaN */ + int i = clamp((int)f, 0, RAMP_TABLE_SIZE-1); float t = f - (float)i; float4 a = fetch_node_float(kg, offset+i); diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 6bd8f2ac69c..9f2d3367420 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -20,17 +20,19 @@ CCL_NAMESPACE_BEGIN /* Texture Coordinate Node */ -__device_inline float3 svm_background_offset(KernelGlobals *kg) +__device_inline float3 svm_background_position(KernelGlobals *kg, float3 P) { Transform cameratoworld = kernel_data.cam.cameratoworld; - return make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + + return camP + P; } __device_inline float3 svm_world_to_ndc(KernelGlobals *kg, ShaderData *sd, float3 P) { if(kernel_data.cam.type != CAMERA_PANORAMA) { if(sd->object == ~0) - P += svm_background_offset(kg); + P = svm_background_position(kg, P); Transform tfm = kernel_data.cam.worldtondc; return transform_perspective(&tfm, P); @@ -78,11 +80,12 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack if(sd->object != ~0) data = transform_point(&tfm, sd->P); else - data = transform_point(&tfm, sd->P + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -135,11 +138,12 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa if(sd->object != ~0) data = transform_point(&tfm, sd->P + sd->dP.dx); else - data = transform_point(&tfm, sd->P + sd->dP.dx + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P + sd->dP.dx)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P + sd->dP.dx); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -195,11 +199,12 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa if(sd->object != ~0) data = transform_point(&tfm, sd->P + sd->dP.dy); else - data = transform_point(&tfm, sd->P + sd->dP.dy + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P + sd->dP.dy)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P + sd->dP.dy); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -225,5 +230,100 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa #endif } +__device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) +{ + uint color_offset, strength_offset, normal_offset, space; + decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space); + + float3 color = stack_load_float3(stack, color_offset); + color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f); + + float3 N; + + if(space == NODE_NORMAL_MAP_TANGENT) { + /* tangent space */ + if(sd->object == ~0) { + stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); + return; + } + + /* first try to get tangent attribute */ + int attr_offset = find_attribute(kg, sd, node.z); + int attr_sign_offset = find_attribute(kg, sd, node.w); + + if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) { + stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); + return; + } + + /* ensure orthogonal and normalized (interpolation breaks it) */ + float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL); + + object_normal_transform(kg, sd, &tangent); + tangent = cross(sd->N, normalize(cross(tangent, sd->N)));; + + float3 B = sign * cross(sd->N, tangent); + N = normalize(color.x * tangent + color.y * B + color.z * sd->N); + } + else { + /* object, world space */ + N = color; + + if(space == NODE_NORMAL_MAP_OBJECT) + object_normal_transform(kg, sd, &N); + + N = normalize(N); + } + + float strength = stack_load_float(stack, strength_offset); + + if(strength != 1.0f) { + strength = max(strength, 0.0f); + N = normalize(sd->N + (N - sd->N)*strength); + } + + stack_store_float3(stack, normal_offset, N); +} + +__device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) +{ + uint tangent_offset, direction_type, axis; + decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL); + + float3 tangent; + + if(direction_type == NODE_TANGENT_UVMAP) { + /* UV map */ + int attr_offset = find_attribute(kg, sd, node.z); + + if(attr_offset == ATTR_STD_NOT_FOUND) + tangent = make_float3(0.0f, 0.0f, 0.0f); + else + tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + } + else { + /* radial */ + int attr_offset = find_attribute(kg, sd, node.z); + float3 generated; + + if(attr_offset == ATTR_STD_NOT_FOUND) + generated = sd->P; + else + generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); + + if(axis == NODE_TANGENT_AXIS_X) + tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f)); + else if(axis == NODE_TANGENT_AXIS_Y) + tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f)); + else + tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f); + } + + object_normal_transform(kg, sd, &tangent); + tangent = cross(sd->N, normalize(cross(tangent, sd->N))); + stack_store_float3(stack, tangent_offset, tangent); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h index 6c22d98e0df..a4f6691435c 100644 --- a/intern/cycles/kernel/svm/svm_texture.h +++ b/intern/cycles/kernel/svm/svm_texture.h @@ -42,8 +42,12 @@ __device float voronoi_distance(NodeDistanceMetric distance_metric, float3 d, fl /* Voronoi / Worley like */ -__device_noinline void voronoi(float3 p, NodeDistanceMetric distance_metric, float e, float da[4], float3 pa[4]) +__device_noinline float4 voronoi_Fn(float3 p, float e, int n1, int n2) { + float da[4]; + float3 pa[4]; + NodeDistanceMetric distance_metric = NODE_VORONOI_DISTANCE_SQUARED; + /* returns distances in da and point coords in pa */ int xx, yy, zz, xi, yi, zi; @@ -105,33 +109,20 @@ __device_noinline void voronoi(float3 p, NodeDistanceMetric distance_metric, flo } } } + + float4 result = make_float4(pa[n1].x, pa[n1].y, pa[n1].z, da[n1]); + + if(n2 != -1) + result = make_float4(pa[n2].x, pa[n2].y, pa[n2].z, da[n2]) - result; + + return result; } -__device float voronoi_Fn(float3 p, int n) -{ - float da[4]; - float3 pa[4]; - - voronoi(p, NODE_VORONOI_DISTANCE_SQUARED, 0, da, pa); - - return da[n]; -} - -__device float voronoi_FnFn(float3 p, int n1, int n2) -{ - float da[4]; - float3 pa[4]; - - voronoi(p, NODE_VORONOI_DISTANCE_SQUARED, 0, da, pa); - - return da[n2] - da[n1]; -} - -__device float voronoi_F1(float3 p) { return voronoi_Fn(p, 0); } -__device float voronoi_F2(float3 p) { return voronoi_Fn(p, 1); } -__device float voronoi_F3(float3 p) { return voronoi_Fn(p, 2); } -__device float voronoi_F4(float3 p) { return voronoi_Fn(p, 3); } -__device float voronoi_F1F2(float3 p) { return voronoi_FnFn(p, 0, 1); } +__device float voronoi_F1(float3 p) { return voronoi_Fn(p, 0.0f, 0, -1).w; } +__device float voronoi_F2(float3 p) { return voronoi_Fn(p, 0.0f, 1, -1).w; } +__device float voronoi_F3(float3 p) { return voronoi_Fn(p, 0.0f, 2, -1).w; } +__device float voronoi_F4(float3 p) { return voronoi_Fn(p, 0.0f, 3, -1).w; } +__device float voronoi_F1F2(float3 p) { return voronoi_Fn(p, 0.0f, 0, 1).w; } __device float voronoi_Cr(float3 p) { diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 77df373a159..b41e34ab407 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -94,6 +94,9 @@ typedef enum NodeType { NODE_PARTICLE_INFO, NODE_TEX_BRICK, NODE_CLOSURE_SET_NORMAL, + NODE_CLOSURE_AMBIENT_OCCLUSION, + NODE_TANGENT, + NODE_NORMAL_MAP } NodeType; typedef enum NodeAttributeType { @@ -279,6 +282,23 @@ typedef enum NodeBlendWeightType { NODE_LAYER_WEIGHT_FACING } NodeBlendWeightType; +typedef enum NodeTangentDirectionType { + NODE_TANGENT_RADIAL, + NODE_TANGENT_UVMAP +} NodeTangentDirectionType; + +typedef enum NodeTangentAxis { + NODE_TANGENT_AXIS_X, + NODE_TANGENT_AXIS_Y, + NODE_TANGENT_AXIS_Z +} NodeTangentAxis; + +typedef enum NodeNormalMapSpace { + NODE_NORMAL_MAP_TANGENT, + NODE_NORMAL_MAP_OBJECT, + NODE_NORMAL_MAP_WORLD +} NodeNormalMapSpace; + typedef enum ShaderType { SHADER_TYPE_SURFACE, SHADER_TYPE_VOLUME, @@ -300,6 +320,7 @@ typedef enum ClosureType { CLOSURE_BSDF_WARD_ID, CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, CLOSURE_BSDF_WESTIN_SHEEN_ID, + CLOSURE_BSDF_PHONG_RAMP_ID, CLOSURE_BSDF_TRANSMISSION_ID, CLOSURE_BSDF_TRANSLUCENT_ID, @@ -307,7 +328,9 @@ typedef enum ClosureType { CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, - CLOSURE_BSDF_GLASS_ID, + CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID, + CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID, + CLOSURE_BSDF_SHARP_GLASS_ID, CLOSURE_BSDF_TRANSPARENT_ID, @@ -317,6 +340,7 @@ typedef enum ClosureType { CLOSURE_BACKGROUND_ID, CLOSURE_HOLDOUT_ID, CLOSURE_SUBSURFACE_ID, + CLOSURE_AMBIENT_OCCLUSION_ID, CLOSURE_VOLUME_ID, CLOSURE_VOLUME_TRANSPARENT_ID, @@ -328,12 +352,13 @@ typedef enum ClosureType { /* watch this, being lazy with memory usage */ #define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID) #define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_OREN_NAYAR_ID) -#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_WESTIN_SHEEN_ID) -#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_GLASS_ID) +#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_PHONG_RAMP_ID) +#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID) #define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID) #define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID) #define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID) #define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID) +#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h index 7e7bd970320..55110d06f22 100644 --- a/intern/cycles/kernel/svm/svm_voronoi.h +++ b/intern/cycles/kernel/svm/svm_voronoi.h @@ -23,21 +23,18 @@ CCL_NAMESPACE_BEGIN __device_noinline float4 svm_voronoi(NodeVoronoiColoring coloring, float scale, float3 p) { /* compute distance and point coordinate of 4 nearest neighbours */ - float da[4]; - float3 pa[4]; - - voronoi(p*scale, NODE_VORONOI_DISTANCE_SQUARED, 1.0f, da, pa); + float4 dpa0 = voronoi_Fn(p*scale, 1.0f, 0, -1); /* output */ float fac; float3 color; if(coloring == NODE_VORONOI_INTENSITY) { - fac = fabsf(da[0]); + fac = fabsf(dpa0.w); color = make_float3(fac, fac, fac); } else { - color = cellnoise_color(pa[0]); + color = cellnoise_color(float4_to_float3(dpa0)); fac = average(color); } diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index c7a9ab3e51a..95941c14b6c 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -162,8 +162,10 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) attr = add(name, TypeDesc::TypeNormal, Attribute::FACE); else if(std == ATTR_STD_UV) attr = add(name, TypeDesc::TypePoint, Attribute::CORNER); - else if(std == ATTR_STD_TANGENT) + else if(std == ATTR_STD_UV_TANGENT) attr = add(name, TypeDesc::TypeVector, Attribute::CORNER); + else if(std == ATTR_STD_UV_TANGENT_SIGN) + attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER); else if(std == ATTR_STD_GENERATED) attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); else if(std == ATTR_STD_POSITION_UNDEFORMED) diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 649936bec04..a78ede979b2 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -55,15 +55,10 @@ Camera::Camera() width = 1024; height = 512; - left = -((float)width/(float)height); - right = (float)width/(float)height; - bottom = -1.0f; - top = 1.0f; - - border_left = 0.0f; - border_right = 1.0f; - border_bottom = 0.0f; - border_top = 1.0f; + viewplane.left = -((float)width/(float)height); + viewplane.right = (float)width/(float)height; + viewplane.bottom = -1.0f; + viewplane.top = 1.0f; screentoworld = transform_identity(); rastertoworld = transform_identity(); @@ -94,12 +89,12 @@ void Camera::update() Transform ndctoraster = transform_scale(width, height, 1.0f); /* raster to screen */ - Transform screentoraster = ndctoraster; - - screentoraster = ndctoraster * - transform_scale(1.0f/(right - left), 1.0f/(top - bottom), 1.0f) * - transform_translate(-left, -bottom, 0.0f); + Transform screentondc = + transform_scale(1.0f/(viewplane.right - viewplane.left), + 1.0f/(viewplane.top - viewplane.bottom), 1.0f) * + transform_translate(-viewplane.left, -viewplane.bottom, 0.0f); + Transform screentoraster = ndctoraster * screentondc; Transform rastertoscreen = transform_inverse(screentoraster); /* screen to camera */ @@ -109,14 +104,24 @@ void Camera::update() screentocamera = transform_inverse(transform_orthographic(nearclip, farclip)); else screentocamera = transform_identity(); + + Transform cameratoscreen = transform_inverse(screentocamera); rastertocamera = screentocamera * rastertoscreen; + cameratoraster = screentoraster * cameratoscreen; cameratoworld = matrix; screentoworld = cameratoworld * screentocamera; rastertoworld = cameratoworld * rastertocamera; ndctoworld = rastertoworld * ndctoraster; - worldtoraster = transform_inverse(rastertoworld); + + /* note we recompose matrices instead of taking inverses of the above, this + * is needed to avoid inverting near degenerate matrices that happen due to + * precision issues with large scenes */ + worldtocamera = transform_inverse(matrix); + worldtoscreen = cameratoscreen * worldtocamera; + worldtondc = screentondc * worldtoscreen; + worldtoraster = ndctoraster * worldtondc; /* differentials */ if(type == CAMERA_ORTHOGRAPHIC) { @@ -164,10 +169,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->rastertoworld = rastertoworld; kcam->rastertocamera = rastertocamera; kcam->cameratoworld = cameratoworld; - kcam->worldtoscreen = transform_inverse(screentoworld); + kcam->worldtocamera = worldtocamera; + kcam->worldtoscreen = worldtoscreen; kcam->worldtoraster = worldtoraster; - kcam->worldtondc = transform_inverse(ndctoworld); - kcam->worldtocamera = transform_inverse(cameratoworld); + kcam->worldtondc = worldtondc; /* camera motion */ kcam->have_motion = 0; @@ -185,8 +190,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) } else { if(use_motion) { - kcam->motion.pre = transform_inverse(motion.pre * rastertocamera); - kcam->motion.post = transform_inverse(motion.post * rastertocamera); + kcam->motion.pre = cameratoraster * transform_inverse(motion.pre); + kcam->motion.post = cameratoraster * transform_inverse(motion.post); } else { kcam->motion.pre = worldtoraster; @@ -197,7 +202,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) #ifdef __CAMERA_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { if(use_motion) { - transform_motion_decompose(&kcam->motion, &motion, &matrix); + transform_motion_decompose((DecompMotionTransform*)&kcam->motion, &motion, &matrix); kcam->have_motion = 1; } } @@ -265,14 +270,8 @@ bool Camera::modified(const Camera& cam) // modified for progressive render // (width == cam.width) && // (height == cam.height) && - (left == cam.left) && - (right == cam.right) && - (bottom == cam.bottom) && - (top == cam.top) && - (border_left == cam.border_left) && - (border_right == cam.border_right) && - (border_bottom == cam.border_bottom) && - (border_top == cam.border_top) && + (viewplane == cam.viewplane) && + (border == cam.border) && (matrix == cam.matrix) && (panorama_type == cam.panorama_type) && (fisheye_fov == cam.fisheye_fov) && diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 1407c86e7c2..9696161180d 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -21,6 +21,7 @@ #include "kernel_types.h" +#include "util_boundbox.h" #include "util_transform.h" #include "util_types.h" @@ -65,10 +66,10 @@ public: /* screen */ int width, height; - float left, right, bottom, top; + BoundBox2D viewplane; /* border */ - float border_left, border_right, border_bottom, border_top; + BoundBox2D border; /* transformation */ Transform matrix; @@ -81,9 +82,15 @@ public: Transform screentoworld; Transform rastertoworld; Transform ndctoworld; - Transform rastertocamera; Transform cameratoworld; + Transform worldtoraster; + Transform worldtoscreen; + Transform worldtondc; + Transform worldtocamera; + + Transform rastertocamera; + Transform cameratoraster;; float3 dx; float3 dy; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index c1c976dc193..14b219383d0 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -37,7 +37,7 @@ ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketTyp value = make_float3(0, 0, 0); stack_offset = SVM_STACK_INVALID; default_value = NONE; - osl_only = false; + usage = USE_ALL; } ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_) @@ -85,27 +85,29 @@ ShaderOutput *ShaderNode::output(const char *name) return NULL; } -ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value) +ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value, int usage) { ShaderInput *input = new ShaderInput(this, name, type); input->value.x = value; + input->usage = usage; inputs.push_back(input); return input; } -ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value) +ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value, int usage) { ShaderInput *input = new ShaderInput(this, name, type); input->value = value; + input->usage = usage; inputs.push_back(input); return input; } -ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only) +ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage) { ShaderInput *input = add_input(name, type); input->default_value = value; - input->osl_only = osl_only; + input->usage = usage; return input; } @@ -219,7 +221,7 @@ void ShaderGraph::disconnect(ShaderInput *to) from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end()); } -void ShaderGraph::finalize(bool do_bump, bool do_osl) +void ShaderGraph::finalize(bool do_bump, bool do_osl, bool do_multi_transform) { /* before compiling, the shader graph may undergo a number of modifications. * currently we set default geometry shader inputs, and create automatic bump @@ -234,6 +236,18 @@ void ShaderGraph::finalize(bool do_bump, bool do_osl) if(do_bump) bump_from_displacement(); + if(do_multi_transform) { + ShaderInput *surface_in = output()->input("Surface"); + ShaderInput *volume_in = output()->input("Volume"); + + /* todo: make this work when surface and volume closures are tangled up */ + + if(surface_in->link) + transform_multi_closure(surface_in->link->parent, NULL, false); + if(volume_in->link) + transform_multi_closure(volume_in->link->parent, NULL, true); + } + finalized = true; } } @@ -326,6 +340,7 @@ void ShaderGraph::remove_proxy_nodes(vector& removed) /* transfer the default input value to the target socket */ to->set(input->value); + to->set(input->value_string); } } @@ -439,7 +454,7 @@ void ShaderGraph::default_inputs(bool do_osl) foreach(ShaderNode *node, nodes) { foreach(ShaderInput *input, node->inputs) { - if(!input->link && !(input->osl_only && !do_osl)) { + if(!input->link && ((input->usage & ShaderInput::USE_SVM) || do_osl)) { if(input->default_value == ShaderInput::TEXTURE_GENERATED) { if(!texco) texco = new TextureCoordinateNode(); @@ -628,5 +643,81 @@ void ShaderGraph::bump_from_displacement() add(pair.second); } +void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume) +{ + /* for SVM in multi closure mode, this transforms the shader mix/add part of + * the graph into nodes that feed weights into closure nodes. this is too + * avoid building a closure tree and then flattening it, and instead write it + * directly to an array */ + + if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { + ShaderInput *fin = node->input("Fac"); + ShaderInput *cl1in = node->input("Closure1"); + ShaderInput *cl2in = node->input("Closure2"); + ShaderOutput *weight1_out, *weight2_out; + + if(fin) { + /* mix closure: add node to mix closure weights */ + ShaderNode *mix_node = add(new MixClosureWeightNode()); + ShaderInput *fac_in = mix_node->input("Fac"); + ShaderInput *weight_in = mix_node->input("Weight"); + + if(fin->link) + connect(fin->link, fac_in); + else + fac_in->value = fin->value; + + if(weight_out) + connect(weight_out, weight_in); + + weight1_out = mix_node->output("Weight1"); + weight2_out = mix_node->output("Weight2"); + } + else { + /* add closure: just pass on any weights */ + weight1_out = weight_out; + weight2_out = weight_out; + } + + if(cl1in->link) + transform_multi_closure(cl1in->link->parent, weight1_out, volume); + if(cl2in->link) + transform_multi_closure(cl2in->link->parent, weight2_out, volume); + } + else { + ShaderInput *weight_in = node->input((volume)? "VolumeMixWeight": "SurfaceMixWeight"); + + /* not a closure node? */ + if(!weight_in) + return; + + /* already has a weight connected to it? add weights */ + if(weight_in->link || weight_in->value.x != 0.0f) { + ShaderNode *math_node = add(new MathNode()); + ShaderInput *value1_in = math_node->input("Value1"); + ShaderInput *value2_in = math_node->input("Value2"); + + if(weight_in->link) + connect(weight_in->link, value1_in); + else + value1_in->value = weight_in->value; + + if(weight_out) + connect(weight_out, value2_in); + else + value2_in->value.x = 1.0f; + + weight_out = math_node->output("Value"); + disconnect(weight_in); + } + + /* connected to closure mix weight */ + if(weight_out) + connect(weight_out, weight_in); + else + weight_in->value.x += 1.0f; + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index b339c3c3847..b79167839ab 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -49,7 +49,8 @@ enum ShaderSocketType { SHADER_SOCKET_VECTOR, SHADER_SOCKET_POINT, SHADER_SOCKET_NORMAL, - SHADER_SOCKET_CLOSURE + SHADER_SOCKET_CLOSURE, + SHADER_SOCKET_STRING }; /* Bump @@ -117,9 +118,16 @@ public: NONE }; + enum Usage { + USE_SVM = 1, + USE_OSL = 2, + USE_ALL = USE_SVM|USE_OSL + }; + ShaderInput(ShaderNode *parent, const char *name, ShaderSocketType type); void set(const float3& v) { value = v; } void set(float f) { value = make_float3(f, 0, 0); } + void set(const ustring v) { value_string = v; } const char *name; ShaderSocketType type; @@ -129,9 +137,10 @@ public: DefaultValue default_value; float3 value; + ustring value_string; int stack_offset; /* for SVM compiler */ - bool osl_only; + int usage; }; /* Output @@ -164,9 +173,9 @@ public: ShaderInput *input(const char *name); ShaderOutput *output(const char *name); - ShaderInput *add_input(const char *name, ShaderSocketType type, float value=0.0f); - ShaderInput *add_input(const char *name, ShaderSocketType type, float3 value); - ShaderInput *add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only=false); + ShaderInput *add_input(const char *name, ShaderSocketType type, float value=0.0f, int usage=ShaderInput::USE_ALL); + ShaderInput *add_input(const char *name, ShaderSocketType type, float3 value, int usage=ShaderInput::USE_ALL); + ShaderInput *add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage=ShaderInput::USE_ALL); ShaderOutput *add_output(const char *name, ShaderSocketType type); virtual ShaderNode *clone() const = 0; @@ -224,7 +233,7 @@ public: void connect(ShaderOutput *from, ShaderInput *to); void disconnect(ShaderInput *to); - void finalize(bool do_bump = false, bool do_osl = false); + void finalize(bool do_bump = false, bool do_osl = false, bool do_multi_closure = false); protected: typedef pair NodePair; @@ -238,6 +247,7 @@ protected: void bump_from_displacement(); void refine_bump_nodes(); void default_inputs(bool do_osl); + void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index f136f08dc2c..230a12f9ff2 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -36,6 +36,7 @@ ImageManager::ImageManager() need_update = true; pack_images = false; osl_texture_system = NULL; + animation_frame = 0; tex_num_images = TEX_NUM_IMAGES; tex_num_float_images = TEX_NUM_FLOAT_IMAGES; @@ -67,7 +68,24 @@ void ImageManager::set_extended_image_limits(void) tex_image_byte_start = TEX_EXTENDED_IMAGE_BYTE_START; } -static bool is_float_image(const string& filename) +bool ImageManager::set_animation_frame_update(int frame) +{ + if(frame != animation_frame) { + animation_frame = frame; + + for(size_t slot = 0; slot < images.size(); slot++) + if(images[slot] && images[slot]->animated) + return true; + + for(size_t slot = 0; slot < float_images.size(); slot++) + if(float_images[slot] && float_images[slot]->animated) + return true; + } + + return false; +} + +bool ImageManager::is_float_image(const string& filename) { ImageInput *in = ImageInput::create(filename); bool is_float = false; @@ -95,7 +113,7 @@ static bool is_float_image(const string& filename) return is_float; } -int ImageManager::add_image(const string& filename, bool& is_float) +int ImageManager::add_image(const string& filename, bool animated, bool& is_float) { Image *img; size_t slot; @@ -133,6 +151,7 @@ int ImageManager::add_image(const string& filename, bool& is_float) img = new Image(); img->filename = filename; img->need_load = true; + img->animated = animated; img->users = 1; float_images[slot] = img; @@ -166,6 +185,7 @@ int ImageManager::add_image(const string& filename, bool& is_float) img = new Image(); img->filename = filename; img->need_load = true; + img->animated = animated; img->users = 1; images[slot] = img; diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 485bfc5cbf5..4d177174971 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -51,16 +51,17 @@ public: ImageManager(); ~ImageManager(); - int add_image(const string& filename, bool& is_float); + int add_image(const string& filename, bool animated, bool& is_float); void remove_image(const string& filename); + bool is_float_image(const string& filename); void device_update(Device *device, DeviceScene *dscene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void set_osl_texture_system(void *texture_system); void set_pack_images(bool pack_images_); - void set_extended_image_limits(void); + bool set_animation_frame_update(int frame); bool need_update; @@ -69,11 +70,13 @@ private: int tex_num_float_images; int tex_image_byte_start; thread_mutex device_mutex; + int animation_frame; struct Image { string filename; bool need_load; + bool animated; int users; }; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index d77516a1b18..4173da453fd 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -147,6 +147,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Mesh *mesh = object->mesh; bool have_emission = false; + /* skip if we are not visible for BSDFs */ + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + continue; + /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; @@ -183,6 +187,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Mesh *mesh = object->mesh; bool have_emission = false; + /* skip if we are not visible for BSDFs */ + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + continue; + /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 14f23992664..bc782a78c60 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -325,6 +325,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorobject_name_map.clear(); og->attribute_map.clear(); + og->object_names.clear(); og->attribute_map.resize(scene->objects.size()); @@ -332,6 +333,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorobjects[i]; og->object_name_map[object->name] = i; + og->object_names.push_back(object->name); /* set object attributes */ foreach(ParamValue& attr, object->attributes) { @@ -545,7 +547,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, } /* create attribute lookup maps */ - if(scene->params.shadingsystem == SceneParams::OSL) + if(scene->shader_manager->use_osl()) update_osl_attributes(device, scene, mesh_attributes); else update_svm_attributes(device, dscene, scene, mesh_attributes); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index d7bf71337f6..3f8055b3540 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -100,6 +100,16 @@ void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_ou } } +void TextureMapping::compile(OSLCompiler &compiler) +{ + if(!skip()) { + Transform tfm = transform_transpose(compute_transform()); + + compiler.parameter("mapping", tfm); + compiler.parameter("use_mapping", 1); + } +} + /* Image Texture */ static ShaderEnum color_space_init() @@ -130,11 +140,12 @@ ImageTextureNode::ImageTextureNode() { image_manager = NULL; slot = -1; - is_float = false; + is_float = -1; filename = ""; color_space = ustring("Color"); projection = ustring("Flat");; projection_blend = 0.0f; + animated = false; add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV); add_output("Color", SHADER_SOCKET_COLOR); @@ -152,7 +163,7 @@ ShaderNode *ImageTextureNode::clone() const ImageTextureNode *node = new ImageTextureNode(*this); node->image_manager = NULL; node->slot = -1; - node->is_float = false; + node->is_float = -1; return node; } @@ -163,8 +174,11 @@ void ImageTextureNode::compile(SVMCompiler& compiler) ShaderOutput *alpha_out = output("Alpha"); image_manager = compiler.image_manager; - if(slot == -1) - slot = image_manager->add_image(filename, is_float); + if(is_float == -1) { + bool is_float_bool; + slot = image_manager->add_image(filename, animated, is_float_bool); + is_float = (int)is_float_bool; + } if(!color_out->links.empty()) compiler.stack_assign(color_out); @@ -220,6 +234,11 @@ void ImageTextureNode::compile(SVMCompiler& compiler) void ImageTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + + if(is_float == -1) + is_float = (int)image_manager->is_float_image(filename); + compiler.parameter("filename", filename.c_str()); if(is_float || color_space != "Color") compiler.parameter("color_space", "Linear"); @@ -250,10 +269,11 @@ EnvironmentTextureNode::EnvironmentTextureNode() { image_manager = NULL; slot = -1; - is_float = false; + is_float = -1; filename = ""; color_space = ustring("Color"); projection = ustring("Equirectangular"); + animated = false; add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION); add_output("Color", SHADER_SOCKET_COLOR); @@ -271,7 +291,7 @@ ShaderNode *EnvironmentTextureNode::clone() const EnvironmentTextureNode *node = new EnvironmentTextureNode(*this); node->image_manager = NULL; node->slot = -1; - node->is_float = false; + node->is_float = -1; return node; } @@ -282,8 +302,11 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) ShaderOutput *alpha_out = output("Alpha"); image_manager = compiler.image_manager; - if(slot == -1) - slot = image_manager->add_image(filename, is_float); + if(slot == -1) { + bool is_float_bool; + slot = image_manager->add_image(filename, animated, is_float_bool); + is_float = (int)is_float_bool; + } if(!color_out->links.empty()) compiler.stack_assign(color_out); @@ -328,7 +351,13 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) void EnvironmentTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + + if(is_float == -1) + is_float = (int)image_manager->is_float_image(filename); + compiler.parameter("filename", filename.c_str()); + compiler.parameter("projection", projection); if(is_float || color_space != "Color") compiler.parameter("color_space", "Linear"); else @@ -438,6 +467,8 @@ void SkyTextureNode::compile(SVMCompiler& compiler) void SkyTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter_vector("sun_direction", sun_direction); compiler.parameter("turbidity", turbidity); compiler.add(this, "node_sky_texture"); @@ -501,6 +532,8 @@ void GradientTextureNode::compile(SVMCompiler& compiler) void GradientTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_gradient_texture"); } @@ -559,6 +592,8 @@ void NoiseTextureNode::compile(SVMCompiler& compiler) void NoiseTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.add(this, "node_noise_texture"); } @@ -619,6 +654,8 @@ void VoronoiTextureNode::compile(SVMCompiler& compiler) void VoronoiTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Coloring", coloring); compiler.add(this, "node_voronoi_texture"); } @@ -706,6 +743,8 @@ void MusgraveTextureNode::compile(SVMCompiler& compiler) void MusgraveTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_musgrave_texture"); @@ -784,6 +823,8 @@ void WaveTextureNode::compile(SVMCompiler& compiler) void WaveTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_wave_texture"); @@ -841,6 +882,8 @@ void MagicTextureNode::compile(SVMCompiler& compiler) void MagicTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Depth", depth); compiler.add(this, "node_magic_texture"); } @@ -897,6 +940,8 @@ void CheckerTextureNode::compile(SVMCompiler& compiler) void CheckerTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.add(this, "node_checker_texture"); } @@ -985,6 +1030,8 @@ void BrickTextureNode::compile(SVMCompiler& compiler) void BrickTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Offset", offset); compiler.parameter("OffsetFrequency", offset_frequency); compiler.parameter("Squash", squash); @@ -1051,6 +1098,9 @@ void MappingNode::compile(OSLCompiler& compiler) { Transform tfm = transform_transpose(tex_mapping.compute_transform()); compiler.parameter("Matrix", tfm); + compiler.parameter_point("mapping_min", tex_mapping.min); + compiler.parameter_point("mapping_max", tex_mapping.max); + compiler.parameter("use_minmax", tex_mapping.use_minmax); compiler.add(this, "node_mapping"); } @@ -1077,6 +1127,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_) add_input("Point", SHADER_SOCKET_POINT); else if(from == SHADER_SOCKET_NORMAL) add_input("Normal", SHADER_SOCKET_NORMAL); + else if(from == SHADER_SOCKET_STRING) + add_input("String", SHADER_SOCKET_STRING); else assert(0); @@ -1092,6 +1144,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_) add_output("Point", SHADER_SOCKET_POINT); else if(to == SHADER_SOCKET_NORMAL) add_output("Normal", SHADER_SOCKET_NORMAL); + else if(to == SHADER_SOCKET_STRING) + add_output("String", SHADER_SOCKET_STRING); else assert(0); } @@ -1210,6 +1264,7 @@ BsdfNode::BsdfNode() add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL); + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); add_output("BSDF", SHADER_SOCKET_CLOSURE); } @@ -1284,10 +1339,8 @@ void WardBsdfNode::attributes(AttributeRequestSet *attributes) { ShaderInput *tangent_in = input("Tangent"); - if(!tangent_in->link) { - attributes->add(ATTR_STD_TANGENT); + if(!tangent_in->link) attributes->add(ATTR_STD_GENERATED); - } ShaderNode::attributes(attributes); } @@ -1346,9 +1399,9 @@ static ShaderEnum glass_distribution_init() { ShaderEnum enm; - enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID); - enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); - enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); + enm.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID); + enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID); + enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); return enm; } @@ -1367,7 +1420,7 @@ void GlassBsdfNode::compile(SVMCompiler& compiler) { closure = (ClosureType)distribution_enum[distribution]; - if(closure == CLOSURE_BSDF_REFRACTION_ID) + if(closure == CLOSURE_BSDF_SHARP_GLASS_ID) BsdfNode::compile(compiler, NULL, input("IOR")); else BsdfNode::compile(compiler, input("Roughness"), input("IOR")); @@ -1379,6 +1432,45 @@ void GlassBsdfNode::compile(OSLCompiler& compiler) compiler.add(this, "node_glass_bsdf"); } +/* Refraction BSDF Closure */ + +static ShaderEnum refraction_distribution_init() +{ + ShaderEnum enm; + + enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID); + enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); + enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); + + return enm; +} + +ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init(); + +RefractionBsdfNode::RefractionBsdfNode() +{ + distribution = ustring("Sharp"); + + add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f); + add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f); +} + +void RefractionBsdfNode::compile(SVMCompiler& compiler) +{ + closure = (ClosureType)distribution_enum[distribution]; + + if(closure == CLOSURE_BSDF_REFRACTION_ID) + BsdfNode::compile(compiler, NULL, input("IOR")); + else + BsdfNode::compile(compiler, input("Roughness"), input("IOR")); +} + +void RefractionBsdfNode::compile(OSLCompiler& compiler) +{ + compiler.parameter("distribution", distribution); + compiler.add(this, "node_refraction_bsdf"); +} + /* Velvet BSDF Closure */ VelvetBsdfNode::VelvetBsdfNode() @@ -1460,6 +1552,8 @@ EmissionNode::EmissionNode() add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f); + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + add_output("Emission", SHADER_SOCKET_CLOSURE); } @@ -1494,6 +1588,8 @@ BackgroundNode::BackgroundNode() { add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f); + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + add_output("Background", SHADER_SOCKET_CLOSURE); } @@ -1523,11 +1619,17 @@ void BackgroundNode::compile(OSLCompiler& compiler) HoldoutNode::HoldoutNode() : ShaderNode("holdout") { + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + add_output("Holdout", SHADER_SOCKET_CLOSURE); } void HoldoutNode::compile(SVMCompiler& compiler) { + float3 value = make_float3(1.0f, 1.0f, 1.0f); + + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, value); compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset()); } @@ -1536,6 +1638,37 @@ void HoldoutNode::compile(OSLCompiler& compiler) compiler.add(this, "node_holdout"); } +/* Ambient Occlusion */ + +AmbientOcclusionNode::AmbientOcclusionNode() +: ShaderNode("ambient_occlusion") +{ + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); + add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + + add_output("AO", SHADER_SOCKET_CLOSURE); +} + +void AmbientOcclusionNode::compile(SVMCompiler& compiler) +{ + ShaderInput *color_in = input("Color"); + + if(color_in->link) { + compiler.stack_assign(color_in); + compiler.add_node(NODE_CLOSURE_WEIGHT, color_in->stack_offset); + } + else + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value); + + compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset()); +} + +void AmbientOcclusionNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_ambient_occlusion"); +} + /* Volume Closure */ VolumeNode::VolumeNode() @@ -1545,6 +1678,7 @@ VolumeNode::VolumeNode() add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Density", SHADER_SOCKET_FLOAT, 1.0f); + add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); add_output("Volume", SHADER_SOCKET_CLOSURE); } @@ -1623,7 +1757,7 @@ void IsotropicVolumeNode::compile(OSLCompiler& compiler) GeometryNode::GeometryNode() : ShaderNode("geometry") { - add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_output("Position", SHADER_SOCKET_POINT); add_output("Normal", SHADER_SOCKET_NORMAL); add_output("Tangent", SHADER_SOCKET_NORMAL); @@ -1635,10 +1769,8 @@ GeometryNode::GeometryNode() void GeometryNode::attributes(AttributeRequestSet *attributes) { - if(!output("Tangent")->links.empty()) { - attributes->add(ATTR_STD_TANGENT); + if(!output("Tangent")->links.empty()) attributes->add(ATTR_STD_GENERATED); - } ShaderNode::attributes(attributes); } @@ -1713,7 +1845,7 @@ void GeometryNode::compile(OSLCompiler& compiler) TextureCoordinateNode::TextureCoordinateNode() : ShaderNode("texture_coordinate") { - add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_output("Generated", SHADER_SOCKET_POINT); add_output("Normal", SHADER_SOCKET_NORMAL); add_output("UV", SHADER_SOCKET_POINT); @@ -2075,13 +2207,14 @@ void ParticleInfoNode::compile(SVMCompiler& compiler) compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, out->stack_offset); } - #if 0 /* XXX Quaternion data is not yet supported by Cycles */ + /* quaternion data is not yet supported by Cycles */ +#if 0 out = output("Rotation"); if(!out->links.empty()) { compiler.stack_assign(out); compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, out->stack_offset); } - #endif +#endif out = output("Size"); if(!out->links.empty()) { @@ -2202,6 +2335,39 @@ void MixClosureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_mix_closure"); } +/* Mix Closure */ + +MixClosureWeightNode::MixClosureWeightNode() +: ShaderNode("mix_closure_weight") +{ + add_input("Weight", SHADER_SOCKET_FLOAT, 1.0f); + add_input("Fac", SHADER_SOCKET_FLOAT, 1.0f); + add_output("Weight1", SHADER_SOCKET_FLOAT); + add_output("Weight2", SHADER_SOCKET_FLOAT); +} + +void MixClosureWeightNode::compile(SVMCompiler& compiler) +{ + ShaderInput *weight_in = input("Weight"); + ShaderInput *fac_in = input("Fac"); + ShaderOutput *weight1_out = output("Weight1"); + ShaderOutput *weight2_out = output("Weight2"); + + compiler.stack_assign(weight_in); + compiler.stack_assign(fac_in); + compiler.stack_assign(weight1_out); + compiler.stack_assign(weight2_out); + + compiler.add_node(NODE_MIX_CLOSURE, + compiler.encode_uchar4(fac_in->stack_offset, weight_in->stack_offset, + weight1_out->stack_offset, weight2_out->stack_offset)); +} + +void MixClosureWeightNode::compile(OSLCompiler& compiler) +{ + assert(0); +} + /* Invert */ InvertNode::InvertNode() @@ -2567,7 +2733,7 @@ void CameraNode::compile(OSLCompiler& compiler) FresnelNode::FresnelNode() : ShaderNode("Fresnel") { - add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f); add_output("Fac", SHADER_SOCKET_FLOAT); } @@ -2592,7 +2758,7 @@ void FresnelNode::compile(OSLCompiler& compiler) LayerWeightNode::LayerWeightNode() : ShaderNode("LayerWeight") { - add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_input("Blend", SHADER_SOCKET_FLOAT, 0.5f); add_output("Fresnel", SHADER_SOCKET_FLOAT); @@ -2946,5 +3112,186 @@ void OSLScriptNode::compile(OSLCompiler& compiler) compiler.add(this, bytecode_hash.c_str(), false); } +/* Normal Map */ + +static ShaderEnum normal_map_space_init() +{ + ShaderEnum enm; + + enm.insert("Tangent", NODE_NORMAL_MAP_TANGENT); + enm.insert("Object", NODE_NORMAL_MAP_OBJECT); + enm.insert("World", NODE_NORMAL_MAP_WORLD); + + return enm; +} + +ShaderEnum NormalMapNode::space_enum = normal_map_space_init(); + +NormalMapNode::NormalMapNode() +: ShaderNode("normal_map") +{ + space = ustring("Tangent"); + attribute = ustring(""); + + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); + add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f); + add_input("Color", SHADER_SOCKET_COLOR); + + add_output("Normal", SHADER_SOCKET_NORMAL); +} + +void NormalMapNode::attributes(AttributeRequestSet *attributes) +{ + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + attributes->add(ATTR_STD_UV_TANGENT); + attributes->add(ATTR_STD_UV_TANGENT_SIGN); + } + else { + attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); + attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + ShaderNode::attributes(attributes); +} + +void NormalMapNode::compile(SVMCompiler& compiler) +{ + ShaderInput *color_in = input("Color"); + ShaderInput *strength_in = input("Strength"); + ShaderOutput *normal_out = output("Normal"); + int attr = 0, attr_sign = 0; + + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + attr = compiler.attribute(ATTR_STD_UV_TANGENT); + attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN); + } + else { + attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str())); + attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + compiler.stack_assign(color_in); + compiler.stack_assign(strength_in); + compiler.stack_assign(normal_out); + + compiler.add_node(NODE_NORMAL_MAP, + compiler.encode_uchar4( + color_in->stack_offset, + strength_in->stack_offset, + normal_out->stack_offset, + space_enum[space]), + attr, attr_sign); +} + +void NormalMapNode::compile(OSLCompiler& compiler) +{ + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + compiler.parameter("attr_name", ustring("geom:tangent")); + compiler.parameter("attr_sign_name", ustring("geom:tangent_sign")); + } + else { + compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str())); + compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + compiler.parameter("space", space); + + compiler.add(this, "node_normal_map"); +} + +/* Tangent */ + +static ShaderEnum tangent_direction_type_init() +{ + ShaderEnum enm; + + enm.insert("Radial", NODE_TANGENT_RADIAL); + enm.insert("UV Map", NODE_TANGENT_UVMAP); + + return enm; +} + +static ShaderEnum tangent_axis_init() +{ + ShaderEnum enm; + + enm.insert("X", NODE_TANGENT_AXIS_X); + enm.insert("Y", NODE_TANGENT_AXIS_Y); + enm.insert("Z", NODE_TANGENT_AXIS_Z); + + return enm; +} + +ShaderEnum TangentNode::direction_type_enum = tangent_direction_type_init(); +ShaderEnum TangentNode::axis_enum = tangent_axis_init(); + +TangentNode::TangentNode() +: ShaderNode("normal_map") +{ + direction_type = ustring("Radial"); + axis = ustring("X"); + attribute = ustring(""); + + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); + add_output("Tangent", SHADER_SOCKET_NORMAL); +} + +void TangentNode::attributes(AttributeRequestSet *attributes) +{ + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + attributes->add(ATTR_STD_UV_TANGENT); + else + attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + else + attributes->add(ATTR_STD_GENERATED); + + ShaderNode::attributes(attributes); +} + +void TangentNode::compile(SVMCompiler& compiler) +{ + ShaderOutput *tangent_out = output("Tangent"); + int attr; + + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + attr = compiler.attribute(ATTR_STD_UV_TANGENT); + else + attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + else + attr = compiler.attribute(ATTR_STD_GENERATED); + + compiler.stack_assign(tangent_out); + + compiler.add_node(NODE_TANGENT, + compiler.encode_uchar4( + tangent_out->stack_offset, + direction_type_enum[direction_type], + axis_enum[axis]), attr); +} + +void TangentNode::compile(OSLCompiler& compiler) +{ + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + compiler.parameter("attr_name", ustring("geom:tangent")); + else + compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + + compiler.parameter("direction_type", direction_type); + compiler.parameter("axis", axis); + compiler.add(this, "node_tangent"); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index d90cae5f668..67733142dd1 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -36,6 +36,7 @@ public: Transform compute_transform(); bool skip(); void compile(SVMCompiler& compiler, int offset_in, int offset_out); + void compile(OSLCompiler &compiler); float3 translation; float3 rotation; @@ -67,11 +68,12 @@ public: ImageManager *image_manager; int slot; - bool is_float; + int is_float; string filename; ustring color_space; ustring projection; float projection_blend; + bool animated; static ShaderEnum color_space_enum; static ShaderEnum projection_enum; @@ -85,10 +87,11 @@ public: ImageManager *image_manager; int slot; - bool is_float; + int is_float; string filename; ustring color_space; ustring projection; + bool animated; static ShaderEnum color_space_enum; static ShaderEnum projection_enum; @@ -240,6 +243,14 @@ public: static ShaderEnum distribution_enum; }; +class RefractionBsdfNode : public BsdfNode { +public: + SHADER_NODE_CLASS(RefractionBsdfNode) + + ustring distribution; + static ShaderEnum distribution_enum; +}; + class EmissionNode : public ShaderNode { public: SHADER_NODE_CLASS(EmissionNode) @@ -257,6 +268,11 @@ public: SHADER_NODE_CLASS(HoldoutNode) }; +class AmbientOcclusionNode : public ShaderNode { +public: + SHADER_NODE_CLASS(AmbientOcclusionNode) +}; + class VolumeNode : public ShaderNode { public: SHADER_NODE_CLASS(VolumeNode) @@ -335,6 +351,11 @@ public: SHADER_NODE_CLASS(MixClosureNode) }; +class MixClosureWeightNode : public ShaderNode { +public: + SHADER_NODE_CLASS(MixClosureWeightNode); +}; + class InvertNode : public ShaderNode { public: SHADER_NODE_CLASS(InvertNode) @@ -457,6 +478,31 @@ public: vector output_names; }; +class NormalMapNode : public ShaderNode { +public: + SHADER_NODE_CLASS(NormalMapNode) + void attributes(AttributeRequestSet *attributes); + + ustring space; + static ShaderEnum space_enum; + + ustring attribute; +}; + +class TangentNode : public ShaderNode { +public: + SHADER_NODE_CLASS(TangentNode) + void attributes(AttributeRequestSet *attributes); + + ustring direction_type; + static ShaderEnum direction_type_enum; + + ustring axis; + static ShaderEnum axis_enum; + + ustring attribute; +}; + CCL_NAMESPACE_END #endif /* __NODES_H__ */ diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 25b4d1f08cc..bd9f16d64ef 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -56,7 +56,7 @@ void Object::compute_bounds(bool motion_blur, float shuttertime) BoundBox mbounds = mesh->bounds; if(motion_blur && use_motion) { - MotionTransform decomp; + DecompMotionTransform decomp; transform_motion_decompose(&decomp, &motion, &tfm); bounds = BoundBox::empty; @@ -148,10 +148,9 @@ ObjectManager::~ObjectManager() { } -void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress) { float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size()); - uint *object_flag = dscene->object_flag.resize(scene->objects.size()); int i = 0; map surface_area_map; Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); @@ -222,29 +221,29 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene mtfm_post = mtfm_post * itfm; memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4); - memcpy(&objects[offset+16], &mtfm_post, sizeof(float4)*4); + memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4); } #ifdef __OBJECT_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { if(ob->use_motion) { /* decompose transformations for interpolation */ - MotionTransform decomp; + DecompMotionTransform decomp; transform_motion_decompose(&decomp, &ob->motion, &ob->tfm); - memcpy(&objects[offset+8], &decomp, sizeof(float4)*12); + memcpy(&objects[offset+8], &decomp, sizeof(float4)*8); flag |= SD_OBJECT_MOTION; have_motion = true; } else { float4 no_motion = make_float4(FLT_MAX); - memcpy(&objects[offset+8], &no_motion, sizeof(float4)*12); + memcpy(&objects[offset+8], &no_motion, sizeof(float4)*8); } } #endif /* dupli object coords */ - objects[offset+20] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f); - objects[offset+21] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f); + objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f); + objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f); /* object flag */ if(ob->use_holdout) @@ -257,7 +256,6 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene } device->tex_alloc("__objects", dscene->objects); - device->tex_alloc("__object_flag", dscene->object_flag); dscene->data.bvh.have_motion = have_motion; } @@ -272,9 +270,12 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc if(scene->objects.size() == 0) return; + /* object info flag */ + uint *object_flag = dscene->object_flag.resize(scene->objects.size()); + /* set object transform matrices, before applying static transforms */ progress.set_status("Updating Objects", "Copying Transformations to device"); - device_update_transforms(device, dscene, scene, progress); + device_update_transforms(device, dscene, scene, object_flag, progress); if(progress.get_cancel()) return; @@ -282,10 +283,11 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc /* todo: do before to support getting object level coords? */ if(scene->params.bvh_type == SceneParams::BVH_STATIC) { progress.set_status("Updating Objects", "Applying Static Transformations"); - apply_static_transforms(scene, progress); + apply_static_transforms(scene, object_flag, progress); } - if(progress.get_cancel()) return; + /* allocate object flag */ + device->tex_alloc("__object_flag", dscene->object_flag); need_update = false; } @@ -299,7 +301,7 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene) dscene->object_flag.clear(); } -void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) +void ObjectManager::apply_static_transforms(Scene *scene, uint *object_flag, Progress& progress) { /* todo: normals and displacement should be done before applying transform! */ /* todo: create objects/meshes in right order! */ @@ -312,6 +314,7 @@ void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) #else bool motion_blur = false; #endif + int i = 0; foreach(Object *object, scene->objects) { map::iterator it = mesh_users.find(object->mesh); @@ -334,8 +337,12 @@ void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) if(progress.get_cancel()) return; } + + object_flag[i] |= SD_TRANSFORM_APPLIED; } } + + i++; } } diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 922c886d961..9c9b11bc29c 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -73,12 +73,12 @@ public: ~ObjectManager(); void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); + void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); - void apply_static_transforms(Scene *scene, Progress& progress); + void apply_static_transforms(Scene *scene, uint *object_flag, Progress& progress); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index a8a40a4e596..e4ee40d881e 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -79,20 +79,19 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(shader->sample_as_light && shader->has_surface_emission) scene->light_manager->need_update = true; - OSLCompiler compiler((void*)this, (void*)ss); + OSLCompiler compiler((void*)this, (void*)ss, scene->image_manager); compiler.background = (shader == scene->shaders[scene->default_background]); compiler.compile(og, shader); } /* setup shader engine */ og->ss = ss; + og->ts = ts; og->services = services; int background_id = scene->shader_manager->get_shader_id(scene->default_background); og->background_state = og->surface_state[background_id & SHADER_MASK]; og->use = true; - tls_create(OSLGlobals::ThreadData, og->thread_data); - foreach(Shader *shader, scene->shaders) shader->need_update = false; @@ -113,8 +112,7 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) /* clear shader engine */ og->use = false; og->ss = NULL; - - tls_delete(OSLGlobals::ThreadData, og->thread_data); + og->ts = NULL; og->surface_state.clear(); og->volume_state.clear(); @@ -128,6 +126,7 @@ void OSLShaderManager::texture_system_init() ts = TextureSystem::create(true); ts->attribute("automip", 1); ts->attribute("autotile", 64); + ts->attribute("gray_to_rgb", 1); /* effectively unlimited for now, until we support proper mipmap lookups */ ts->attribute("max_memory_MB", 16384); @@ -159,7 +158,7 @@ void OSLShaderManager::shading_system_init() const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]); ss->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes); - OSLShader::register_closures(ss); + OSLShader::register_closures((OSLShadingSystem*)ss); loaded_shaders.clear(); } @@ -278,10 +277,11 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str /* Graph Compiler */ -OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_) +OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, ImageManager *image_manager_) { manager = manager_; shadingsys = shadingsys_; + image_manager = image_manager_; current_type = SHADER_TYPE_SURFACE; current_shader = NULL; background = false; @@ -325,7 +325,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output) while((i = sname.find(" ")) != string::npos) sname.replace(i, 1, ""); - /* if output exists with the same name, add "In" suffix */ + /* if input exists with the same name, add "Out" suffix */ foreach(ShaderInput *input, node->inputs) { if (strcmp(input->name, output->name)==0) { sname += "Out"; @@ -340,6 +340,9 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) { /* exception for output node, only one input is actually used * depending on the current shader type */ + + if(!(input->usage & ShaderInput::USE_OSL)) + return true; if(node->name == ustring("output")) { if(strcmp(input->name, "Surface") == 0 && current_type != SHADER_TYPE_SURFACE) @@ -403,6 +406,9 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) case SHADER_SOCKET_INT: parameter(param_name.c_str(), (int)input->value.x); break; + case SHADER_SOCKET_STRING: + parameter(param_name.c_str(), input->value_string); + break; case SHADER_SOCKET_CLOSURE: break; } diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index cee37c58d74..9b58745bd46 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -52,6 +52,8 @@ public: OSLShaderManager(); ~OSLShaderManager(); + bool use_osl() { return true; } + void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); @@ -81,7 +83,7 @@ protected: class OSLCompiler { public: - OSLCompiler(void *manager, void *shadingsys); + OSLCompiler(void *manager, void *shadingsys, ImageManager *image_manager); void compile(OSLGlobals *og, Shader *shader); void add(ShaderNode *node, const char *name, bool isfilepath = false); @@ -108,6 +110,7 @@ public: ShaderType output_type() { return current_type; } bool background; + ImageManager *image_manager; private: string id(ShaderNode *node); diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index 9f951d9673f..2a1570f7a0d 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -57,8 +57,7 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene { /* count particles. * adds one dummy particle at the beginning to avoid invalid lookups, - * in case a shader uses particle info without actual particle data. - */ + * in case a shader uses particle info without actual particle data. */ int num_particles = 1; foreach(ParticleSystem *psys, scene->particle_systems) num_particles += psys->particles.size(); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 15031b9500c..8085cfdd3e6 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -53,42 +53,25 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) object_manager = new ObjectManager(); integrator = new Integrator(); image_manager = new ImageManager(); - shader_manager = ShaderManager::create(this); particle_system_manager = new ParticleSystemManager(); + /* OSL only works on the CPU */ + if(device_info_.type == DEVICE_CPU) + shader_manager = ShaderManager::create(this, params.shadingsystem); + else + shader_manager = ShaderManager::create(this, SceneParams::SVM); + if (device_info_.type == DEVICE_CPU) image_manager->set_extended_image_limits(); } Scene::~Scene() { - if(device) camera->device_free(device, &dscene); - delete camera; - - if(device) filter->device_free(device, &dscene); - delete filter; - - if(device) film->device_free(device, &dscene); - delete film; - - if(device) background->device_free(device, &dscene); - delete background; - - if(device) mesh_manager->device_free(device, &dscene); - delete mesh_manager; - - if(device) object_manager->device_free(device, &dscene); - delete object_manager; - - if(device) integrator->device_free(device, &dscene); - delete integrator; - - if(device) shader_manager->device_free(device, &dscene); - delete shader_manager; - - if(device) light_manager->device_free(device, &dscene); - delete light_manager; + free_memory(true); +} +void Scene::free_memory(bool final) +{ foreach(Shader *s, shaders) delete s; foreach(Mesh *m, meshes) @@ -100,11 +83,44 @@ Scene::~Scene() foreach(ParticleSystem *p, particle_systems) delete p; - if(device) image_manager->device_free(device, &dscene); - delete image_manager; + if(device) { + camera->device_free(device, &dscene); + filter->device_free(device, &dscene); + film->device_free(device, &dscene); + background->device_free(device, &dscene); + integrator->device_free(device, &dscene); - if(device) particle_system_manager->device_free(device, &dscene); - delete particle_system_manager; + object_manager->device_free(device, &dscene); + mesh_manager->device_free(device, &dscene); + shader_manager->device_free(device, &dscene); + light_manager->device_free(device, &dscene); + + particle_system_manager->device_free(device, &dscene); + + if(!params.persistent_images || final) + image_manager->device_free(device, &dscene); + } + + if(final) { + delete filter; + delete camera; + delete film; + delete background; + delete integrator; + delete object_manager; + delete mesh_manager; + delete shader_manager; + delete light_manager; + delete particle_system_manager; + delete image_manager; + } + else { + shaders.clear(); + meshes.clear(); + objects.clear(); + lights.clear(); + particle_systems.clear(); + } } void Scene::device_update(Device *device_, Progress& progress) @@ -229,5 +245,22 @@ bool Scene::need_reset() || particle_system_manager->need_update); } +void Scene::reset() +{ + shader_manager->add_default(this); + + /* ensure all objects are updated */ + camera->tag_update(); + filter->tag_update(this); + film->tag_update(this); + background->tag_update(this); + integrator->tag_update(this); +} + +void Scene::device_free() +{ + free_memory(false); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index bd45c1c04e6..92ef692b4b9 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -120,6 +120,7 @@ public: bool use_bvh_cache; bool use_bvh_spatial_split; bool use_qbvh; + bool persistent_images; SceneParams() { @@ -139,7 +140,8 @@ public: && bvh_type == params.bvh_type && use_bvh_cache == params.use_bvh_cache && use_bvh_spatial_split == params.use_bvh_spatial_split - && use_qbvh == params.use_qbvh); } + && use_qbvh == params.use_qbvh + && persistent_images == params.persistent_images); } }; /* Scene */ @@ -198,6 +200,12 @@ public: bool need_update(); bool need_reset(); + + void reset(); + void device_free(); + +protected: + void free_memory(bool final); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 7303cb52ad8..1d1a3d54893 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -49,7 +49,7 @@ Session::Session(const SessionParams& params_) TaskScheduler::init(params.threads); - device = Device::create(params.device, stats, params.background, params.threads); + device = Device::create(params.device, stats, params.background); if(params.background) { buffers = NULL; @@ -637,6 +637,15 @@ void Session::reset(BufferParams& buffer_params, int samples) reset_gpu(buffer_params, samples); else reset_cpu(buffer_params, samples); + + if(params.progressive_refine) { + thread_scoped_lock buffers_lock(buffers_mutex); + + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + + tile_buffers.clear(); + } } void Session::set_samples(int samples) @@ -757,7 +766,7 @@ void Session::update_status_time(bool show_pause, bool show_done) if(preview_time == 0.0 && resolution == 1) preview_time = time_dt(); - double tile_time = (tile == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample); + double tile_time = (tile == 0 || sample == 0)? 0.0: (time_dt() - preview_time - paused_time) / sample; /* negative can happen when we pause a bit before rendering, can discard that */ if(preview_time < 0.0) preview_time = 0.0; @@ -818,7 +827,7 @@ bool Session::update_progressive_refine(bool cancel) double current_time = time_dt(); - if (current_time - last_update_time < 1.0f) { + if (current_time - last_update_time < 1.0) { /* if last sample was processed, we need to write buffers anyway */ if (!write) return false; @@ -842,4 +851,18 @@ bool Session::update_progressive_refine(bool cancel) return write; } +void Session::device_free() +{ + scene->device_free(); + + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + + tile_buffers.clear(); + + /* used from background render only, so no need to + * re-create render/display buffers here + */ +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 7bb0cd1ae01..cfc1502287d 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -130,6 +130,7 @@ public: void set_samples(int samples); void set_pause(bool pause); + void device_free(); protected: struct DelayedReset { thread_mutex mutex; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 17f7fbd43d6..b9b49bf2989 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -121,12 +121,12 @@ ShaderManager::~ShaderManager() { } -ShaderManager *ShaderManager::create(Scene *scene) +ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem) { ShaderManager *manager; #ifdef WITH_OSL - if(scene->params.shadingsystem == SceneParams::OSL) + if(shadingsystem == SceneParams::OSL) manager = new OSLShaderManager(); else #endif diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 373b3356f51..d4421002ceb 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -107,9 +107,11 @@ class ShaderManager { public: bool need_update; - static ShaderManager *create(Scene *scene); + static ShaderManager *create(Scene *scene, int shadingsystem); virtual ~ShaderManager(); + virtual bool use_osl() { return false; } + /* device update */ virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0; virtual void device_free(Device *device, DeviceScene *dscene) = 0; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index dc249984499..4acd174e60f 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -487,56 +487,28 @@ void SVMCompiler::generate_closure(ShaderNode *node, set& done) } } -void SVMCompiler::generate_multi_closure(ShaderNode *node, set& done, uint in_offset) +void SVMCompiler::generate_multi_closure(ShaderNode *node, set& done, set& closure_done) { /* todo: the weaks point here is that unlike the single closure sampling * we will evaluate all nodes even if they are used as input for closures * that are unused. it's not clear what would be the best way to skip such * nodes at runtime, especially if they are tangled up */ + + /* only generate once */ + if(closure_done.find(node) != closure_done.end()) + return; + + closure_done.insert(node); if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { - ShaderInput *fin = node->input("Fac"); + /* weighting is already taken care of in ShaderGraph::transform_multi_closure */ ShaderInput *cl1in = node->input("Closure1"); ShaderInput *cl2in = node->input("Closure2"); - uint out1_offset = SVM_STACK_INVALID; - uint out2_offset = SVM_STACK_INVALID; - - if(fin) { - /* mix closure */ - set dependencies; - find_dependencies(dependencies, done, fin); - generate_svm_nodes(dependencies, done); - - stack_assign(fin); - - if(cl1in->link) - out1_offset = stack_find_offset(SHADER_SOCKET_FLOAT); - if(cl2in->link) - out2_offset = stack_find_offset(SHADER_SOCKET_FLOAT); - - add_node(NODE_MIX_CLOSURE, - encode_uchar4(fin->stack_offset, in_offset, out1_offset, out2_offset)); - } - else { - /* add closure */ - out1_offset = in_offset; - out2_offset = in_offset; - } - - if(cl1in->link) { - generate_multi_closure(cl1in->link->parent, done, out1_offset); - - if(fin) - stack_clear_offset(SHADER_SOCKET_FLOAT, out1_offset); - } - - if(cl2in->link) { - generate_multi_closure(cl2in->link->parent, done, out2_offset); - - if(fin) - stack_clear_offset(SHADER_SOCKET_FLOAT, out2_offset); - } + if(cl1in->link) + generate_multi_closure(cl1in->link->parent, done, closure_done); + if(cl2in->link) + generate_multi_closure(cl2in->link->parent, done, closure_done); } else { /* execute dependencies for closure */ @@ -548,7 +520,16 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set& don } } - mix_weight_offset = in_offset; + /* closure mix weight */ + const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight"; + ShaderInput *weight_in = node->input(weight_name); + + if(weight_in && (weight_in->link || weight_in->value.x != 1.0f)) { + stack_assign(weight_in); + mix_weight_offset = weight_in->stack_offset; + } + else + mix_weight_offset = SVM_STACK_INVALID; /* compile closure itself */ node->compile(*this); @@ -561,9 +542,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set& don current_shader->has_surface_emission = true; if(node->name == ustring("transparent")) current_shader->has_surface_transparent = true; - - /* end node is added outside of this */ } + + done.insert(node); } @@ -634,8 +615,10 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty if(generate) { set done; - if(use_multi_closure) - generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); + if(use_multi_closure) { + set closure_done; + generate_multi_closure(clin->link->parent, done, closure_done); + } else generate_closure(clin->link->parent, done); } @@ -658,9 +641,9 @@ void SVMCompiler::compile(Shader *shader, vector& global_svm_nodes, int in shader->graph_bump = shader->graph->copy(); /* finalize */ - shader->graph->finalize(false, false); + shader->graph->finalize(false, false, use_multi_closure); if(shader->graph_bump) - shader->graph_bump->finalize(true, false); + shader->graph_bump->finalize(true, false, use_multi_closure); current_shader = shader; diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index 0db68f400fc..0b15c5aaa1e 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -81,6 +81,7 @@ public: bool background; protected: + /* stack */ struct Stack { Stack() { memset(users, 0, sizeof(users)); } Stack(const Stack& other) { memcpy(users, other.users, sizeof(users)); } @@ -123,11 +124,15 @@ protected: bool node_skip_input(ShaderNode *node, ShaderInput *input); + /* single closure */ void find_dependencies(set& dependencies, const set& done, ShaderInput *input); void generate_svm_nodes(const set& nodes, set& done); void generate_closure(ShaderNode *node, set& done); - void generate_multi_closure(ShaderNode *node, set& done, uint in_offset); + /* multi closure */ + void generate_multi_closure(ShaderNode *node, set& done, set& closure_done); + + /* compile */ void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); vector svm_nodes; diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index bf5f791a245..dce417704cc 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -54,6 +54,7 @@ set(SRC_HEADERS util_path.h util_progress.h util_set.h + util_stats.h util_string.h util_system.h util_task.h @@ -61,8 +62,8 @@ set(SRC_HEADERS util_time.h util_transform.h util_types.h - util_view.h util_vector.h + util_view.h util_xml.h ) diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp index 163a92902f3..057fb6213e9 100644 --- a/intern/cycles/util/util_attribute.cpp +++ b/intern/cycles/util/util_attribute.cpp @@ -30,8 +30,10 @@ const char *attribute_standard_name(AttributeStandard std) return "uv"; else if(std == ATTR_STD_GENERATED) return "generated"; - else if(std == ATTR_STD_TANGENT) + else if(std == ATTR_STD_UV_TANGENT) return "tangent"; + else if(std == ATTR_STD_UV_TANGENT_SIGN) + return "tangent_sign"; else if(std == ATTR_STD_POSITION_UNDEFORMED) return "undeformed"; else if(std == ATTR_STD_POSITION_UNDISPLACED) diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index b35c4c12bb8..6dd1c6c71e8 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -31,6 +31,8 @@ using namespace std; CCL_NAMESPACE_BEGIN +/* 3D BoundBox */ + class BoundBox { public: @@ -160,6 +162,85 @@ __forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b, const Bou return intersect(a, intersect(b, c)); } +/* 2D BoundBox */ + +class BoundBox2D { +public: + float left; + float right; + float bottom; + float top; + + BoundBox2D() + : left(0.0f), right(1.0f), bottom(0.0f), top(1.0f) + { + } + + bool operator==(const BoundBox2D& other) const + { + return (left == other.left && right == other.right && + bottom == other.bottom && top == other.top); + } + + float width() + { + return right - left; + } + + float height() + { + return top - bottom; + } + + BoundBox2D operator*(float f) const + { + BoundBox2D result; + + result.left = left*f; + result.right = right*f; + result.bottom = bottom*f; + result.top = top*f; + + return result; + } + + BoundBox2D subset(const BoundBox2D& other) const + { + BoundBox2D subset; + + subset.left = left + other.left*(right - left); + subset.right = left + other.right*(right - left); + subset.bottom = bottom + other.bottom*(top - bottom); + subset.top = bottom + other.top*(top - bottom); + + return subset; + } + + BoundBox2D make_relative_to(const BoundBox2D& other) const + { + BoundBox2D result; + + result.left = ((left - other.left) / (other.right - other.left)); + result.right = ((right - other.left) / (other.right - other.left)); + result.bottom = ((bottom - other.bottom) / (other.top - other.bottom)); + result.top = ((top - other.bottom) / (other.top - other.bottom)); + + return result; + } + + BoundBox2D clamp(float mn = 0.0f, float mx = 1.0f) + { + BoundBox2D result; + + result.left = ccl::clamp(left, mn, mx); + result.right = ccl::clamp(right, mn, mx); + result.bottom = ccl::clamp(bottom, mn, mx); + result.top = ccl::clamp(top, mn, mx); + + return result; + } +}; + CCL_NAMESPACE_END #endif /* __UTIL_BOUNDBOX_H__ */ diff --git a/intern/cycles/util/util_opencl.cpp b/intern/cycles/util/util_opencl.cpp index 40b637f5cb7..c146c14b10c 100644 --- a/intern/cycles/util/util_opencl.cpp +++ b/intern/cycles/util/util_opencl.cpp @@ -140,6 +140,10 @@ int clLibraryInit() #endif int error = 0; + // OpenCL disabled for now, only works with this environment variable set + if(!getenv("CYCLES_OPENCL_TEST")) + return 0; + // Check if already initialized if (module != NULL) { diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index c97379d8776..03e25d4d132 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -68,6 +68,21 @@ public: return *this; } + void reset() + { + tile = 0; + sample = 0; + start_time = time_dt(); + total_time = 0.0f; + tile_time = 0.0f; + status = "Initializing"; + substatus = ""; + sync_status = ""; + sync_substatus = ""; + cancel = false; + cancel_message = ""; + } + /* cancel */ void set_cancel(const string& cancel_message_) { diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h index 405c81a1e1f..27638015f40 100644 --- a/intern/cycles/util/util_stats.h +++ b/intern/cycles/util/util_stats.h @@ -19,31 +19,22 @@ #ifndef __UTIL_STATS_H__ #define __UTIL_STATS_H__ -#include "util_thread.h" - CCL_NAMESPACE_BEGIN class Stats { public: - Stats() : lock(), mem_used(0), mem_peak(0) {} + Stats() : mem_used(0), mem_peak(0) {} void mem_alloc(size_t size) { - lock.lock(); - mem_used += size; if(mem_used > mem_peak) mem_peak = mem_used; - - lock.unlock(); } void mem_free(size_t size) { - lock.lock(); mem_used -= size; - lock.unlock(); } - spin_lock lock; size_t mem_used; size_t mem_peak; }; diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index ea0abd6f54f..8c4ec312256 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -168,10 +168,16 @@ void TaskScheduler::init(int num_threads) if(users == 0) { do_exit = false; - /* launch threads that will be waiting for work */ - if(num_threads == 0) + if(num_threads == 0) { + /* automatic number of threads will be main thread + num cores */ num_threads = system_cpu_thread_count(); + } + else { + /* main thread will also work, for fixed threads we count it too */ + num_threads -= 1; + } + /* launch threads that will be waiting for work */ threads.resize(num_threads); thread_level.resize(num_threads); diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index a2f284479c7..b795ca7524b 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -94,7 +94,10 @@ public: static void init(int num_threads = 0); static void exit(); - static int num_threads() { return threads.size(); } + /* number of threads that can work on tasks, main thread counts too */ + static int num_threads() { return threads.size() + 1; } + + /* test if any session is using the scheduler */ static bool active() { return users != 0; } protected: diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index 6d1bd0023a7..d7e9ec03df3 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -33,9 +33,6 @@ typedef boost::mutex thread_mutex; typedef boost::mutex::scoped_lock thread_scoped_lock; typedef boost::condition_variable thread_condition_variable; -/* use boost for spinlocks as well */ -typedef boost::detail::spinlock spin_lock; - /* own pthread based implementation, to avoid boost version conflicts with * dynamically loaded blender plugins */ @@ -73,41 +70,6 @@ protected: bool joined; }; -/* Thread Local Storage - * - * Boost implementation is a bit slow, and Mac OS X __thread is not supported - * but the pthreads implementation is optimized, so we use these macros. */ - -#ifdef __APPLE__ - -#define tls_ptr(type, name) \ - pthread_key_t name -#define tls_set(name, value) \ - pthread_setspecific(name, value) -#define tls_get(type, name) \ - ((type*)pthread_getspecific(name)) -#define tls_create(type, name) \ - pthread_key_create(&name, NULL) -#define tls_delete(type, name) \ - pthread_key_delete(name); - -#else - -#ifdef __WIN32 -#define __thread __declspec(thread) -#endif - -#define tls_ptr(type, name) \ - __thread type *name -#define tls_set(name, value) \ - name = value -#define tls_get(type, name) \ - name -#define tls_create(type, name) -#define tls_delete(type, name) - -#endif - CCL_NAMESPACE_END #endif /* __UTIL_THREAD_H__ */ diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 70ee13d96d7..ca19146e125 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -246,11 +246,30 @@ static void transform_decompose(Transform *decomp, const Transform *tfm) decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid) +void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid) { - transform_decompose(&decomp->pre, &motion->pre); + Transform pre, post; + + transform_decompose(&pre, &motion->pre); transform_decompose(&decomp->mid, mid); - transform_decompose(&decomp->post, &motion->post); + transform_decompose(&post, &motion->post); + + /* ensure rotation around shortest angle, negated quaternions are the same + * but this means we don't have to do the check in quat_interpolate */ + if(dot(decomp->mid.x, post.x) < 0.0f) + decomp->mid.x = -decomp->mid.x; + if(dot(pre.x, decomp->mid.x) < 0.0f) + pre.x = -pre.x; + + /* drop scale of pre/post */ + pre.y.w = decomp->mid.y.w; + post.y.w = decomp->mid.y.w; + + /* store translation/rotation part of pre/post */ + decomp->pre_x = pre.x; + decomp->pre_y = pre.y; + decomp->post_x = post.x; + decomp->post_y = post.y; } CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index df525542207..a1c12ddf0e1 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -39,15 +39,23 @@ typedef struct Transform { #endif } Transform; +/* transform decomposed in rotation/translation/scale. we use the same data + * structure as Transform, and tightly pack decomposition into it. first the + * rotation (4), then translation (3), then 3x3 scale matrix (9). + * + * For the DecompMotionTransform we drop scale from pre/post. */ + typedef struct MotionTransform { Transform pre; Transform mid; Transform post; } MotionTransform; -/* transform decomposed in rotation/translation/scale. we use the same data - * structure as Transform, and tightly pack decomposition into it. first the - * rotation (4), then translation (3), then 3x3 scale matrix (9) */ +typedef struct DecompMotionTransform { + Transform mid; + float4 pre_x, pre_y; + float4 post_x, post_y; +} DecompMotionTransform; /* Functions */ @@ -303,13 +311,15 @@ __device_inline Transform transform_clear_scale(const Transform& tfm) __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) { + /* use simpe nlerp instead of slerp. it's faster and almost the same */ + return normalize((1.0f - t)*q1 + t*q2); + +#if 0 + /* note: this does not ensure rotation around shortest angle, q1 and q2 + * are assumed to be matched already in transform_motion_decompose */ float costheta = dot(q1, q2); - /* rotate around shortest angle */ - if(costheta < 0.0f) { - costheta = -costheta; - q1 = -q1; - } + /* possible optimization: it might be possible to precompute theta/qperp */ if(costheta > 0.9995f) { /* linear interpolation in degenerate case */ @@ -318,14 +328,18 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) else { /* slerp */ float theta = acosf(clamp(costheta, -1.0f, 1.0f)); - float thetap = theta * t; float4 qperp = normalize(q2 - q1 * costheta); + float thetap = theta * t; return q1 * cosf(thetap) + qperp * sinf(thetap); } +#endif } __device_inline Transform transform_quick_inverse(Transform M) { + /* possible optimization: can we avoid doing this altogether and construct + * the inverse matrix directly from negated translation, transposed rotation, + * scale can be inverted but what about shearing? */ Transform R; float det = M.x.x*(M.z.z*M.y.y - M.z.y*M.y.z) - M.y.x*(M.z.z*M.x.y - M.z.y*M.x.z) + M.z.x*(M.y.z*M.x.y - M.y.y*M.x.z); @@ -380,14 +394,21 @@ __device_inline void transform_compose(Transform *tfm, const Transform *decomp) tfm->w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); } -__device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t) +/* Disabled for now, need arc-length parametrization for constant speed motion. + * #define CURVED_MOTION_INTERPOLATE */ + +__device void transform_motion_interpolate(Transform *tfm, const DecompMotionTransform *motion, float t) { + /* possible optimization: is it worth it adding a check to skip scaling? + * it's probably quite uncommon to have scaling objects. or can we skip + * just shearing perhaps? */ Transform decomp; +#ifdef CURVED_MOTION_INTERPOLATE /* 3 point bezier curve interpolation for position */ - float3 Ppre = float4_to_float3(motion->pre.y); + float3 Ppre = float4_to_float3(motion->pre_y); float3 Pmid = float4_to_float3(motion->mid.y); - float3 Ppost = float4_to_float3(motion->post.y); + float3 Ppost = float4_to_float3(motion->post_y); float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost); float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t); @@ -395,25 +416,33 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform decomp.y.x = P.x; decomp.y.y = P.y; decomp.y.z = P.z; +#endif /* linear interpolation for rotation and scale */ if(t < 0.5f) { t *= 2.0f; - decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t); - decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w; - decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z; - decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w; + decomp.x = quat_interpolate(motion->pre_x, motion->mid.x, t); +#ifdef CURVED_MOTION_INTERPOLATE + decomp.y.w = (1.0f - t)*motion->pre_y.w + t*motion->mid.y.w; +#else + decomp.y = (1.0f - t)*motion->pre_y + t*motion->mid.y; +#endif } else { t = (t - 0.5f)*2.0f; - decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t); - decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w; - decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z; - decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w; + decomp.x = quat_interpolate(motion->mid.x, motion->post_x, t); +#ifdef CURVED_MOTION_INTERPOLATE + decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post_y.w; +#else + decomp.y = (1.0f - t)*motion->mid.y + t*motion->post_y; +#endif } + decomp.z = motion->mid.z; + decomp.w = motion->mid.w; + /* compose rotation, translation, scale into matrix */ transform_compose(tfm, &decomp); } @@ -425,7 +454,7 @@ __device_inline bool operator==(const MotionTransform& A, const MotionTransform& return (A.pre == B.pre && A.post == B.post); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid); +void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid); #endif diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index f2c02cadcbf..3d246104ddc 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -41,7 +41,9 @@ #define __align(...) __declspec(align(__VA_ARGS__)) #else #define __device_inline static inline __attribute__((always_inline)) +#ifndef FREE_WINDOWS64 #define __forceinline inline __attribute__((always_inline)) +#endif #define __align(...) __attribute__((aligned(__VA_ARGS__))) #endif @@ -449,7 +451,8 @@ typedef enum AttributeStandard { ATTR_STD_VERTEX_NORMAL, ATTR_STD_FACE_NORMAL, ATTR_STD_UV, - ATTR_STD_TANGENT, + ATTR_STD_UV_TANGENT, + ATTR_STD_UV_TANGENT_SIGN, ATTR_STD_GENERATED, ATTR_STD_POSITION_UNDEFORMED, ATTR_STD_POSITION_UNDISPLACED, diff --git a/intern/elbeem/intern/ntl_geometryobject.cpp b/intern/elbeem/intern/ntl_geometryobject.cpp index 4f640253f0f..1e08cb96a95 100644 --- a/intern/elbeem/intern/ntl_geometryobject.cpp +++ b/intern/elbeem/intern/ntl_geometryobject.cpp @@ -787,7 +787,7 @@ ntlVec3Gfx ntlGeometryObject::getTranslation(double t) { } /*! get active flag time t*/ float ntlGeometryObject::getGeoActive(double t) { - float act = mcGeoActive.get(t); // if <= 0.0 -> off + float act = (mcGeoActive.get(t) >= 1.) ? 1.0 : 0.0; return act; } diff --git a/intern/elbeem/intern/ntl_world.cpp b/intern/elbeem/intern/ntl_world.cpp index 0b36f724985..dcc81dbe5cb 100644 --- a/intern/elbeem/intern/ntl_world.cpp +++ b/intern/elbeem/intern/ntl_world.cpp @@ -143,6 +143,7 @@ void ntlWorld::initDefaults() mFirstSim = 1; mSingleStepDebug = false; mFrameCnt = 0; + mSimFrameCnt = 0; mpOpenGLRenderer = NULL; /* create scene storage */ @@ -406,7 +407,6 @@ int ntlWorld::advanceSims(int framenum) } for(size_t i=0;isize();i++) { (*mpSims)[i]->setFrameNum(framenum); } - double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); // time stopped? nothing else to do... if( (*mpSims)[mFirstSim]->getFrameTime(framenum) <= 0.0 ){ @@ -416,6 +416,13 @@ int ntlWorld::advanceSims(int framenum) (*mpSims)[mFirstSim]->checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0); } + // Prevent bug [#29186] Object contribute to fluid sim animation start earlier than keyframe + // Was: double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); - DG + double totalTime = 0.0, targetTime = 0.0; + for(size_t i = 0; i < mSimFrameCnt; i++) + totalTime += (*mpSims)[mFirstSim]->getFrameTime(framenum); + targetTime = totalTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); + int gstate = 0; myTime_t advsstart = getTime(); @@ -461,6 +468,8 @@ int ntlWorld::advanceSims(int framenum) sim->prepareVisualization(); } + mSimFrameCnt++; + return 0; } diff --git a/intern/elbeem/intern/ntl_world.h b/intern/elbeem/intern/ntl_world.h index 3c5958477d4..c207904cf75 100644 --- a/intern/elbeem/intern/ntl_world.h +++ b/intern/elbeem/intern/ntl_world.h @@ -115,6 +115,9 @@ class ntlWorld /*! count no. of frame for viz render */ int mFrameCnt; + + /*! count no. of frame for correct sim time */ + int mSimFrameCnt; }; diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index e52ac0af2ed..ea09987c564 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -189,7 +189,6 @@ elseif(APPLE) if(WITH_INPUT_NDOF) list(APPEND SRC intern/GHOST_NDOFManagerCocoa.mm - intern/GHOST_NDOFManagerCocoa.h ) endif() diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 87ab3c013c6..f886dfd9d7d 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -120,7 +120,7 @@ extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle, /** * Removes a timer. * \param systemhandle The handle to the system - * \param timerTask Timer task to be removed. + * \param timertaskhandle Timer task to be removed. * \return Indication of success. */ extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle, @@ -185,7 +185,7 @@ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandl /** * Changes the window user data. * \param windowhandle The handle to the window - * \param data The window user data. + * \param userdata The window user data. */ extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata); @@ -212,6 +212,7 @@ extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, * Begins full screen mode. * \param systemhandle The handle to the system * \param setting The new setting of the display. + * \param stereoVisual Option for stereo display. * \return A handle to the window displayed in full screen. * This window is invalid after full screen has been ended. */ @@ -302,7 +303,7 @@ extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandl /** * Set the shape of the cursor. * \param windowhandle The handle to the window - * \param cursor The new cursor shape type id. + * \param cursorshape The new cursor shape type id. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle, @@ -484,10 +485,10 @@ extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timer /** * Changes the time user data. * \param timertaskhandle The handle to the timertask - * \param data The timer user data. + * \param userdata The timer user data. */ extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle, - GHOST_TUserDataPtr userData); + GHOST_TUserDataPtr userdata); /** * Returns indication as to whether the window is valid. @@ -825,7 +826,8 @@ extern GHOST_TUns8 *GHOST_getClipboard(int selection); /** * Put data to the Clipboard - * \param set the selection instead, X11 only feature + * \param buffer the string buffer to set. + * \param selection Set the selection instead, X11 only feature. */ extern void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection); diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 49e7def8730..468a37de633 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -90,8 +90,8 @@ bool GHOST_NDOFManagerX11::processEvents() case SPNAV_EVENT_MOTION: { /* convert to blender view coords */ - short t[3] = {e.motion.x, e.motion.y, -e.motion.z}; - short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz}; + short t[3] = {(short)e.motion.x, (short)e.motion.y, (short)-e.motion.z}; + short r[3] = {(short)-e.motion.rx, (short)-e.motion.ry, (short)e.motion.rz}; updateTranslation(t, now); updateRotation(r, now); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 08f982ffd3f..9162b7ce4e0 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -282,9 +282,6 @@ protected: /** Raised window is not yet known by the window manager, so delay application become active event handling */ bool m_needDelayedApplicationBecomeActiveEventProcessing; - /** Mouse buttons state */ - GHOST_TUns32 m_pressedMouseButtons; - /** State of the modifiers. */ GHOST_TUns32 m_modifierMask; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 27720a01a3f..16edb4af575 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -423,7 +423,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) #pragma mark defines for 10.6 api not documented in 10.5 -#ifndef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 enum { /* The following event types are available on some hardware on 10.5.2 and later */ NSEventTypeGesture = 29, @@ -435,12 +435,10 @@ enum { }; @interface NSEvent(GestureEvents) -/* This message is valid for events of type NSEventTypeMagnify, on 10.5.2 or later */ -#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 - (float)magnification; // change in magnification. #else -- (CGFloat)magnification; // change in magnification. -#endif +@interface NSEvent(GestureEvents) +- (CGFloat)magnification; // change in magnification on 10.5.2 or later. @end #endif @@ -553,7 +551,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() char *rstring = NULL; m_modifierMask =0; - m_pressedMouseButtons =0; m_isGestureInProgress = false; m_cursorDelta_x=0; m_cursorDelta_y=0; @@ -579,8 +576,10 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() sysctl( mib, 2, rstring, &len, NULL, 0 ); //Hack on MacBook revision, as multitouch avail. function missing + //MacbookAir or MacBook version >= 5 (retina is MacBookPro10,1) if (strstr(rstring,"MacBookAir") || - (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9'))) + (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')) || + (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-4]>='1') && (rstring[strlen(rstring)-4]<='9'))) m_hasMultiTouchTrackpad = true; else m_hasMultiTouchTrackpad = false; @@ -850,12 +849,14 @@ GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) cons GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const { + UInt32 button_state = GetCurrentEventButtonState(); + buttons.clear(); - buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); - buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight); - buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle); - buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4); - buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5); + buttons.set(GHOST_kButtonMaskLeft, button_state & (1 << 0)); + buttons.set(GHOST_kButtonMaskRight, button_state & (1 << 1)); + buttons.set(GHOST_kButtonMaskMiddle, button_state & (1 << 2)); + buttons.set(GHOST_kButtonMaskButton4, button_state & (1 << 3)); + buttons.set(GHOST_kButtonMaskButton5, button_state & (1 << 4)); return GHOST_kSuccess; } @@ -1593,13 +1594,17 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if ((dx == 0) && (dy == 0)) break; /* Quadratic acceleration */ - dx = dx*(fabs(dx)+0.5); - if (dx<0.0) dx-=0.5; else dx+=0.5; - if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax; + dx = dx*(fabs(dx) + 0.5); + if (dx < 0.0) dx -= 0.5; + else dx += 0.5; + if (dx < -deltaMax) dx = -deltaMax; + else if (dx > deltaMax) dx = deltaMax; - dy = dy*(fabs(dy)+0.5); - if (dy<0.0) dy-=0.5; else dy+=0.5; - if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax; + dy = dy*(fabs(dy) + 0.5); + if (dy < 0.0) dy -= 0.5; + else dy += 0.5; + if (dy < -deltaMax) dy= -deltaMax; + else if (dy > deltaMax) dy= deltaMax; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); dy = -dy; diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index 237d4c0f787..fdc4f33b784 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -73,7 +73,7 @@ GHOST_SystemSDL::createWindow(const STR_String& title, { GHOST_WindowSDL *window = NULL; - window = new GHOST_WindowSDL(this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1); + window = new GHOST_WindowSDL(this, title, left, top, width, height, state, parentWindow, type, stereoVisual, numOfAASamples); if (window) { if (GHOST_kWindowStateFullScreen == state) { diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index c9953c80a52..2d3cc4f88dc 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -256,7 +256,7 @@ createWindow( window = new GHOST_WindowX11(this, m_display, title, left, top, width, height, - state, parentWindow, type, stereoVisual); + state, parentWindow, type, stereoVisual, numOfAASamples); if (window) { /* Both are now handle in GHOST_WindowX11.cpp diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 23eefe17959..7a5bb8ab604 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -28,7 +28,7 @@ #include -#ifndef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 //Use of the SetSystemUIMode function (64bit compatible) #include #endif @@ -58,7 +58,7 @@ extern "C" { extern void wm_draw_update(bContext *C); };*/ @interface CocoaWindowDelegate : NSObject -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 #endif { @@ -115,12 +115,12 @@ extern "C" { - (void)windowDidResize:(NSNotification *)notification { -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //if (![[notification object] inLiveResize]) { //Send event only once, at end of resize operation (when user has released mouse button) #endif systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow); -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //} #endif /* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run @@ -609,9 +609,12 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() [m_openGLView release]; if (m_window) { + // previously we called [m_window release], but on 10.8 this does not + // remove the window from [NSApp orderedWindows] and perhaps other + // places, leading to crashes. so instead we set setReleasedWhenClosed + // back to YES right before closing + [m_window setReleasedWhenClosed:YES]; [m_window close]; - [[m_window delegate] release]; - [m_window release]; m_window = nil; } @@ -913,7 +916,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) * doesn't know view/window difference. */ m_fullScreen = true; -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //10.6 provides Cocoa functions to autoshow menu bar, and to change a window style //Hide menu & dock if needed if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) { @@ -972,7 +975,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) m_fullScreen = false; //Exit fullscreen -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //Show again menu & dock if needed if ([[m_window screen] isEqual:[NSScreen mainScreen]]) { [NSApp setPresentationOptions:NSApplicationPresentationDefault]; diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp index 369fc4ace14..6641b28a20e 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cpp +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -26,6 +26,7 @@ #include "GHOST_WindowSDL.h" #include "SDL_mouse.h" +#include #include static SDL_GLContext s_firstContext = NULL; @@ -48,6 +49,20 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, m_invalid_window(false), m_sdl_custom_cursor(NULL) { + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + if (numOfAASamples) { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, numOfAASamples); + } + + /* creating the window _must_ come after setting attributes */ m_sdl_win = SDL_CreateWindow(title, left, top, @@ -55,14 +70,7 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, height, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); - //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + m_sdl_glcontext = SDL_GL_CreateContext(m_sdl_win); @@ -164,6 +172,10 @@ GHOST_WindowSDL::activateDrawingContext() if (m_sdl_glcontext != NULL) { int status = SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext); (void)status; + /* Disable AA by default */ + if (m_numOfAASamples > 0) { + glDisable(GL_MULTISAMPLE_ARB); + } return GHOST_kSuccess; } return GHOST_kFailure; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index dded7dc256d..fead1884f8a 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -868,7 +868,7 @@ GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextTyp } // Attempt to enable multisample - if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled) + if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled && !is_crappy_intel_card()) { success = initMultisample(preferredFormat); diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index dd1930a241b..156bc86869a 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1265,6 +1265,10 @@ activateDrawingContext() { if (m_context != NULL) { glXMakeCurrent(m_display, m_window, m_context); + /* Disable AA by default */ + if (m_numOfAASamples > 0) { + glDisable(GL_MULTISAMPLE_ARB); + } return GHOST_kSuccess; } return GHOST_kFailure; diff --git a/intern/guardedalloc/cpp/mallocn.cpp b/intern/guardedalloc/cpp/mallocn.cpp index da77f0e1c83..8b05d25018f 100644 --- a/intern/guardedalloc/cpp/mallocn.cpp +++ b/intern/guardedalloc/cpp/mallocn.cpp @@ -28,6 +28,9 @@ #include #include "../MEM_guardedalloc.h" +void *operator new(size_t size, const char *str) throw(std::bad_alloc); +void *operator new[](size_t size, const char *str) throw(std::bad_alloc); + /* not default but can be used when needing to set a string */ void *operator new(size_t size, const char *str) throw(std::bad_alloc) { diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index a65871f4410..4a79f5d0de1 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -58,7 +58,7 @@ * store original buffer's name when doing MEM_dupallocN * helpful to profile issues with non-freed "dup_alloc" buffers, * but this introduces some overhead to memory header and makes - * things slower a bit, so betterto keep disabled by default + * things slower a bit, so better to keep disabled by default */ //#define DEBUG_MEMDUPLINAME diff --git a/intern/iksolver/intern/IK_QJacobianSolver.cpp b/intern/iksolver/intern/IK_QJacobianSolver.cpp index 43d177d0651..75f51f566c9 100644 --- a/intern/iksolver/intern/IK_QJacobianSolver.cpp +++ b/intern/iksolver/intern/IK_QJacobianSolver.cpp @@ -377,7 +377,7 @@ bool IK_QJacobianSolver::Solve( norm = maxnorm; // check for convergence - if (norm < 1e-3) { + if (norm < 1e-3 && iterations > 10) { solved = true; break; } diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt index 99c64d956cb..bc3ea0cf24c 100644 --- a/intern/itasc/CMakeLists.txt +++ b/intern/itasc/CMakeLists.txt @@ -22,7 +22,7 @@ # Contributor(s): Jacques Beaurain. # # ***** END GPL LICENSE BLOCK ***** - +remove_strict_flags() set(INC ) diff --git a/intern/itasc/kdl/chain.hpp b/intern/itasc/kdl/chain.hpp index 773f472cc5c..fde9d4ed23e 100644 --- a/intern/itasc/kdl/chain.hpp +++ b/intern/itasc/kdl/chain.hpp @@ -35,11 +35,16 @@ namespace KDL { */ class Chain { private: -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + std::vector segments; +# else // Eigen allocator is needed for alignment of Eigen data types std::vector > segments; +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #else - std::vector segments; + // Eigen allocator is needed for alignment of Eigen data types + std::vector > segments; #endif unsigned int nrOfJoints; unsigned int nrOfSegments; diff --git a/intern/itasc/kdl/tree.hpp b/intern/itasc/kdl/tree.hpp index 08c1aadc6de..a020c6cf2cf 100644 --- a/intern/itasc/kdl/tree.hpp +++ b/intern/itasc/kdl/tree.hpp @@ -27,19 +27,30 @@ #include #include -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) -#include +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + //no include +# else +# include +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ +#else +# include #endif namespace KDL { //Forward declaration class TreeElement; -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + typedef std::map SegmentMap; +# else // Eigen allocator is needed for alignment of Eigen data types typedef std::map, Eigen::aligned_allocator > > SegmentMap; +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #else - typedef std::map SegmentMap; + // Eigen allocator is needed for alignment of Eigen data types + typedef std::map, Eigen::aligned_allocator > > SegmentMap; #endif class TreeElement { diff --git a/intern/locale/CMakeLists.txt b/intern/locale/CMakeLists.txt new file mode 100644 index 00000000000..1f14a0e7a6a --- /dev/null +++ b/intern/locale/CMakeLists.txt @@ -0,0 +1,47 @@ +# ***** 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) 2012, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Bastien Montagne. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . +) + +set(INC_SYS +) + +set(SRC + boost_locale_wrapper.cpp + + boost_locale_wrapper.h +) + +if(WITH_INTERNATIONAL) + list(APPEND INC_SYS + ${BOOST_INCLUDE_DIR} + ) + add_definitions(-DWITH_INTERNATIONAL) + add_definitions(${BOOST_DEFINITIONS}) +endif() + +blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/locale/SConscript b/intern/locale/SConscript new file mode 100644 index 00000000000..df745f093ea --- /dev/null +++ b/intern/locale/SConscript @@ -0,0 +1,14 @@ +#!/usr/bin/python + +Import('env') + +sources = env.Glob('*.cpp') + +incs = '.' +defs = [] + +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + incs += ' ' + env['BF_BOOST_INC'] + +env.BlenderLib( 'bf_intern_locale', sources, Split(incs), defs, libtype=['intern','player'], priority=[10, 185]) diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp new file mode 100644 index 00000000000..939c66bad13 --- /dev/null +++ b/intern/locale/boost_locale_wrapper.cpp @@ -0,0 +1,114 @@ +/* + * ***** 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) 2012, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include +#include + +#include "boost_locale_wrapper.h" + +static std::string messages_path; +static std::string default_domain; + +void bl_locale_init(const char *_messages_path, const char *_default_domain) +{ + // Avoid using ICU backend, we do not need its power and it's rather heavy! + boost::locale::localization_backend_manager lman = boost::locale::localization_backend_manager::global(); +#if defined (_WIN32) + lman.select("winapi"); +#else + lman.select("posix"); +#endif + boost::locale::localization_backend_manager::global(lman); + + messages_path = _messages_path; + default_domain = _default_domain; +} + +void bl_locale_set(const char *locale) +{ + boost::locale::generator gen; + // Specify location of dictionaries. + gen.add_messages_path(messages_path); + gen.add_messages_domain(default_domain); + //gen.set_default_messages_domain(default_domain); + + if (locale && locale[0]) { + std::locale::global(gen(locale)); + } + else { +#if defined (__APPLE__) + // workaround to get osx system locale from user defaults + FILE* fp; + std::string locale_osx = ""; + char result[16]; + int result_len = 0; + + fp = popen("defaults read .GlobalPreferences AppleLocale", "r"); + + if(fp) { + result_len = fread(result, 1, sizeof(result) - 1, fp); + + if(result_len > 0) { + result[result_len-1] = '\0'; // \0 terminate and remove \n + locale_osx = std::string(result) + std::string(".UTF-8"); + } + + pclose(fp); + } + + if(locale_osx == "") + fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n"); + + std::locale::global(gen(locale_osx.c_str())); +#else + std::locale::global(gen("")); +#endif + } + // Note: boost always uses "C" LC_NUMERIC by default! +} + +const char* bl_locale_pgettext(const char *msgctxt, const char *msgid) +{ + // Note: We cannot use short stuff like boost::locale::gettext, because those return + // std::basic_string objects, which c_ptr()-returned char* is no more valid + // once deleted (which happens as soons they are out of scope of this func). + typedef boost::locale::message_format char_message_facet; + try { + std::locale l; + char_message_facet const &facet = std::use_facet(l); + char const *r = facet.get(0, msgctxt, msgid); + if(r) + return r; + return msgid; + } + catch(std::exception const &e) { +// std::cout << "boost_locale_pgettext: " << e.what() << " \n"; + return msgid; + } +} + diff --git a/intern/locale/boost_locale_wrapper.h b/intern/locale/boost_locale_wrapper.h new file mode 100644 index 00000000000..e7956d216f1 --- /dev/null +++ b/intern/locale/boost_locale_wrapper.h @@ -0,0 +1,49 @@ +/* + * ***** 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) 2012, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file locale/boost_locale_wrapper.h + * \ingroup locale + * A thin C wrapper around boost::locale... + */ + +#ifndef __BOOST_LOCALE_WRAPPER_H__ +#define __BOOST_LOCALE_WRAPPER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void bl_locale_init(const char *messages_path, const char *default_domain); +void bl_locale_set(const char *locale); +const char* bl_locale_pgettext(const char *msgctxt, const char *msgid); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOST_LOCALE_WRAPPER_H__ */ diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h index cfff5d10e4f..daf66dc05b1 100644 --- a/intern/memutil/MEM_CacheLimiter.h +++ b/intern/memutil/MEM_CacheLimiter.h @@ -247,8 +247,10 @@ private: if (!elem->can_destroy()) continue; - /* by default 0 means higherst priority element */ - int priority = -(queue.size() - i - 1); + /* by default 0 means highest priority element */ + /* casting a size type to int is questionable, + but unlikely to cause problems */ + int priority = -((int)(queue.size()) - i - 1); priority = getItemPriority(elem->get()->get_data(), priority); if (priority < best_match_priority || best_match_elem == NULL) { diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h index 09cf5c95854..dd19aae9db9 100644 --- a/intern/memutil/MEM_SmartPtr.h +++ b/intern/memutil/MEM_SmartPtr.h @@ -170,7 +170,7 @@ public : } /** - * Assignment operator - ownership is transfered from rhs to lhs. + * Assignment operator - ownership is transferred from rhs to lhs. * There is an intenional side-effect of function of transferring * ownership from the const parameter rhs. This is to insure * the 1-1 relationship. diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 49fc44d1e12..2d73d2ff56b 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -48,7 +48,7 @@ using namespace OCIO_NAMESPACE; #endif #define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type() -#define MEM_DELETE(what, type) if(what) { (what)->~type(); MEM_freeN(what); } (void)0 +#define MEM_DELETE(what, type) if(what) { ((type*)(what))->~type(); MEM_freeN(what); } (void)0 static void OCIO_reportError(const char *err) { @@ -421,8 +421,7 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p) { - p->~OCIO_ConstProcessorRcPtr(); - MEM_freeN(p); + MEM_DELETE(p, ConstProcessorRcPtr); } const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) diff --git a/intern/opennl/CMakeLists.txt b/intern/opennl/CMakeLists.txt index b7a24839e38..754036de101 100644 --- a/intern/opennl/CMakeLists.txt +++ b/intern/opennl/CMakeLists.txt @@ -28,7 +28,11 @@ remove_strict_flags() # remove debug flag here since this is not a blender maintained library # and debug gives a lot of prints on UV unwrapping. developers can enable if they need to. -add_definitions(-UDEBUG) +if(MSVC) + remove_definitions(-DDEBUG) +else() + add_definitions(-UDEBUG) +endif() # quiet compiler warnings about undefined defines diff --git a/intern/smoke/intern/FFT_NOISE.h b/intern/smoke/intern/FFT_NOISE.h index a087b4e1391..8b7e4f2728b 100644 --- a/intern/smoke/intern/FFT_NOISE.h +++ b/intern/smoke/intern/FFT_NOISE.h @@ -167,6 +167,8 @@ static void generatTile_FFT(float* const noiseTileData, std::string filename) for (int x = 0; x < xRes; x++, index++) noise[index] -= forward[index][0] / totalCells; + // fill noiseTileData + memcpy(noiseTileData, noise, sizeof(float) * totalCells); // save out the noise tile saveTile(noise, filename); diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp index 1c89f5d681b..5b6509afead 100644 --- a/intern/smoke/intern/WTURBULENCE.cpp +++ b/intern/smoke/intern/WTURBULENCE.cpp @@ -220,21 +220,25 @@ void WTURBULENCE::setNoise(int type) { if(type == (1<<1)) // FFT { +#ifdef WITH_FFTW3 // needs fft - #ifdef WITH_FFTW3 std::string noiseTileFilename = std::string("noise.fft"); generatTile_FFT(_noiseTile, noiseTileFilename); - #endif + return; +#else + fprintf(stderr, "FFTW not enabled, falling back to wavelet noise.\n"); +#endif } - else if(type == (1<<2)) // curl +#if 0 + if(type == (1<<2)) // curl { // TODO: not supported yet + return; } - else // standard - wavelet - { - std::string noiseTileFilename = std::string("noise.wavelets"); - generateTile_WAVELET(_noiseTile, noiseTileFilename); - } +#endif + + std::string noiseTileFilename = std::string("noise.wavelets"); + generateTile_WAVELET(_noiseTile, noiseTileFilename); } // init direct access functions from blender diff --git a/intern/utfconv/utfconv.h b/intern/utfconv/utfconv.h index cf0e69170a2..ada85e274e3 100644 --- a/intern/utfconv/utfconv.h +++ b/intern/utfconv/utfconv.h @@ -57,18 +57,18 @@ size_t count_utf_16_from_8(const char *string8); /** * Converts utf-16 string to allocated utf-8 string - * @params in16 utf-16 string to convert - * @params out8 utf-8 string to string the conversion - * @params size8 the allocated size in bytes of out8 + * @param in16 utf-16 string to convert + * @param out8 utf-8 string to string the conversion + * @param size8 the allocated size in bytes of out8 * @return Returns any errors occured during conversion. See the block above, */ int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8); /** * Converts utf-8 string to allocated utf-16 string - * @params in8 utf-8 string to convert - * @params out16 utf-16 string to string the conversion - * @params size16 the allocated size in wchar_t (two byte) of out16 + * @param in8 utf-8 string to convert + * @param out16 utf-16 string to string the conversion + * @param size16 the allocated size in wchar_t (two byte) of out16 * @return Returns any errors occured during conversion. See the block above, */ int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16); @@ -76,16 +76,16 @@ int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16); /** * Allocates and converts the utf-8 string from utf-16 - * @params in16 utf-16 string to convert - * @params add any additional size which will be allocated for new utf-8 string in bytes + * @param in16 utf-16 string to convert + * @param add any additional size which will be allocated for new utf-8 string in bytes * @return New allocated and converted utf-8 string or NULL if in16 is 0. */ char *alloc_utf_8_from_16(const wchar_t *in16, size_t add); /** * Allocates and converts the utf-16 string from utf-8 - * @params in8 utf-8 string to convert - * @params add any additional size which will be allocated for new utf-16 string in wchar_t (two bytes) + * @param in8 utf-8 string to convert + * @param add any additional size which will be allocated for new utf-16 string in wchar_t (two bytes) * @return New allocated and converted utf-16 string or NULL if in8 is 0. */ wchar_t *alloc_utf16_from_8(const char *in8, size_t add); diff --git a/source/darwin/blender.app/Contents/Info.plist b/release/darwin/blender.app/Contents/Info.plist similarity index 100% rename from source/darwin/blender.app/Contents/Info.plist rename to release/darwin/blender.app/Contents/Info.plist diff --git a/source/darwin/blender.app/Contents/MacOS/blender b/release/darwin/blender.app/Contents/MacOS/blender similarity index 100% rename from source/darwin/blender.app/Contents/MacOS/blender rename to release/darwin/blender.app/Contents/MacOS/blender diff --git a/source/darwin/blender.app/Contents/PkgInfo b/release/darwin/blender.app/Contents/PkgInfo similarity index 100% rename from source/darwin/blender.app/Contents/PkgInfo rename to release/darwin/blender.app/Contents/PkgInfo diff --git a/source/darwin/blender.app/Contents/Resources/blender file icon.icns b/release/darwin/blender.app/Contents/Resources/blender file icon.icns similarity index 100% rename from source/darwin/blender.app/Contents/Resources/blender file icon.icns rename to release/darwin/blender.app/Contents/Resources/blender file icon.icns diff --git a/source/darwin/blender.app/Contents/Resources/blender icon.icns b/release/darwin/blender.app/Contents/Resources/blender icon.icns similarity index 100% rename from source/darwin/blender.app/Contents/Resources/blender icon.icns rename to release/darwin/blender.app/Contents/Resources/blender icon.icns diff --git a/source/darwin/blenderplayer.app/Contents/Info.plist b/release/darwin/blenderplayer.app/Contents/Info.plist similarity index 100% rename from source/darwin/blenderplayer.app/Contents/Info.plist rename to release/darwin/blenderplayer.app/Contents/Info.plist diff --git a/source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer b/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer similarity index 100% rename from source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer rename to release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer diff --git a/source/darwin/blenderplayer.app/Contents/PkgInfo b/release/darwin/blenderplayer.app/Contents/PkgInfo similarity index 100% rename from source/darwin/blenderplayer.app/Contents/PkgInfo rename to release/darwin/blenderplayer.app/Contents/PkgInfo diff --git a/source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns b/release/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns similarity index 100% rename from source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns rename to release/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns diff --git a/source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns b/release/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns similarity index 100% rename from source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns rename to release/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns diff --git a/source/darwin/set_simulation_threads.app/Contents/Info.plist b/release/darwin/set_simulation_threads.app/Contents/Info.plist similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Info.plist rename to release/darwin/set_simulation_threads.app/Contents/Info.plist diff --git a/source/darwin/set_simulation_threads.app/Contents/MacOS/applet b/release/darwin/set_simulation_threads.app/Contents/MacOS/applet similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/MacOS/applet rename to release/darwin/set_simulation_threads.app/Contents/MacOS/applet diff --git a/source/darwin/set_simulation_threads.app/Contents/PkgInfo b/release/darwin/set_simulation_threads.app/Contents/PkgInfo similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/PkgInfo rename to release/darwin/set_simulation_threads.app/Contents/PkgInfo diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt b/release/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt rename to release/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/applet.icns b/release/darwin/set_simulation_threads.app/Contents/Resources/applet.icns similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Resources/applet.icns rename to release/darwin/set_simulation_threads.app/Contents/Resources/applet.icns diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc b/release/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc rename to release/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf b/release/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf rename to release/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf diff --git a/release/datafiles/blender_icons.png b/release/datafiles/blender_icons.png index 55a83964a8b..b0d5e825738 100644 Binary files a/release/datafiles/blender_icons.png and b/release/datafiles/blender_icons.png differ diff --git a/release/datafiles/prvicons.png b/release/datafiles/prvicons.png index dc31964b33f..1636e644b12 100644 Binary files a/release/datafiles/prvicons.png and b/release/datafiles/prvicons.png differ diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png index 7f40ead3911..41284eff9c1 100644 Binary files a/release/datafiles/splash.png and b/release/datafiles/splash.png differ diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend index 5056246e743..cdd43c74f3b 100644 Binary files a/release/datafiles/startup.blend and b/release/datafiles/startup.blend differ diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 7e604c5de4c..6bf81d73f8b 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -232,7 +232,6 @@ def enable(module_name, default_set=True, persistent=False): import os import sys - import imp def handle_error(): import traceback @@ -246,6 +245,7 @@ def enable(module_name, default_set=True, persistent=False): mtime_orig = getattr(mod, "__time__", 0) mtime_new = os.path.getmtime(mod.__file__) if mtime_orig != mtime_new: + import imp print("module changed on disk:", mod.__file__, "reloading...") try: diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index 0db3f85f1ff..c7414e84046 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -40,46 +40,46 @@ LANGUAGES_CATEGORIES = ( ) LANGUAGES = ( # ID, UI english label, ISO code. - ( 0, "Default (Default)", "DEFAULT", ""), - ( 1, "English (English)", "en_US", "english"), - ( 2, "Japanese (日本語)", "ja_JP", "japanese"), - ( 3, "Dutch (Nederlandse taal)", "nl_NL", "dutch"), - ( 4, "Italian (Italiano)", "it_IT", "italian"), - ( 5, "German (Deutsch)", "de_DE", "german"), - ( 6, "Finnish (Suomi)", "fi_FI", "finnish"), - ( 7, "Swedish (Svenska)", "sv_SE", "swedish"), - ( 8, "French (Français)", "fr_FR", "french"), - ( 9, "Spanish (Español)", "es", "spanish"), - (10, "Catalan (Català)", "ca_AD", "catalan"), - (11, "Czech (Český)", "cs_CZ", "czech"), - (12, "Portuguese (Português)", "pt_PT", "portuguese_portugal"), - (13, "Simplified Chinese (简体中文)", "zh_CN", "Chinese (Simplified)_China.1252"), - (14, "Traditional Chinese (繁體中文)", "zh_TW", "Chinese (Traditional)_China.1252"), - (15, "Russian (Русский)", "ru_RU", "russian"), - (16, "Croatian (Hrvatski)", "hr_HR", "croatian"), - (17, "Serbian (Српски)", "sr_RS", "serbian"), - (18, "Ukrainian (Український)", "uk_UA", "ukrainian"), - (19, "Polish (Polski)", "pl_PL", "polish"), - (20, "Romanian (Român)", "ro_RO", "romanian"), + ( 0, "Default (Default)", "DEFAULT"), + ( 1, "English (English)", "en_US"), + ( 2, "Japanese (日本語)", "ja_JP"), + ( 3, "Dutch (Nederlandse taal)", "nl_NL"), + ( 4, "Italian (Italiano)", "it_IT"), + ( 5, "German (Deutsch)", "de_DE"), + ( 6, "Finnish (Suomi)", "fi_FI"), + ( 7, "Swedish (Svenska)", "sv_SE"), + ( 8, "French (Français)", "fr_FR"), + ( 9, "Spanish (Español)", "es"), + (10, "Catalan (Català)", "ca_AD"), + (11, "Czech (Český)", "cs_CZ"), + (12, "Portuguese (Português)", "pt_PT"), + (13, "Simplified Chinese (简体中文)", "zh_CN"), + (14, "Traditional Chinese (繁體中文)", "zh_TW"), + (15, "Russian (Русский)", "ru_RU"), + (16, "Croatian (Hrvatski)", "hr_HR"), + (17, "Serbian (Српски)", "sr_RS"), + (18, "Ukrainian (Український)", "uk_UA"), + (19, "Polish (Polski)", "pl_PL"), + (20, "Romanian (Român)", "ro_RO"), # Using the utf8 flipped form of Arabic (العربية). - (21, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG", "arabic"), - (22, "Bulgarian (Български)", "bg_BG", "bulgarian"), - (23, "Greek (Ελληνικά)", "el_GR", "greek"), - (24, "Korean (한국 언어)", "ko_KR", "korean"), - (25, "Nepali (नेपाली)", "ne_NP", "nepali"), + (21, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG"), + (22, "Bulgarian (Български)", "bg_BG"), + (23, "Greek (Ελληνικά)", "el_GR"), + (24, "Korean (한국 언어)", "ko_KR"), + (25, "Nepali (नेपाली)", "ne_NP"), # Using the utf8 flipped form of Persian (فارسی). - (26, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR", "farsi"), - (27, "Indonesian (Bahasa indonesia)", "id_ID", "indonesian"), - (28, "Serbian Latin (Srpski latinica)", "sr_RS@latin", "serbian (latin)"), - (29, "Kyrgyz (Кыргыз тили)", "ky_KG", "kyrgyz"), - (30, "Turkish (Türkçe)", "tr_TR", "turkish"), - (31, "Hungarian (Magyar)", "hu_HU", "hungarian"), - (32, "Brazilian Portuguese (Português do Brasil)", "pt_BR", "protuguese_brazil"), + (26, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR"), + (27, "Indonesian (Bahasa indonesia)", "id_ID"), + (28, "Serbian Latin (Srpski latinica)", "sr_RS@latin"), + (29, "Kyrgyz (Кыргыз тили)", "ky_KG"), + (30, "Turkish (Türkçe)", "tr_TR"), + (31, "Hungarian (Magyar)", "hu_HU"), + (32, "Brazilian Portuguese (Português do Brasil)", "pt_BR"), # Using the utf8 flipped form of Hebrew (עִבְרִית)). - (33, "Hebrew (תירִבְעִ)", "he_IL", "hebrew"), - (34, "Estonian (Eestlane)", "et_EE", "estonian"), - (35, "Esperanto (Esperanto)", "eo", "esperanto"), - (36, "Spanish from Spain (Español de España)", "es_ES", "spanish_spain"), + (33, "Hebrew (תירִבְעִ)", "he_IL"), + (34, "Estonian (Eestlane)", "et_EE"), + (35, "Esperanto (Esperanto)", "eo"), + (36, "Spanish from Spain (Español de España)", "es_ES"), ) # Name of language file used by Blender to generate translations' menu. @@ -114,6 +114,9 @@ DOMAIN = "blender" # File type (ext) to parse. PYGETTEXT_ALLOWED_EXTS = {".c", ".cpp", ".cxx", ".hpp", ".hxx", ".h"} +# Max number of contexts into a BLF_I18N_MSGID_MULTI_CTXT macro... +PYGETTEXT_MAX_MULTI_CTXT = 16 + # Where to search contexts definitions, relative to SOURCE_DIR (defined below). PYGETTEXT_CONTEXTS_DEFSRC = os.path.join("source", "blender", "blenfont", "BLF_translation.h") @@ -149,7 +152,10 @@ _str_whole_re = ( # End of loop. "))*" ) -_ctxt_re = r"(?P(?:" + _str_whole_re.format(_="_ctxt") + r")|(?:[A-Z_0-9]+))" +_ctxt_re_gen = lambda uid : r"(?P(?:".format(uid=uid) + \ + _str_whole_re.format(_="_ctxt{uid}".format(uid=uid)) + \ + r")|(?:[A-Z_0-9]+))" +_ctxt_re = _ctxt_re_gen("") _msg_re = r"(?P" + _str_whole_re.format(_="_msg") + r")" PYGETTEXT_KEYWORDS = (() + tuple((r"{}\(\s*" + _msg_re + r"\s*\)").format(it) @@ -165,7 +171,11 @@ PYGETTEXT_KEYWORDS = (() + for it in ("BMO_error_raise",)) + tuple(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\)|,)").format(it) - for it in ("modifier_setError",)) + for it in ("modifier_setError",)) + + + tuple((r"{}\(\s*" + _msg_re + r"\s*,\s*(?:" + \ + r"\s*,\s*)?(?:".join(_ctxt_re_gen(i) for i in range(PYGETTEXT_MAX_MULTI_CTXT)) + r")?\s*\)").format(it) + for it in ("BLF_I18N_MSGID_MULTI_CTXT",)) ) ESCAPE_RE = ( diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py index 60a943d2bd4..fbe405a61c6 100644 --- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py +++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py @@ -77,6 +77,7 @@ dict_uimsgs = { "boxpack", "buffersize", "builtin", "builtins", + "bytecode", "chunksize", "de", "defocus", @@ -425,12 +426,14 @@ dict_uimsgs = { "fh", "fov", "fft", + "futura", "gfx", "gl", "glsl", "gpl", "gpu", "gpus", "hc", + "hdc", "hdr", "hh", "mm", "ss", "ff", # hh:mm:ss:ff timecode "hsv", "hsva", @@ -441,6 +444,7 @@ dict_uimsgs = { "mux", "ndof", "ppc", + "precisa", "px", "qmc", "rgb", "rgba", @@ -502,6 +506,8 @@ dict_uimsgs = { "mtl", "ogg", "openjpeg", + "osl", + "oso", "piz", "png", "po", diff --git a/release/scripts/modules/bl_i18n_utils/update_languages_menu.py b/release/scripts/modules/bl_i18n_utils/update_languages_menu.py index d45a5543220..9b4cb20fadf 100755 --- a/release/scripts/modules/bl_i18n_utils/update_languages_menu.py +++ b/release/scripts/modules/bl_i18n_utils/update_languages_menu.py @@ -53,7 +53,7 @@ FLAG_MESSAGES = { def find_matching_po(languages, stats, forbidden): """Match languages defined in LANGUAGES setting to relevant po, if possible!""" ret = [] - for uid, label, org_key, long_loc in languages: + for uid, label, org_key, in languages: key = org_key if key not in stats: # Try to simplify the key (eg from es_ES to es). @@ -64,11 +64,11 @@ def find_matching_po(languages, stats, forbidden): key = key + org_key[org_key.index('@'):] if key in stats: if key in forbidden: - ret.append((stats[key], uid, label, org_key, long_loc, FORBIDDEN)) + ret.append((stats[key], uid, label, org_key, FORBIDDEN)) else: - ret.append((stats[key], uid, label, org_key, long_loc, OK)) + ret.append((stats[key], uid, label, org_key, OK)) else: - ret.append((0.0, uid, label, org_key, long_loc, MISSING)) + ret.append((0.0, uid, label, org_key, MISSING)) return ret def main(): @@ -103,14 +103,14 @@ def main(): stats = sorted(stats, key=lambda it: it[0], reverse=True) langs_cats = [[] for i in range(len(limits))] highest_uid = 0 - for prop, uid, label, key, long_loc, flag in stats: + for prop, uid, label, key, flag in stats: if prop < limits[idx][0]: # Sub-sort languages by iso-codes. langs_cats[idx].sort(key=lambda it: it[2]) idx += 1 if prop < min_trans and flag == OK: flag = TOOLOW - langs_cats[idx].append((uid, label, key, long_loc, flag)) + langs_cats[idx].append((uid, label, key, flag)) if abs(uid) > highest_uid: highest_uid = abs(uid) # Sub-sort last group of languages by iso-codes! @@ -120,7 +120,7 @@ def main(): f.write("# and to generate translation menu.\n") f.write("#\n") f.write("# File format:\n") - f.write("# ID:MENULABEL:ISOCODE:WINCODE\n") + f.write("# ID:MENULABEL:ISOCODE\n") f.write("# ID must be unique, except for 0 value (marks categories for menu).\n") f.write("# Line starting with a # are comments!\n") f.write("#\n") @@ -135,12 +135,12 @@ def main(): # Do not write the category if it has no language! f.write("# Void category! #0:{}:\n".format(cat[1])) # ...and all matching language entries! - for uid, label, key, long_loc, flag in langs_cat: + for uid, label, key, flag in langs_cat: if flag == OK: - f.write("{}:{}:{}:{}\n".format(uid, label, key, long_loc)) + f.write("{}:{}:{}\n".format(uid, label, key)) else: # Non-existing, commented entry! - f.write("# {} #{}:{}:{}:{}\n".format(FLAG_MESSAGES[flag], uid, label, key, long_loc)) + f.write("# {} #{}:{}:{}\n".format(FLAG_MESSAGES[flag], uid, label, key)) if __name__ == "__main__": diff --git a/release/scripts/modules/bl_i18n_utils/update_pot.py b/release/scripts/modules/bl_i18n_utils/update_pot.py index 51197b86678..ecb5d837a09 100755 --- a/release/scripts/modules/bl_i18n_utils/update_pot.py +++ b/release/scripts/modules/bl_i18n_utils/update_pot.py @@ -52,6 +52,7 @@ SRC_POTFILES = settings.FILE_NAME_SRC_POTFILES CONTEXT_DEFAULT = settings.CONTEXT_DEFAULT PYGETTEXT_ALLOWED_EXTS = settings.PYGETTEXT_ALLOWED_EXTS +PYGETTEXT_MAX_MULTI_CTXT = settings.PYGETTEXT_MAX_MULTI_CTXT SVN_EXECUTABLE = settings.SVN_EXECUTABLE @@ -79,6 +80,31 @@ clean_str = lambda s: "".join(m.group("clean") for m in _clean_str(s)) def check_file(path, rel_path, messages): + def process_entry(ctxt, msg): + # Context. + if ctxt: + if ctxt in CONTEXTS: + ctxt = CONTEXTS[ctxt] + elif '"' in ctxt or "'" in ctxt: + ctxt = clean_str(ctxt) + else: + print("WARNING: raw context “{}” couldn’t be resolved!" + "".format(ctxt)) + ctxt = CONTEXT_DEFAULT + else: + ctxt = CONTEXT_DEFAULT + # Message. + if msg: + if '"' in msg or "'" in msg: + msg = clean_str(msg) + else: + print("WARNING: raw message “{}” couldn’t be resolved!" + "".format(msg)) + msg = "" + else: + msg = "" + return (ctxt, msg) + with open(path, encoding="utf-8") as f: f = f.read() for srch in pygettexts: @@ -86,34 +112,23 @@ def check_file(path, rel_path, messages): line = pos = 0 while m: d = m.groupdict() - # Context. - ctxt = d.get("ctxt_raw") - if ctxt: - if ctxt in CONTEXTS: - ctxt = CONTEXTS[ctxt] - elif '"' in ctxt or "'" in ctxt: - ctxt = clean_str(ctxt) - else: - print("WARNING: raw context “{}” couldn’t be resolved!" - "".format(ctxt)) - ctxt = CONTEXT_DEFAULT - else: - ctxt = CONTEXT_DEFAULT - # Message. - msg = d.get("msg_raw") - if msg: - if '"' in msg or "'" in msg: - msg = clean_str(msg) - else: - print("WARNING: raw message “{}” couldn’t be resolved!" - "".format(msg)) - msg = "" - else: - msg = "" # Line. line += f[pos:m.start()].count('\n') - # And we are done for this item! - messages.setdefault((ctxt, msg), []).append(":".join((rel_path, str(line)))) + msg = d.get("msg_raw") + # First, try the "multi-contexts" stuff! + ctxts = tuple(d.get("ctxt_raw{}".format(i)) for i in range(PYGETTEXT_MAX_MULTI_CTXT)) + if ctxts[0]: + for ctxt in ctxts: + if not ctxt: + break + ctxt, _msg = process_entry(ctxt, msg) + # And we are done for this item! + messages.setdefault((ctxt, _msg), []).append(":".join((rel_path, str(line)))) + else: + ctxt = d.get("ctxt_raw") + ctxt, msg = process_entry(ctxt, msg) + # And we are done for this item! + messages.setdefault((ctxt, msg), []).append(":".join((rel_path, str(line)))) pos = m.end() line += f[m.start():pos].count('\n') m = srch(f, pos) @@ -138,12 +153,12 @@ def py_xgettext(messages): rel_path = os.path.relpath(path, SOURCE_DIR) if rel_path in forbidden: continue - elif rel_path in forced: - forced.remove(rel_path) - check_file(path, rel_path, messages) - for path in forced: + elif rel_path not in forced: + forced.add(rel_path) + for rel_path in sorted(forced): + path = os.path.join(SOURCE_DIR, rel_path) if os.path.exists(path): - check_file(os.path.join(SOURCE_DIR, path), path, messages) + check_file(path, rel_path, messages) # Spell checking! diff --git a/release/scripts/modules/bl_i18n_utils/update_trunk.py b/release/scripts/modules/bl_i18n_utils/update_trunk.py index 9b904ec861a..b84a227ae0a 100755 --- a/release/scripts/modules/bl_i18n_utils/update_trunk.py +++ b/release/scripts/modules/bl_i18n_utils/update_trunk.py @@ -115,7 +115,7 @@ def main(): if not os.path.exists(os.path.join(TRUNK_PO_DIR, ".".join((lang, "po")))): failed.add(lang) - # Check and compile each po separatly, to keep track of those failing. + # Check and compile each po separately, to keep track of those failing. # XXX There should not be any failing at this stage, import step is # supposed to have already filtered them out! for po in os.listdir(TRUNK_PO_DIR): diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py index 34beb6035ae..52bf1c04e65 100644 --- a/release/scripts/modules/bpy/ops.py +++ b/release/scripts/modules/bpy/ops.py @@ -74,7 +74,7 @@ class BPyOpsSubMod(object): eg. bpy.ops.object """ - __keys__ = ("module",) + __slots__ = ("module",) def __init__(self, module): self.module = module @@ -111,7 +111,7 @@ class BPyOpsSubModOp(object): eg. bpy.ops.object.somefunc """ - __keys__ = ("module", "func") + __slots__ = ("module", "func") def _get_doc(self): return op_as_string(self.idname()) diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index 573694ff08e..4ad00eb267e 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -216,7 +216,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): for mod in _global_loaded_modules: test_reload(mod) - _global_loaded_modules[:] = [] + del _global_loaded_modules[:] for base_path in script_paths(): for path_subdir in _script_module_dirs: diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index ad3cf8c08ec..0166f954dc9 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -223,7 +223,7 @@ def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()): else: other_dir = None - ed_adj[:] = [] + del ed_adj[:] flipped = False @@ -235,22 +235,22 @@ def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()): if other_dir and flipped is False: flipped = True # only flip the list once context_loop.reverse() - ed_adj[:] = [] + del ed_adj[:] context_loop.append(other_dir) # save 1 look-up ed_adj = edges[context_loop[-1]] if len(ed_adj) != 2: - ed_adj[:] = [] + del ed_adj[:] break else: - ed_adj[:] = [] + del ed_adj[:] break i = ed_adj.index(context_loop[-2]) context_loop.append(ed_adj[not i]) # Dont look at this again - ed_adj[:] = [] + del ed_adj[:] return edge_loops @@ -325,10 +325,12 @@ def ngon_tessellate(from_data, indices, fix_loops=True): fgon to create from existing verts. from_data: either a mesh, or a list/tuple of vectors. - indices: a list of indices to use this list is the ordered closed polyline + :arg indices: a list of indices to use this list is the ordered closed polyline to fill, and can be a subset of the data given. - fix_loops: If this is enabled polylines that use loops to make multiple + :type indices: list + :arg fix_loops: If this is enabled polylines that use loops to make multiple polylines are delt with correctly. + :type fix_loops: bool """ from mathutils.geometry import tessellate_polygon @@ -436,7 +438,7 @@ def ngon_tessellate(from_data, indices, fix_loops=True): if s1[0][1] == s1[-1][1]: # remove endpoints double s1.pop() - s2[:] = [] # Empty this segment s2 so we don't use it again. + del s2[:] # Empty this segment s2 so we don't use it again. return True joining_segments = True diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 4cd823d9184..e42ae43aed6 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -394,7 +394,7 @@ class Mesh(bpy_types.ID): p.vertices = f loop_index += loop_len - # if no edges - calculae them + # if no edges - calculate them if faces and (not edges): self.update(calc_edges=True) diff --git a/release/scripts/modules/rna_xml.py b/release/scripts/modules/rna_xml.py index fc8e3125228..e21ccd08a35 100644 --- a/release/scripts/modules/rna_xml.py +++ b/release/scripts/modules/rna_xml.py @@ -178,7 +178,7 @@ def rna2xml(fw=print_ln, fw("%s\n" % (ident, value_type_name)) # ------------------------------------------------------------------------- - # needs re-workign to be generic + # needs re-working to be generic if root_node: fw("%s<%s>\n" % (root_ident, root_node)) diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml index 805aa9bd184..0a77aa132a8 100644 --- a/release/scripts/presets/interface_theme/back_to_black.xml +++ b/release/scripts/presets/interface_theme/back_to_black.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-100" + shadedown="0"> - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-100" + shadedown="0"> - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-100" + shadedown="0"> - - - + + - - - - + shadedown="0"> - - - - - + - + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-100" + shadedown="0"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text="#ffffff" + text_hi="#ffffff" + header="#000000" + header_text="#979797" + header_text_hi="#ffffff" + button="#000000" + button_title="#c5c5c5" + button_text="#c3c3c3" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml index 232276e300e..18ae3072208 100644 --- a/release/scripts/presets/interface_theme/blender_24x.xml +++ b/release/scripts/presets/interface_theme/blender_24x.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + shadetop="10" + shadedown="-10"> - - - + + - - - - - - - - + shadetop="10" + shadedown="-10"> - - - - - - - - - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="10" + shadedown="-10"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + text="#000000" + text_hi="#0f0f0f" + header="#b4b4b4" + header_text="#000000" + header_text_hi="#ffffff" + button="#b4b4b4" + button_title="#000000" + button_text="#000000" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml index 581f5ce82d6..c10eb108000 100644 --- a/release/scripts/presets/interface_theme/elsyiun.xml +++ b/release/scripts/presets/interface_theme/elsyiun.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0"> - - - + + + + + + - - - - + shadedown="0"> - - - + + + shadetop="5" + shadedown="0"> - + - + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="5" + shadedown="0"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text="#000000" + text_hi="#ffffff" + header="#3b3b3b" + header_text="#000000" + header_text_hi="#ffffff" + button="#3b3b3b" + button_title="#8b8b8b" + button_text="#8b8b8b" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml index 61730583396..ad514bbbafa 100644 --- a/release/scripts/presets/interface_theme/hexagon.xml +++ b/release/scripts/presets/interface_theme/hexagon.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + shadetop="10" + shadedown="0"> - - - - - - - - - - - + + - - - - - - - - + text_sel="#000000" + show_shaded="TRUE" + shadetop="10" + shadedown="0"> - + + + + + - + text_sel="#000000" + show_shaded="TRUE" + shadetop="10" + shadedown="0"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + text="#000000" + text_hi="#0f0f0f" + header="#5c606c" + header_text="#dddddd" + header_text_hi="#ffffff" + button="#6c717f" + button_title="#d7d7d7" + button_text="#d7d7d7" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml index 05075f06239..8f4a42b6ab7 100644 --- a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml +++ b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + text="#dfdfdf" + text_sel="#dfdfdf" + show_shaded="TRUE" + shadetop="21" + shadedown="-21"> - - - + + + - - - + + - - - - + text_sel="#dfdbcf" + show_shaded="TRUE" + shadetop="5" + shadedown="-5"> - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-10" + shadedown="0"> - + - + text_sel="#dfdbcf" + show_shaded="TRUE" + shadetop="15" + shadedown="-5"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + button_text="#000000" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index b5df519cf59..ec8efc8d371 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -366,7 +366,7 @@ kmi = km.keymap_items.new('mesh.split', 'Y', 'PRESS') kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True) kmi = km.keymap_items.new('mesh.delete', 'X', 'PRESS') kmi = km.keymap_items.new('mesh.delete', 'DEL', 'PRESS') -kmi = km.keymap_items.new('mesh.knifetool', 'LEFTMOUSE', 'PRESS', key_modifier='K') +kmi = km.keymap_items.new('mesh.knife_tool', 'LEFTMOUSE', 'PRESS', key_modifier='K') # BMESH_TODO: midpoints for knife were moved to modal keymap #kmi = km.keymap_items.new('mesh.knifetool', 'LEFTMOUSE', 'PRESS', shift=True, key_modifier='K') #kmi.properties.type = 'MIDPOINTS' diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py index 074069255bc..ce328b86eac 100644 --- a/release/scripts/startup/bl_operators/image.py +++ b/release/scripts/startup/bl_operators/image.py @@ -224,7 +224,7 @@ class ProjectApply(Operator): image_name = ProjectEdit._proj_hack[0] # TODO, deal with this nicer try: - image = bpy.data.images[image_name] + image = bpy.data.images[image_name, None] except KeyError: import traceback traceback.print_exc() diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 4e90f2e8585..9e449f325d6 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -665,15 +665,60 @@ class TransformsToDeltasAnim(Operator): return (obs is not None) def execute(self, context): + # map from standard transform paths to "new" transform paths + STANDARD_TO_DELTA_PATHS = { + "location" : "delta_location", + "rotation_euler" : "delta_rotation_euler", + "rotation_quaternion" : "delta_rotation_quaternion", + #"rotation_axis_angle" : "delta_rotation_axis_angle", + "scale" : "delta_scale" + } + DELTA_PATHS = STANDARD_TO_DELTA_PATHS.values() + + # try to apply on each selected object + success = False for obj in context.selected_editable_objects: - # get animation data adt = obj.animation_data if (adt is None) or (adt.action is None): self.report({'WARNING'}, "No animation data to convert on object: %r" % obj.name) continue - + + # first pass over F-Curves: ensure that we don't have conflicting + # transforms already (e.g. if this was applied already) [#29110] + existingFCurves = {} + for fcu in adt.action.fcurves: + # get "delta" path - i.e. the final paths which may clash + path = fcu.data_path + if path in STANDARD_TO_DELTA_PATHS: + # to be converted - conflicts may exist... + dpath = STANDARD_TO_DELTA_PATHS[path] + elif path in DELTA_PATHS: + # already delta - check for conflicts... + dpath = path + else: + # non-transform - ignore + continue + + # a delta path like this for the same index shouldn't + # exist already, otherwise we've got a conflict + if dpath in existingFCurves: + # ensure that this index hasn't occurred before + if fcu.array_index in existingFCurves[dpath]: + # conflict + self.report({'ERROR'}, + "Object '%r' already has '%r' F-Curve(s). Remove these before trying again" % + (obj.name, dpath)) + return {'CANCELLED'} + else: + # no conflict here + existingFCurves[dpath] += [fcu.array_index] + else: + # no conflict yet + existingFCurves[dpath] = [fcu.array_index] + + # if F-Curve uses standard transform path # just append "delta_" to this path for fcu in adt.action.fcurves: diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index b7adf53dbf1..ee9769d8b43 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -554,6 +554,12 @@ class WM_MT_operator_presets(Menu): def draw(self, context): self.operator = context.active_operator.bl_idname + + # dummy 'default' menu item + layout = self.layout + layout.operator("wm.operator_defaults") + layout.separator() + Menu.draw_preset(self, context) @property diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index 694412e51d7..6d1f35fe937 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -116,8 +116,12 @@ class PlayRenderedAnim(Operator): cmd = [player_path] # extra options, fps controls etc. if preset in {'BLENDER24', 'INTERNAL'}: - opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), - "-j", str(scene.frame_step), file] + opts = ["-a", + "-f", str(rd.fps), str(rd.fps_base), + "-s", str(scene.frame_start), + "-e", str(scene.frame_end), + "-j", str(scene.frame_step), + file] cmd.extend(opts) elif preset == 'DJV': opts = [file, "-playback_speed", "%d" % int(rd.fps / rd.fps_base)] diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py index b60b5257984..727c4ad739f 100644 --- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py +++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py @@ -26,195 +26,124 @@ from bpy.types import Operator def extend(obj, operator, EXTEND_MODE): - from bpy_extras import mesh_utils - + import bmesh me = obj.data - me_verts = me.vertices - # script will fail without UVs if not me.uv_textures: me.uv_textures.new() - - # Toggle Edit mode - is_editmode = (obj.mode == 'EDIT') - if is_editmode: - bpy.ops.object.mode_set(mode='OBJECT') - - #t = sys.time() - edge_average_lengths = {} - - OTHER_INDEX = 2, 3, 0, 1 - - def extend_uvs(face_source, face_target, edge_key): - """ - Takes 2 faces, - Projects its extends its UV coords onto the face next to it. - Both faces must share an edge - """ - - def face_edge_vs(vi): - vlen = len(vi) - return [(vi[i], vi[(i + 1) % vlen]) for i in range(vlen)] - - vidx_source = face_source.vertices - vidx_target = face_target.vertices - - uv_layer = me.uv_layers.active.data - uvs_source = [uv_layer[i].uv for i in face_source.loop_indices] - uvs_target = [uv_layer[i].uv for i in face_target.loop_indices] - - # vertex index is the key, uv is the value - - uvs_vhash_source = {vindex: uvs_source[i] for i, vindex in enumerate(vidx_source)} - - uvs_vhash_target = {vindex: uvs_target[i] for i, vindex in enumerate(vidx_target)} - - edge_idxs_source = face_edge_vs(vidx_source) - edge_idxs_target = face_edge_vs(vidx_target) - - source_matching_edge = -1 - target_matching_edge = -1 - - edge_key_swap = edge_key[1], edge_key[0] - - try: - source_matching_edge = edge_idxs_source.index(edge_key) - except: - source_matching_edge = edge_idxs_source.index(edge_key_swap) - try: - target_matching_edge = edge_idxs_target.index(edge_key) - except: - target_matching_edge = edge_idxs_target.index(edge_key_swap) - - edgepair_inner_source = edge_idxs_source[source_matching_edge] - edgepair_inner_target = edge_idxs_target[target_matching_edge] - edgepair_outer_source = edge_idxs_source[OTHER_INDEX[source_matching_edge]] - edgepair_outer_target = edge_idxs_target[OTHER_INDEX[target_matching_edge]] - - if edge_idxs_source[source_matching_edge] == edge_idxs_target[target_matching_edge]: - iA = 0 # Flipped, most common - iB = 1 - else: # The normals of these faces must be different - iA = 1 - iB = 0 - - # Set the target UV's touching source face, no tricky calculations needed, - uvs_vhash_target[edgepair_inner_target[0]][:] = uvs_vhash_source[edgepair_inner_source[iA]] - uvs_vhash_target[edgepair_inner_target[1]][:] = uvs_vhash_source[edgepair_inner_source[iB]] - - # Set the 2 UV's on the target face that are not touching - # for this we need to do basic expanding on the source faces UV's - if EXTEND_MODE == 'LENGTH': - - try: # divide by zero is possible - ''' - measure the length of each face from the middle of each edge to the opposite - along the axis we are copying, use this - ''' - i1a = edgepair_outer_target[iB] - i2a = edgepair_inner_target[iA] - if i1a > i2a: - i1a, i2a = i2a, i1a - - i1b = edgepair_outer_source[iB] - i2b = edgepair_inner_source[iA] - if i1b > i2b: - i1b, i2b = i2b, i1b - # print edge_average_lengths - factor = edge_average_lengths[i1a, i2a][0] / edge_average_lengths[i1b, i2b][0] - except: - # Div By Zero? - factor = 1.0 - - uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + factor * (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]]) - uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + factor * (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]]) - - else: - # same as above but with no factors - uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]]) - uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]]) - - face_act = me.polygons.active - if face_act == -1: + + bm = bmesh.from_edit_mesh(me) + + f_act = bm.faces.active + uv_act = bm.loops.layers.uv.active + + if f_act is None: operator.report({'ERROR'}, "No active face") return - - face_sel = [f for f in me.polygons if len(f.vertices) == 4 and f.select] - - face_act_local_index = -1 - for i, f in enumerate(face_sel): - if f.index == face_act: - face_act_local_index = i - break - - if face_act_local_index == -1: - operator.report({'ERROR'}, "Active face not selected") + elif len(f_act.verts) != 4: + operator.report({'ERROR'}, "Active face must be a quad") return - # Modes - # 0 not yet searched for. - # 1:mapped, use search from this face - removed! - # 2:all siblings have been searched. don't search again. - face_modes = [0] * len(face_sel) - face_modes[face_act_local_index] = 1 # extend UV's from this face. + faces = [f for f in bm.faces if f.select and len(f.verts) == 4] - # Edge connectivity - edge_faces = {} - for i, f in enumerate(face_sel): - for edkey in f.edge_keys: + for f in faces: + f.tag = False + f_act.tag = True + + + # our own local walker + def walk_face(f): + # all faces in this list must be tagged + f.tag = True + faces_a = [f] + faces_b = [] + + while faces_a: + for f in faces_a: + for l in f.loops: + l_edge = l.edge + if (l_edge.is_manifold is True) and (l_edge.seam is False): + l_other = l.link_loop_radial_next + f_other = l_other.face + if not f_other.tag: + yield (f, l, f_other) + f_other.tag = True + faces_b.append(f_other) + # swap + faces_a, faces_b = faces_b, faces_a + faces_b.clear() + + def extrapolate_uv(fac, + l_a_outer, l_a_inner, + l_b_outer, l_b_inner): + l_b_inner[:] = l_a_inner + l_b_outer[:] = l_a_inner + ((l_a_inner - l_a_outer) * fac) + + def apply_uv(f_prev, l_prev, f_next): + l_a = [None, None, None, None] + l_b = [None, None, None, None] + + l_a[0] = l_prev + l_a[1] = l_a[0].link_loop_next + l_a[2] = l_a[1].link_loop_next + l_a[3] = l_a[2].link_loop_next + + # l_b + # +-----------+ + # |(3) |(2) + # | | + # |l_next(0) |(1) + # +-----------+ + # ^ + # l_a | + # +-----------+ + # |l_prev(0) |(1) + # | (f) | + # |(3) |(2) + # +-----------+ + # copy from this face to the one above. + + # get the other loops + l_next = l_prev.link_loop_radial_next + if l_next.vert != l_prev.vert: + l_b[1] = l_next + l_b[0] = l_b[1].link_loop_next + l_b[3] = l_b[0].link_loop_next + l_b[2] = l_b[3].link_loop_next + else: + l_b[0] = l_next + l_b[1] = l_b[0].link_loop_next + l_b[2] = l_b[1].link_loop_next + l_b[3] = l_b[2].link_loop_next + + l_a_uv = [l[uv_act].uv for l in l_a] + l_b_uv = [l[uv_act].uv for l in l_b] + + if EXTEND_MODE == 'LENGTH': + a0, b0, c0 = l_a[3].vert.co, l_a[0].vert.co, l_b[3].vert.co + a1, b1, c1 = l_a[2].vert.co, l_a[1].vert.co, l_b[2].vert.co + + d1 = (a0 - b0).length + (a1 - b1).length + d2 = (b0 - c0).length + (b1 - c1).length try: - edge_faces[edkey].append(i) - except: - edge_faces[edkey] = [i] + fac = d2 / d1 + except ZeroDivisionError: + fac = 1.0 + else: + fac = 1.0 - if EXTEND_MODE == 'LENGTH': - edge_loops = mesh_utils.edge_loops_from_tessfaces(me, face_sel, [ed.key for ed in me.edges if ed.use_seam]) - me_verts = me.vertices - for loop in edge_loops: - looplen = [0.0] - for ed in loop: - edge_average_lengths[ed] = looplen - looplen[0] += (me_verts[ed[0]].co - me_verts[ed[1]].co).length - looplen[0] = looplen[0] / len(loop) + extrapolate_uv(fac, + l_a_uv[3], l_a_uv[0], + l_b_uv[3], l_b_uv[0]) - # remove seams, so we don't map across seams. - for ed in me.edges: - if ed.use_seam: - # remove the edge pair if we can - try: - del edge_faces[ed.key] - except: - pass - # Done finding seams + extrapolate_uv(fac, + l_a_uv[2], l_a_uv[1], + l_b_uv[2], l_b_uv[1]) - # face connectivity - faces around each face - # only store a list of indices for each face. - face_faces = [[] for i in range(len(face_sel))] + for f_triple in walk_face(f_act): + apply_uv(*f_triple) - for edge_key, faces in edge_faces.items(): - if len(faces) == 2: # Only do edges with 2 face users for now - face_faces[faces[0]].append((faces[1], edge_key)) - face_faces[faces[1]].append((faces[0], edge_key)) - - # Now we know what face is connected to what other face, map them by connectivity - ok = True - while ok: - ok = False - for i in range(len(face_sel)): - if face_modes[i] == 1: # searchable - for f_sibling, edge_key in face_faces[i]: - if face_modes[f_sibling] == 0: - face_modes[f_sibling] = 1 # mapped and search from. - extend_uvs(face_sel[i], face_sel[f_sibling], edge_key) - face_modes[i] = 1 # we can map from this one now. - ok = True # keep searching - - face_modes[i] = 2 # don't search again - - if is_editmode: - bpy.ops.object.mode_set(mode='EDIT') - else: - me.update_tag() + bmesh.update_edit_mesh(me, False) def main(context, operator): diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py index 526d78c4c11..198b3660ff8 100644 --- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py +++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py @@ -552,7 +552,7 @@ class LightMapPack(Operator): # Disable REGISTER flag for now because this operator might create new # images. This leads to non-proper operator redo because current undo # stack is local for edit mode and can not remove images created by this - # oprtator. + # operator. # Proper solution would be to make undo stack aware of such things, # but for now just disable redo. Keep undo here so unwanted changes to uv # coords might be undone. diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py index 9fa44cac812..160ca5c6977 100644 --- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py +++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py @@ -23,7 +23,7 @@ import bpy from bpy.types import Operator DEG_TO_RAD = 0.017453292519943295 # pi/180.0 -SMALL_NUM = 0.000000001 +SMALL_NUM = 0.0000001 # see bug [#31598] why we dont have smaller values BIG_NUM = 1e15 global USER_FILL_HOLES @@ -517,7 +517,7 @@ def mergeUvIslands(islandList): for uv in f.uv: uv+= offset - sourceIsland[0][:] = [] # Empty + del sourceIsland[0][:] # Empty # Move edge loop into new and offset. @@ -527,7 +527,7 @@ def mergeUvIslands(islandList): (e[0]+offset, e[1]+offset, e[2])\ ) for e in sourceIsland[6] ] ) - sourceIsland[6][:] = [] # Empty + del sourceIsland[6][:] # Empty # Sort by edge length, reverse so biggest are first. @@ -540,7 +540,7 @@ def mergeUvIslands(islandList): for p in sourceIsland[7]: p+= offset - sourceIsland[7][:] = [] + del sourceIsland[7][:] # Decrement the efficiency @@ -759,7 +759,7 @@ class thickface(object): self.v = [mesh_verts[i] for i in face.vertices] self.uv = [uv_layer[i].uv for i in face.loop_indices] - self.no = face.normal + self.no = face.normal.copy() self.area = face.area self.edge_keys = face.edge_keys @@ -993,7 +993,7 @@ def main(context, if mostUniqueAngle < USER_PROJECTION_LIMIT_CONVERTED: #print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectMeshFaces) # Now weight the vector to all its faces, will give a more direct projection - # if the face its self was not representive of the normal from surrounding faces. + # if the face its self was not representative of the normal from surrounding faces. newProjectVec = tempMeshFaces[mostUniqueIndex].no newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)] diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 2bff11a686d..105b532ac38 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -41,12 +41,17 @@ class MESH_OT_delete_edgeloop(Operator): return bpy.ops.transform.edge_slide.poll() def execute(self, context): + mesh = context.object.data + use_mirror_x = mesh.use_mirror_x + mesh.use_mirror_x = False if 'FINISHED' in bpy.ops.transform.edge_slide(value=1.0): bpy.ops.mesh.select_more() bpy.ops.mesh.remove_doubles() - return {'FINISHED'} - - return {'CANCELLED'} + ret = {'FINISHED'} + else: + ret = {'CANCELLED'} + mesh.use_mirror_x = use_mirror_x + return ret rna_path_prop = StringProperty( name="Context Attributes", @@ -1044,6 +1049,8 @@ class WM_OT_properties_edit(Operator): try: value_eval = eval(value) + # assert else None -> None, not "None", see [#33431] + assert(type(value_eval) in {str, float, int, bool, tuple, list}) except: value_eval = value diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index 50c34be1414..845beb0f862 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -239,7 +239,7 @@ class DATA_PT_ghost(ArmatureButtonsPanel, Panel): class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel): - bl_label = "iTaSC parameters" + bl_label = "Inverse Kinematics" bl_options = {'DEFAULT_CLOSED'} @classmethod diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py index 1441c642d51..fdaee6b7cde 100644 --- a/release/scripts/startup/bl_ui/properties_data_bone.py +++ b/release/scripts/startup/bl_ui/properties_data_bone.py @@ -244,7 +244,6 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel): pchan = ob.pose.bones[bone.name] row = layout.row() - row.prop(ob.pose, "ik_solver") active = pchan.is_in_ik_chain diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 5f6036c8945..25cecc90c70 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -142,8 +142,12 @@ class DATA_PT_camera(CameraButtonsPanel, Panel): if cam.sensor_fit == 'AUTO': col.prop(cam, "sensor_width", text="Size") else: - col.prop(cam, "sensor_width", text="Width") - col.prop(cam, "sensor_height", text="Height") + sub = col.column() + sub.active = cam.sensor_fit == 'HORIZONTAL' + sub.prop(cam, "sensor_width", text="Width") + sub = col.column() + sub.active = cam.sensor_fit == 'VERTICAL' + sub.prop(cam, "sensor_height", text="Height") col = split.column(align=True) col.prop(cam, "sensor_fit", text="") diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index a8f4aa30e95..7747ef45c4d 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -174,11 +174,14 @@ class DATA_PT_geometry_curve(CurveButtonsPanel, Panel): col.prop(curve, "bevel_object", text="") col = layout.column(align=True) - col.active = (curve.bevel_object is not None) - col.prop(curve, "use_fill_caps") col.prop(curve, "bevel_factor_start") col.prop(curve, "bevel_factor_end") + row = col.row() + row.active = (curve.bevel_object is not None) + row.prop(curve, "use_fill_caps") + row.prop(curve, "use_map_taper") + class DATA_PT_pathanim(CurveButtonsPanelCurve, Panel): bl_label = "Path Animation" diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 902358813df..62461d800f6 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -625,6 +625,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "wrap_method", text="") if md.wrap_method == 'PROJECT': + col.prop(md, "project_limit", text="Limit") split = layout.split(percentage=0.25) col = split.column() @@ -642,8 +643,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.label(text="Cull Faces:") col.prop(md, "cull_face", expand=True) - layout.label(text="Auxiliary Target:") - layout.prop(md, "auxiliary_target", text="") + layout.prop(md, "auxiliary_target") elif md.wrap_method == 'NEAREST_SURFACEPOINT': layout.prop(md, "use_keep_above_surface") @@ -1029,5 +1029,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "use_y_symmetry") col.prop(md, "use_z_symmetry") + def TRIANGULATE(self, layout, ob, md): + layout.prop(md, "use_beauty") + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py index 3fa63bac13c..eb0929895f8 100644 --- a/release/scripts/startup/bl_ui/properties_object_constraint.py +++ b/release/scripts/startup/bl_ui/properties_object_constraint.py @@ -134,7 +134,7 @@ class ConstraintButtonsPanel(): layout.prop(con, "ik_type") getattr(self, 'IK_' + con.ik_type)(context, layout, con) else: - # Legacy IK constraint + # Standard IK constraint self.target_template(layout, con) layout.prop(con, "pole_target") @@ -151,17 +151,27 @@ class ConstraintButtonsPanel(): col.prop(con, "iterations") col.prop(con, "chain_count") - col.label(text="Weight:") - col.prop(con, "weight", text="Position", slider=True) - sub = col.column() - sub.active = con.use_rotation - sub.prop(con, "orient_weight", text="Rotation", slider=True) - col = split.column() col.prop(con, "use_tail") col.prop(con, "use_stretch") - col.separator() - col.prop(con, "use_rotation") + + layout.label(text="Weight:") + + split = layout.split() + col = split.column() + row = col.row(align=True) + row.prop(con, "use_location", text="") + sub = row.row() + sub.active = con.use_location + sub.prop(con, "weight", text="Position", slider=True) + + col = split.column() + row = col.row(align=True) + row.prop(con, "use_rotation", text="") + sub = row.row() + sub.active = con.use_rotation + sub.prop(con, "orient_weight", text="Rotation", slider=True) + def IK_COPY_POSE(self, context, layout, con): self.target_template(layout, con) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 6fcd56fb99e..3f672d2a977 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -148,7 +148,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel): #row.label(text="Render") if part.is_fluid: - layout.label(text="{} fluid particles for this frame".format(str(part.count))) + layout.label(text="%d fluid particles for this frame" % part.count) return row = col.row() diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py index 5ff179902a3..23d16c14f2d 100644 --- a/release/scripts/startup/bl_ui/space_console.py +++ b/release/scripts/startup/bl_ui/space_console.py @@ -25,7 +25,7 @@ class CONSOLE_HT_header(Header): bl_space_type = 'CONSOLE' def draw(self, context): - layout = self.layout.row(align=True) + layout = self.layout.row() layout.template_header() diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index a81553a8257..5535070c1c4 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -241,9 +241,9 @@ class DOPESHEET_MT_channel(Menu): layout.operator("anim.channels_delete") layout.separator() - layout.operator("anim.channels_setting_toggle") - layout.operator("anim.channels_setting_enable") - layout.operator("anim.channels_setting_disable") + layout.operator_menu_enum("anim.channels_setting_toggle", "type") + layout.operator_menu_enum("anim.channels_setting_enable", "type") + layout.operator_menu_enum("anim.channels_setting_disable", "type") layout.separator() layout.operator("anim.channels_editable_toggle") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index e89bd78a84f..4cb6538458f 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -161,9 +161,9 @@ class GRAPH_MT_channel(Menu): layout.operator("anim.channels_delete") layout.separator() - layout.operator("anim.channels_setting_toggle") - layout.operator("anim.channels_setting_enable") - layout.operator("anim.channels_setting_disable") + layout.operator_menu_enum("anim.channels_setting_toggle", "type") + layout.operator_menu_enum("anim.channels_setting_enable", "type") + layout.operator_menu_enum("anim.channels_setting_disable", "type") layout.separator() layout.operator("anim.channels_editable_toggle") diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 5302ad9b471..1ea20d96386 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -249,6 +249,7 @@ class IMAGE_MT_uvs_weldalign(Menu): layout = self.layout layout.operator("uv.weld") # W, 1 + layout.operator("uv.remove_doubles") layout.operator_enum("uv.align", "axis") # W, 2/3/4 @@ -413,7 +414,9 @@ class IMAGE_HT_header(Header): row = layout.row(align=True) row.prop(toolsettings, "use_snap", text="") - row.prop(toolsettings, "snap_target", text="") + row.prop(toolsettings, "snap_uv_element", text="", icon_only=True) + if toolsettings.snap_uv_element != 'INCREMENT': + row.prop(toolsettings, "snap_target", text="") mesh = context.edit_object.data layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="") @@ -684,7 +687,7 @@ class IMAGE_PT_paint(Panel, ImagePaintPanel): if brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index c0f2d3c361b..8df117e27a0 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -193,7 +193,7 @@ class INFO_MT_mesh_add(Menu): def draw(self, context): layout = self.layout - layout.operator_context = 'EXEC_REGION_WIN' + layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("mesh.primitive_plane_add", icon='MESH_PLANE', text="Plane") layout.operator("mesh.primitive_cube_add", icon='MESH_CUBE', text="Cube") layout.operator("mesh.primitive_circle_add", icon='MESH_CIRCLE', text="Circle") @@ -373,7 +373,7 @@ class INFO_MT_help(Menu): layout = self.layout layout.operator("wm.url_open", text="Manual", icon='HELP').url = "http://wiki.blender.org/index.php/Doc:2.6/Manual" - layout.operator("wm.url_open", text="Release Log", icon='URL').url = "http://www.blender.org/development/release-logs/blender-264" + layout.operator("wm.url_open", text="Release Log", icon='URL').url = "http://www.blender.org/development/release-logs/blender-265" layout.separator() layout.operator("wm.url_open", text="Blender Website", icon='URL').url = "http://www.blender.org" diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index cba45d4c2b7..fdfd43157c7 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -31,21 +31,21 @@ def act_strip(context): def draw_color_balance(layout, color_balance): col = layout.column() col.label(text="Lift:") - col.template_color_wheel(color_balance, "lift", value_slider=True, cubic=True) + col.template_color_picker(color_balance, "lift", value_slider=True, cubic=True) row = col.row() row.prop(color_balance, "lift", text="") row.prop(color_balance, "invert_lift", text="Inverse") col = layout.column() col.label(text="Gamma:") - col.template_color_wheel(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) + col.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) row = col.row() row.prop(color_balance, "gamma", text="") row.prop(color_balance, "invert_gamma", text="Inverse") col = layout.column() col.label(text="Gain:") - col.template_color_wheel(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) + col.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) row = col.row() row.prop(color_balance, "gain", text="") row.prop(color_balance, "invert_gain", text="Inverse") @@ -707,8 +707,6 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): layout.template_ID(strip, "scene") scene = strip.scene - if scene: - layout.prop(scene.render, "use_sequencer") layout.label(text="Camera Override") layout.template_ID(strip, "scene_camera") diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index a64f8aa4aed..fa8752c21be 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -137,9 +137,6 @@ class TEXT_PT_find(Panel): row.operator("text.replace_set_selected", text="", icon='TEXT') col.operator("text.replace") - # mark - layout.operator("text.mark_all") - # settings layout.prop(st, "use_match_case") row = layout.row() @@ -216,17 +213,6 @@ class TEXT_MT_edit_select(Menu): layout.operator("text.select_line") -class TEXT_MT_edit_markers(Menu): - bl_label = "Markers" - - def draw(self, context): - layout = self.layout - - layout.operator("text.markers_clear") - layout.operator("text.next_marker") - layout.operator("text.previous_marker") - - class TEXT_MT_format(Menu): bl_label = "Format" @@ -290,7 +276,6 @@ class TEXT_MT_edit(Menu): layout.separator() layout.menu("TEXT_MT_edit_select") - layout.menu("TEXT_MT_edit_markers") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 455bf210ac2..0bb25e98456 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -422,7 +422,7 @@ class USERPREF_PT_system(Panel): col.separator() col.separator() - if hasattr(system, "compute_device"): + if hasattr(system, "compute_device_type"): col.label(text="Compute Device:") col.row().prop(system, "compute_device_type", expand=True) sub = col.row() @@ -442,10 +442,9 @@ class USERPREF_PT_system(Panel): col.label(text="Anisotropic Filtering") col.prop(system, "anisotropic_filter", text="") col.prop(system, "use_vertex_buffer_objects") - # Anti-aliasing is disabled as it breaks border/lasso select - #~ col.prop(system, "use_antialiasing") col.label(text="Window Draw Method:") col.prop(system, "window_draw_method", text="") + col.prop(system, "multi_sample", text="") col.label(text="Text Draw Options:") col.prop(system, "use_text_antialiasing") col.label(text="Textures:") @@ -728,6 +727,29 @@ class USERPREF_PT_theme(Panel): colsub = padding.column() colsub.row().prop(ui, "header") + col.separator() + col.separator() + + ui = theme.user_interface + col.label("Axis Colors:") + + row = col.row() + + subsplit = row.split(percentage=0.95) + + padding = subsplit.split(percentage=0.15) + colsub = padding.column() + colsub = padding.column() + colsub.row().prop(ui, "axis_x") + colsub.row().prop(ui, "axis_y") + colsub.row().prop(ui, "axis_z") + + subsplit = row.split(percentage=0.85) + + padding = subsplit.split(percentage=0.15) + colsub = padding.column() + colsub = padding.column() + layout.separator() layout.separator() elif theme.theme_area == 'BONE_COLOR_SETS': diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 21a80df9ead..b1dfc397ce0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -168,6 +168,8 @@ class VIEW3D_MT_transform(VIEW3D_MT_transform_base): # generic... layout = self.layout + layout.operator("transform.shrink_fatten", text="Shrink Fatten") + layout.separator() layout.operator("transform.translate", text="Move Texture Space").texture_space = True @@ -1734,18 +1736,9 @@ class VIEW3D_MT_edit_mesh_select_mode(Menu): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - - props = layout.operator("wm.context_set_value", text="Vertex", icon='VERTEXSEL') - props.value = "(True, False, False)" - props.data_path = "tool_settings.mesh_select_mode" - - props = layout.operator("wm.context_set_value", text="Edge", icon='EDGESEL') - props.value = "(False, True, False)" - props.data_path = "tool_settings.mesh_select_mode" - - props = layout.operator("wm.context_set_value", text="Face", icon='FACESEL') - props.value = "(False, False, True)" - props.data_path = "tool_settings.mesh_select_mode" + layout.operator("mesh.select_mode", text="Vertex", icon='VERTEXSEL').type = 'VERT' + layout.operator("mesh.select_mode", text="Edge", icon='EDGESEL').type = 'EDGE' + layout.operator("mesh.select_mode", text="Face", icon='FACESEL').type = 'FACE' class VIEW3D_MT_edit_mesh_extrude(Menu): @@ -1845,8 +1838,8 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.separator() - layout.operator("mesh.edge_rotate", text="Rotate Edge CW").direction = 'CW' - layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").direction = 'CCW' + layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False + layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").use_ccw = True layout.separator() @@ -1895,13 +1888,13 @@ class VIEW3D_MT_edit_mesh_faces(Menu): layout.separator() - layout.operator("mesh.edge_rotate", text="Rotate Edge CW").direction = 'CW' + layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False layout.separator() - layout.operator_menu_enum("mesh.uvs_rotate", "direction") + layout.operator("mesh.uvs_rotate") layout.operator("mesh.uvs_reverse") - layout.operator_menu_enum("mesh.colors_rotate", "direction") + layout.operator("mesh.colors_rotate") layout.operator("mesh.colors_reverse") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 49355de4006..91132a72b07 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -633,7 +633,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): elif context.image_paint_object and brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) @@ -681,7 +681,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): # Vertex Paint Mode # elif context.vertex_paint_object and brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) @@ -1048,7 +1048,7 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel): @classmethod def poll(cls, context): brush = context.tool_settings.image_paint.brush - return (brush and brush.image_tool != 'SOFTEN') + return (brush is not None) def draw_header(self, context): ipaint = context.tool_settings.image_paint diff --git a/release/scripts/templates/bmesh_simple.py b/release/scripts/templates/bmesh_simple.py index 656febf4918..45e6b52d578 100644 --- a/release/scripts/templates/bmesh_simple.py +++ b/release/scripts/templates/bmesh_simple.py @@ -19,3 +19,4 @@ for v in bm.verts: # Finish up, write the bmesh back to the mesh bm.to_mesh(me) +bm.free() # free and prevent further access diff --git a/release/scripts/templates/bmesh_simple_editmode.py b/release/scripts/templates/bmesh_simple_editmode.py new file mode 100644 index 00000000000..d79ba02c2cb --- /dev/null +++ b/release/scripts/templates/bmesh_simple_editmode.py @@ -0,0 +1,23 @@ +# This example assumes we have a mesh object in edit-mode + +import bpy +import bmesh + +# Get the active mesh +obj = bpy.context.edit_object +me = obj.data + + +# Get a BMesh representation +bm = bmesh.from_edit_mesh(me) + +bm.faces.active = None + +# Modify the BMesh, can do anything here... +for v in bm.verts: + v.co.x += 1.0 + + +# Show the updates in the viewport +# and recalculate n-gon tessellation. +bmesh.update_edit_mesh(me, True) diff --git a/release/scripts/templates/script_stub.py b/release/scripts/templates/script_stub.py index 3b3212892d5..44c7b802e2c 100644 --- a/release/scripts/templates/script_stub.py +++ b/release/scripts/templates/script_stub.py @@ -8,4 +8,7 @@ import os filename = "my_script.py" filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename) -exec(compile(open(filepath).read(), filepath, 'exec')) +global_namespace = {"__file__": filepath, "__name__": "__main__"} +file = open(filepath, 'rb') +exec(compile(file.read(), filepath, 'exec'), global_namespace) +file.close() diff --git a/release/text/readme.html b/release/text/readme.html index 40ea9035835..414a7d8e744 100644 --- a/release/text/readme.html +++ b/release/text/readme.html @@ -12,18 +12,18 @@ -

Blender 2.64

+

Blender 2.65


About

Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows and FreeBSD and has a large world-wide community.

Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.

For more information, visit blender.org.


-

2.64

-

The Blender Foundation and online developer community is proud to present Blender 2.64. This release is the fifth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. More information about this release.

+

2.65

+

The Blender Foundation and online developer community is proud to present Blender 2.65. This release is the sixth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. More information about this release.


Bugs

-

Although Blender 2.64 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.

+

Although Blender 2.65 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.


Package Contents

The downloaded Blender package includes:

@@ -47,7 +47,7 @@

Links

Users:

General information www.blender.org
- Full release log www.blender.org/development/release-logs/blender-264/
+ Full release log www.blender.org/development/release-logs/blender-265/
Tutorials www.blender.org/education-help/
Manual wiki.blender.org/index.php/Doc:2.6/Manual
User Forum www.blenderartists.org
diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c index e1732b0caae..d6301b723a7 100644 --- a/source/blender/avi/intern/avi.c +++ b/source/blender/avi/intern/avi.c @@ -665,13 +665,13 @@ AviError AVI_open_movie(const char *name, AviMovie *movie) } } -/* Some AVI's have offset entries in absolute coordinates - * instead of an offset from the movie beginning... this is... - * wacky, but we need to handle it. The wacky offset always - * starts at movi_offset it seems... so we'll check that. - * Note the the offset needs an extra 4 bytes for some - * undetermined reason */ - + /* Some AVI's have offset entries in absolute coordinates + * instead of an offset from the movie beginning... this is... + * wacky, but we need to handle it. The wacky offset always + * starts at movi_offset it seems... so we'll check that. + * Note the the offset needs an extra 4 bytes for some + * undetermined reason */ + if (movie->entries[0].Offset == movie->movi_offset) movie->read_offset = 4; } diff --git a/source/blender/avi/intern/avi_rgb.c b/source/blender/avi/intern/avi_rgb.c index 11d9bdf8612..c6a78eccce2 100644 --- a/source/blender/avi/intern/avi_rgb.c +++ b/source/blender/avi/intern/avi_rgb.c @@ -98,7 +98,7 @@ void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, unsigned char *buf buf = MEM_mallocN(movie->header->Height * movie->header->Width * 3, "fromavirgbbuf"); rowstride = movie->header->Width * 3; - if (bits != 16) if (movie->header->Width % 2) rowstride++; + if ((bits != 16) && (movie->header->Width % 2)) rowstride++; for (y = 0; y < movie->header->Height; y++) { memcpy(&buf[y * movie->header->Width * 3], &buffer[((movie->header->Height - 1) - y) * rowstride], movie->header->Width * 3); diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index b01ce93cb65..159d4b067b6 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -35,16 +35,6 @@ #define TEXT_DOMAIN_NAME "blender" -/* blf_translation.c */ - -#ifdef WITH_INTERNATIONAL -unsigned char *BLF_get_unifont(int *unifont_size); -void BLF_free_unifont(void); -#endif - -const char *BLF_gettext(const char *msgid); -const char *BLF_pgettext(const char *context, const char *message); - /* blf_lang.c */ /* Search the path directory to the locale files, this try all @@ -61,22 +51,29 @@ void BLF_lang_set(const char *); /* Get the current locale (short code, e.g. es_ES). */ const char *BLF_lang_get(void); -/* Set the current encoding name. */ -void BLF_lang_encoding(const char *str); - /* Get EnumPropertyItem's for translations menu. */ struct EnumPropertyItem *BLF_RNA_lang_enum_properties(void); +/* blf_translation.c */ + +#ifdef WITH_INTERNATIONAL +unsigned char *BLF_get_unifont(int *unifont_size); +void BLF_free_unifont(void); +#endif + +const char *BLF_pgettext(const char *msgctxt, const char *msgid); + /* translation */ int BLF_translate_iface(void); int BLF_translate_tooltips(void); -const char *BLF_translate_do_iface(const char *contex, const char *msgid); -const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); +const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid); +const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); /* The "translation-marker" macro. */ #define N_(msgid) msgid #define CTX_N_(context, msgid) msgid + /* Those macros should be used everywhere in UI code. */ #ifdef WITH_INTERNATIONAL /* #define _(msgid) BLF_gettext(msgid) */ @@ -88,10 +85,17 @@ const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); /* #define _(msgid) msgid */ #define IFACE_(msgid) msgid #define TIP_(msgid) msgid - #define CTX_IFACE_(context, msgid) msgid - #define CTX_TIP_(context, msgid) msgid + #define CTX_IFACE_(context, msgid) ((void)context, msgid) + #define CTX_TIP_(context, msgid) ((void)context, msgid) #endif +/* Helper macro, when we want to define a same msgid for multiple msgctxt... + * Does nothing in C, but is "parsed" by our i18n py tools. + * XXX Currently limited to at most 16 contexts at most + * (but you can call it several times with the same msgid, should you need more contexts!). + */ +#define BLF_I18N_MSGID_MULTI_CTXT(msgid, ...) + /****************************************************************************** * All i18n contexts must be defined here. * This is a nice way to be sure not to use a context twice for different @@ -104,8 +108,39 @@ const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); /* Default context for operator names/labels. */ #define BLF_I18NCONTEXT_OPERATOR_DEFAULT "Operator" -/* Audio disambiguation context. */ -#define BLF_I18NCONTEXT_AUDIO "Audio" - +/* ID-types contexts. */ +/* WARNING! Keep it in sync with idtypes in blenkernel/intern/idcode.c */ +#define BLF_I18NCONTEXT_ID_ACTION "Action" +#define BLF_I18NCONTEXT_ID_ARMATURE "Armature" +#define BLF_I18NCONTEXT_ID_BRUSH "Brush" +#define BLF_I18NCONTEXT_ID_CAMERA "Camera" +#define BLF_I18NCONTEXT_ID_CURVE "Curve" +#define BLF_I18NCONTEXT_ID_GPENCIL "GPencil" +#define BLF_I18NCONTEXT_ID_GROUP "Group" +#define BLF_I18NCONTEXT_ID_ID "ID" +#define BLF_I18NCONTEXT_ID_IMAGE "Image" +/*#define BLF_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */ +#define BLF_I18NCONTEXT_ID_SHAPEKEY "Key" +#define BLF_I18NCONTEXT_ID_LAMP "Lamp" +#define BLF_I18NCONTEXT_ID_LIBRARY "Library" +#define BLF_I18NCONTEXT_ID_LATTICE "Lattice" +#define BLF_I18NCONTEXT_ID_MATERIAL "Material" +#define BLF_I18NCONTEXT_ID_METABALL "Metaball" +#define BLF_I18NCONTEXT_ID_MESH "Mesh" +#define BLF_I18NCONTEXT_ID_NODETREE "NodeTree" +#define BLF_I18NCONTEXT_ID_OBJECT "Object" +#define BLF_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings" +#define BLF_I18NCONTEXT_ID_SCENE "Scene" +#define BLF_I18NCONTEXT_ID_SCREEN "Screen" +#define BLF_I18NCONTEXT_ID_SEQUENCE "Sequence" +#define BLF_I18NCONTEXT_ID_SPEAKER "Speaker" +#define BLF_I18NCONTEXT_ID_SOUND "Sound" +#define BLF_I18NCONTEXT_ID_TEXTURE "Texture" +#define BLF_I18NCONTEXT_ID_TEXT "Text" +#define BLF_I18NCONTEXT_ID_VFONT "VFont" +#define BLF_I18NCONTEXT_ID_WORLD "World" +#define BLF_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager" +#define BLF_I18NCONTEXT_ID_MOVIECLIP "MovieClip" +#define BLF_I18NCONTEXT_ID_MASK "Mask" #endif /* __BLF_TRANSLATION_H__ */ diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 022dfd282b0..90baef14a74 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../makesrna ../imbuf ../../../intern/guardedalloc + ../../../intern/locale ) set(INC_SYS @@ -54,9 +55,6 @@ set(SRC ) if(WITH_INTERNATIONAL) - list(APPEND INC_SYS - ${GETTEXT_INCLUDE_DIRS} - ) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index 075da58b116..c0591c877ef 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -4,11 +4,10 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../blenloader' +incs = '. intern #/intern/guardedalloc #/intern/locale ../blenkernel ../blenlib ../blenloader' incs += ' ../makesdna ../makesrna ../imbuf ../editors/include' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] -incs += ' ' + env['BF_GETTEXT_INC'] defs = ['GLEW_STATIC'] diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index f3cc92e7a27..778b6c11e5a 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -28,7 +28,6 @@ * \ingroup blf */ - #include #include #include diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index 501f8cd2958..0ed48623dd5 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -28,20 +28,17 @@ */ -#include -#include -#include - -#include "BKE_global.h" - -#include "BLF_api.h" #include "BLF_translation.h" /* own include */ #ifdef WITH_INTERNATIONAL -#include +#include +#include +#include -#include "libintl.h" +#include "boost_locale_wrapper.h" + +#include "BKE_global.h" #include "DNA_userdef_types.h" @@ -49,52 +46,33 @@ #include "MEM_guardedalloc.h" -#include "BLI_string.h" -#include "BLI_utildefines.h" -#include "BLI_path_util.h" #include "BLI_fileops.h" #include "BLI_linklist.h" +#include "BLI_path_util.h" #include "BLI_string.h" - -#define SYSTEM_ENCODING_DEFAULT "UTF-8" -#define FONT_SIZE_DEFAULT 12 +#include "BLI_utildefines.h" /* Locale options. */ -static char global_messagepath[1024]; -static char global_language[32]; -static char global_encoding_name[32]; - static const char **locales = NULL; -static char **long_locales = NULL; /* XXX Temp fix until we get a final solution with modern intl lib under windows! */ static int num_locales = 0; static EnumPropertyItem *locales_menu = NULL; static int num_locales_menu = 0; #define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0) #define LOCALE(_id) (locales ? locales[_id] : "") -#define LONG_LOCALE(_id) (long_locales ? long_locales[_id] : "") static void free_locales(void) { if (locales) { int idx = num_locales_menu - 1; /* Last item does not need to be freed! */ while (idx--) { - MEM_freeN((void*)locales_menu[idx].identifier); - MEM_freeN((void*)locales_menu[idx].name); - MEM_freeN((void*)locales_menu[idx].description); /* Also frees locales's relevant value! */ - } - - idx = num_locales; - while (idx--) { - if (long_locales[idx]) { - MEM_freeN(long_locales[idx]); - } + MEM_freeN((void *)locales_menu[idx].identifier); + MEM_freeN((void *)locales_menu[idx].name); + MEM_freeN((void *)locales_menu[idx].description); /* Also frees locales's relevant value! */ } MEM_freeN(locales); locales = NULL; - MEM_freeN(long_locales); - long_locales = NULL; } if (locales_menu) { MEM_freeN(locales_menu); @@ -140,7 +118,6 @@ static void fill_locales(void) /* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */ if (num_locales > 0) { locales = MEM_callocN(num_locales * sizeof(char*), __func__); - long_locales = MEM_callocN(num_locales * sizeof(char*), __func__); while (line) { int id; char *loc, *sep1, *sep2, *sep3; @@ -163,26 +140,28 @@ static void fill_locales(void) sep2++; sep3 = strchr(sep2, ':'); + if (sep3) { locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2); - - if (id == 0) { - /* The DEFAULT item... */ - if (BLI_strnlen(loc, 2)) { - locales[id] = locales_menu[idx].description = BLI_strdup(""); - long_locales[id] = BLI_strdup(""); - } - /* Menu "label", not to be stored in locales! */ - else { - locales_menu[idx].description = BLI_strdup(""); - } - } - else { - locales[id] = locales_menu[idx].description = BLI_strdup(loc); - long_locales[id] = BLI_strdup(sep3 + 1); - } - idx++; } + else { + locales_menu[idx].identifier = loc = BLI_strdup(sep2); + } + + if (id == 0) { + /* The DEFAULT item... */ + if (BLI_strnlen(loc, 2)) { + locales[id] = locales_menu[idx].description = BLI_strdup(""); + } + /* Menu "label", not to be stored in locales! */ + else { + locales_menu[idx].description = BLI_strdup(""); + } + } + else { + locales[id] = locales_menu[idx].description = BLI_strdup(loc); + } + idx++; } } @@ -207,15 +186,12 @@ void BLF_lang_init(void) { char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale"); - BLI_strncpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT, sizeof(global_encoding_name)); - if (messagepath) { - BLI_strncpy(global_messagepath, messagepath, sizeof(global_messagepath)); + bl_locale_init(messagepath, TEXT_DOMAIN_NAME); fill_locales(); } else { printf("%s: 'locale' data path for translations not found, continuing\n", __func__); - global_messagepath[0] = '\0'; } } @@ -224,159 +200,37 @@ void BLF_lang_free(void) free_locales(); } -/* Get LANG/LANGUAGE environment variable. */ -static void get_language_variable(const char *varname, char *var, const size_t maxlen) -{ - char *env = getenv(varname); - - if (env) { - char *s; - - /* Store defaul locale. */ - BLI_strncpy(var, env, maxlen); - - /* Use first language as default. */ - s = strchr(var, ':'); - if (s) - s[0] = 0; - } -} - -/* Get language to be used based on locale (which might be empty when using default language) and - * LANG environment variable. - */ -static void get_language(const char *locale, const char *lang, char *language, const size_t maxlen) -{ - if (locale[0]) { - BLI_strncpy(language, locale, maxlen); - } - else { - char *s; - - BLI_strncpy(language, lang, maxlen); - - s = strchr(language, '.'); - if (s) - s[0] = 0; - } -} - -/* XXX WARNING!!! In osx somehow the previous function call jumps in this one??? (ton, ppc) */ void BLF_lang_set(const char *str) { - char *locreturn; - int ok = TRUE; int ulang = ULANGUAGE; + const char *short_locale = str ? str : LOCALE(ulang); + const char *short_locale_utf8 = NULL; if ((U.transopts & USER_DOTRANSLATE) == 0) return; -#if defined(_WIN32) && !defined(FREE_WINDOWS) - { - const char *long_locale = str ? str : LONG_LOCALE(ulang); - if (long_locale) { - char *envStr; - - if (ulang) - envStr = BLI_sprintfN("LANG=%s", long_locale); - else /* Use system setting. */ - envStr = BLI_sprintfN("LANG=%s", getenv("LANG")); - - gettext_putenv(envStr); - MEM_freeN(envStr); - } - - locreturn = setlocale(LC_ALL, long_locale); - - if (locreturn == NULL) { - if (G.debug & G_DEBUG) - printf("Could not change locale to %s\n", long_locale); - - ok = FALSE; - } - } -#else - { - const char *short_locale = str ? str : LOCALE(ulang); - static char default_lang[64] = "\0"; - static char default_language[64] = "\0"; - - if (default_lang[0] == 0) - get_language_variable("LANG", default_lang, sizeof(default_lang)); - - if (default_language[0] == 0) - get_language_variable("LANGUAGE", default_language, sizeof(default_language)); - - if (short_locale[0]) { - char *short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); - - if (G.debug & G_DEBUG) - printf("Setting LANG and LANGUAGE to %s\n", short_locale_utf8); - - locreturn = setlocale(LC_ALL, short_locale_utf8); - - if (locreturn != NULL) { - BLI_setenv("LANG", short_locale_utf8); - BLI_setenv("LANGUAGE", short_locale_utf8); - } - else { - if (G.debug & G_DEBUG) - printf("Setting LANG and LANGUAGE to %s\n", short_locale); - - locreturn = setlocale(LC_ALL, short_locale); - - if (locreturn != NULL) { - BLI_setenv("LANG", short_locale); - BLI_setenv("LANGUAGE", short_locale); - } - } - - if (G.debug & G_DEBUG && locreturn == NULL) - printf("Could not change locale to %s nor %s\n", short_locale, short_locale_utf8); - - MEM_freeN(short_locale_utf8); + /* We want to avoid locales like '.UTF-8'! */ + if (short_locale[0]) { + /* Hurrey! encoding needs to be placed *before* variant! */ + char *variant = strchr(short_locale, '@'); + if (variant) { + char *locale = BLI_strdupn(short_locale, variant - short_locale); + short_locale_utf8 = BLI_sprintfN("%s.UTF-8%s", locale, variant); + MEM_freeN(locale); } else { - if (G.debug & G_DEBUG) - printf("Setting LANG=%s and LANGUAGE=%s\n", default_lang, default_language); - - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", default_language); - locreturn = setlocale(LC_ALL, ""); - - if (G.debug & G_DEBUG && locreturn == NULL) - printf("Could not reset locale\n"); - } - - if (locreturn == NULL) { - char language[65]; - - get_language(short_locale, default_lang, language, sizeof(language)); - - if (G.debug & G_DEBUG) - printf("Fallback to LANG=%s and LANGUAGE=%s\n", default_lang, language); - - /* Fallback to default settings. */ - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", language); - - locreturn = setlocale(LC_ALL, ""); - - ok = FALSE; + short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); } } -#endif - - if (ok) { - /*printf("Change locale to %s\n", locreturn ); */ - BLI_strncpy(global_language, locreturn, sizeof(global_language)); + else { + short_locale_utf8 = short_locale; } - setlocale(LC_NUMERIC, "C"); + bl_locale_set(short_locale_utf8); - textdomain(TEXT_DOMAIN_NAME); - bindtextdomain(TEXT_DOMAIN_NAME, global_messagepath); - bind_textdomain_codeset(TEXT_DOMAIN_NAME, global_encoding_name); + if (short_locale[0]) { + MEM_freeN((void*)short_locale_utf8); + } } const char *BLF_lang_get(void) @@ -385,12 +239,6 @@ const char *BLF_lang_get(void) return LOCALE(uilang); } -void BLF_lang_encoding(const char *str) -{ - BLI_strncpy(global_encoding_name, str, sizeof(global_encoding_name)); - /* bind_textdomain_codeset(TEXT_DOMAIN_NAME, encoding_name); */ -} - #undef LOCALE #undef ULANGUAGE @@ -406,12 +254,6 @@ void BLF_lang_free(void) return; } -void BLF_lang_encoding(const char *str) -{ - (void)str; - return; -} - void BLF_lang_set(const char *str) { (void)str; diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c index 9c863da9eba..5d4b631688a 100644 --- a/source/blender/blenfont/intern/blf_translation.c +++ b/source/blender/blenfont/intern/blf_translation.c @@ -31,18 +31,11 @@ #include #include +#include "BLF_translation.h" + #ifdef WITH_INTERNATIONAL -#include -#include -#define GETTEXT_CONTEXT_GLUE "\004" - -/* needed for windows version of gettext */ -#ifndef LC_MESSAGES -# define LC_MESSAGES 1729 -#endif - -#endif +#include "boost_locale_wrapper.h" #include "MEM_guardedalloc.h" @@ -52,11 +45,8 @@ #include "BLI_path_util.h" #include "BLI_fileops.h" -#include "BLF_translation.h" - #include "DNA_userdef_types.h" /* For user settings. */ -#ifdef WITH_INTERNATIONAL static const char unifont_filename[] = "droidsans.ttf.gz"; static unsigned char *unifont_ttf = NULL; static int unifont_size = 0; @@ -90,55 +80,19 @@ void BLF_free_unifont(void) #endif -const char *BLF_gettext(const char *msgid) +const char *BLF_pgettext(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL - if (msgid && msgid[0]) - return gettext(msgid); + if (msgid && msgid[0]) { + return bl_locale_pgettext(msgctxt, msgid); + } return ""; #else + (void)msgctxt; return msgid; #endif } -const char *BLF_pgettext(const char *context, const char *message) -{ -#ifdef WITH_INTERNATIONAL - char static_msg_ctxt_id[1024]; - char *dynamic_msg_ctxt_id = NULL; - char *msg_ctxt_id; - const char *translation; - - size_t overall_length = strlen(context) + strlen(message) + sizeof(GETTEXT_CONTEXT_GLUE) + 1; - - if (!message || !context || !message[0]) - return ""; - - if (overall_length > sizeof(static_msg_ctxt_id)) { - dynamic_msg_ctxt_id = malloc(overall_length); - msg_ctxt_id = dynamic_msg_ctxt_id; - } - else { - msg_ctxt_id = static_msg_ctxt_id; - } - - sprintf(msg_ctxt_id, "%s%s%s", context, GETTEXT_CONTEXT_GLUE, message); - - translation = (char *)dcgettext(TEXT_DOMAIN_NAME, msg_ctxt_id, LC_MESSAGES); - - if (dynamic_msg_ctxt_id) - free(dynamic_msg_ctxt_id); - - if (translation == msg_ctxt_id) - translation = message; - - return translation; -#else - (void)context; - return message; -#endif -} - int BLF_translate_iface(void) { #ifdef WITH_INTERNATIONAL @@ -157,36 +111,32 @@ int BLF_translate_tooltips(void) #endif } -const char *BLF_translate_do_iface(const char *context, const char *msgid) +const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (BLF_translate_iface()) { - if (context) - return BLF_pgettext(context, msgid); - else - return BLF_gettext(msgid); + return BLF_pgettext(msgctxt, msgid); } - else + else { return msgid; + } #else - (void)context; + (void)msgctxt; return msgid; #endif } -const char *BLF_translate_do_tooltip(const char *context, const char *msgid) +const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (BLF_translate_tooltips()) { - if (context) - return BLF_pgettext(context, msgid); - else - return BLF_gettext(msgid); + return BLF_pgettext(msgctxt, msgid); } - else + else { return msgid; + } #else - (void)context; + (void)msgctxt; return msgid; #endif } diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index c6c54cc6e8a..617c4cd2bc8 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -709,10 +709,16 @@ void DM_debug_print(DerivedMesh *dm); void DM_debug_print_cdlayers(CustomData *cdata); #endif +#ifdef __GNUC__ +BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) + __attribute__((nonnull(1))) +; +#endif + BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) { const int j = index_mf_to_mpoly[i]; - return (j != ORIGINDEX_NONE) ? index_mp_to_orig[j] : ORIGINDEX_NONE; + return (j != ORIGINDEX_NONE) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : ORIGINDEX_NONE; } #endif diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 87e87904fe7..b624d0f9c3a 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,8 +41,8 @@ extern "C" { /* these lines are grep'd, watch out for our not-so-awesome regex * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ -#define BLENDER_VERSION 264 -#define BLENDER_SUBVERSION 7 +#define BLENDER_VERSION 265 +#define BLENDER_SUBVERSION 0 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 @@ -50,9 +50,9 @@ extern "C" { /* used by packaging tools */ /* can be left blank, otherwise a,b,c... etc with no quotes */ -#define BLENDER_VERSION_CHAR a +#define BLENDER_VERSION_CHAR /* alpha/beta/rc/release, docs use this */ -#define BLENDER_VERSION_CYCLE alpha +#define BLENDER_VERSION_CYCLE release extern char versionstr[]; /* from blender.c */ diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index f7af534c2c2..f6276a69d57 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -167,6 +167,9 @@ enum { #define G_FILE_RELATIVE_REMAP (1 << 24) #define G_FILE_HISTORY (1 << 25) #define G_FILE_MESH_COMPAT (1 << 26) /* BMesh option to save as older mesh format */ +#define G_FILE_SAVE_COPY (1 << 27) /* restore paths after editing them */ + +#define G_FILE_FLAGS_RUNTIME (G_FILE_NO_UI | G_FILE_RELATIVE_REMAP | G_FILE_MESH_COMPAT | G_FILE_SAVE_COPY) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index ebfbe94802a..9af0d96884a 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -30,9 +30,7 @@ /** \file BKE_icons.h * \ingroup bke - */ - -/* + * * Resizable Icons for Blender */ diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 1875fd66628..1f9630d9fce 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -48,6 +48,9 @@ struct Main; #define IMA_MAX_SPACE 64 +void BKE_images_init(void); +void BKE_images_exit(void); + /* call from library */ void BKE_image_free(struct Image *me); @@ -133,14 +136,13 @@ enum { #define IMA_CHAN_FLAG_RGB 2 #define IMA_CHAN_FLAG_ALPHA 4 -/* depending Image type, and (optional) ImageUser setting it returns ibuf */ -/* always call to make signals work */ -struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser); +/* checks whether there's an image buffer for given image and user */ +int BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser); /* same as above, but can be used to retrieve images being rendered in * a thread safe way, always call both acquire and release */ struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r); -void BKE_image_release_ibuf(struct Image *ima, void *lock); +void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock); /* returns a new image or NULL if it can't load */ struct Image *BKE_image_load(const char *filepath); diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 3acd4d1986e..244decf9d52 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -37,6 +37,7 @@ extern "C" { #endif struct Lamp; +struct Scene; struct Lamp *BKE_lamp_add(const char *name) WARN_UNUSED; struct Lamp *BKE_lamp_copy(struct Lamp *la) WARN_UNUSED; @@ -44,6 +45,8 @@ struct Lamp *localize_lamp(struct Lamp *la) WARN_UNUSED; void BKE_lamp_make_local(struct Lamp *la); void BKE_lamp_free(struct Lamp *la); +void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 2f889084d0e..e53d0efffbd 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -283,9 +283,9 @@ typedef struct IndexNode { void create_vert_poly_map(MeshElemMap **map, int **mem, const struct MPoly *mface, const struct MLoop *mloop, int totvert, int totface, int totloop); - + void create_vert_edge_map(MeshElemMap **map, int **mem, - const struct MEdge *medge, int totvert, int totedge); + const struct MEdge *medge, int totvert, int totedge); /* vertex level transformations & checks (no derived mesh) */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 7ee1c85d0de..2fa78b30835 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -319,8 +319,8 @@ int modifier_dependsOnTime(struct ModifierData *md); int modifier_supportsMapping(struct ModifierData *md); int modifier_couldBeCage(struct Scene *scene, struct ModifierData *md); int modifier_isCorrectableDeformed(struct ModifierData *md); -int modifier_sameTopology(ModifierData *md); -int modifier_nonGeometrical(ModifierData *md); +int modifier_isSameTopology(ModifierData *md); +int modifier_isNonGeometrical(ModifierData *md); int modifier_isEnabled(struct Scene *scene, struct ModifierData *md, int required_mode); void modifier_setError(struct ModifierData *md, const char *format, ...) #ifdef __GNUC__ diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 8fa20eb2cc2..bee2c374f27 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -48,7 +48,7 @@ struct Scene; void multires_customdata_delete(struct Mesh *me); void multires_set_tot_level(struct Object *ob, - struct MultiresModifierData *mmd, int lvl); + struct MultiresModifierData *mmd, int lvl); void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 29e03f66bcc..b8f168cbdea 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -34,8 +34,6 @@ #include "DNA_listBase.h" -#include "RNA_types.h" - /* not very important, but the stack solver likes to know a maximum */ #define MAX_SOCKET 64 @@ -82,7 +80,7 @@ typedef struct bNodeSocketTemplate { char name[64]; /* MAX_NAME */ float val1, val2, val3, val4; /* default alloc value for inputs */ float min, max; - PropertySubType subtype; + int subtype; /* would use PropertySubType but this is a bad level include to use RNA */ int flag; /* after this line is used internal only */ @@ -316,6 +314,8 @@ void ntreeUserIncrefID(struct bNodeTree *ntree); void ntreeUserDecrefID(struct bNodeTree *ntree); +struct bNodeTree *ntreeFromID(struct ID *id); + void ntreeMakeLocal(struct bNodeTree *ntree); int ntreeHasType(struct bNodeTree *ntree, int type); void ntreeUpdateTree(struct bNodeTree *ntree); @@ -553,6 +553,10 @@ struct ShadeResult; #define SH_NODE_TEX_BRICK 169 #define SH_NODE_BUMP 170 #define SH_NODE_SCRIPT 171 +#define SH_NODE_AMBIENT_OCCLUSION 172 +#define SH_NODE_BSDF_REFRACTION 173 +#define SH_NODE_TANGENT 174 +#define SH_NODE_NORMAL_MAP 175 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 @@ -702,6 +706,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria #define CMP_NODE_SWITCH 317 #define CMP_NODE_PIXELATE 318 +#define CMP_NODE_MAP_RANGE 319 + /* channel toggles */ #define CMP_CHAN_RGB 1 #define CMP_CHAN_A 2 diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index ba611817c8f..88294cb30b6 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -248,7 +248,7 @@ void BKE_sequencer_cache_cleanup(void); struct ImBuf *BKE_sequencer_cache_get(SeqRenderData context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type); /* passed ImBuf is properly refed, so ownership is *not* - * transfered to the cache. + * transferred to the cache. * you can pass the same ImBuf multiple times to the cache without problems. */ diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 875903f2e20..accac8694a9 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -83,7 +83,7 @@ void txt_sel_line (struct Text *text); char* txt_sel_to_buf (struct Text *text); void txt_insert_buf (struct Text *text, const char *in_buffer); void txt_print_undo (struct Text *text); -void txt_undo_add_toop (struct Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc); +void txt_undo_add_op (struct Text *text, int op); void txt_do_undo (struct Text *text); void txt_do_redo (struct Text *text); void txt_split_curline (struct Text *text); @@ -100,14 +100,6 @@ void txt_move_lines (struct Text *text, const int direction); void txt_duplicate_line (struct Text *text); int setcurr_tab_spaces (struct Text *text, int space); -void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, const unsigned char color[4], int group, int flags); -short txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); -short txt_clear_markers (struct Text *text, int group, int flags); -struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int group, int flags); -struct TextMarker *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); -struct TextMarker *txt_prev_marker (struct Text *text, struct TextMarker *marker); -struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marker); - /* utility functions, could be moved somewhere more generic but are python/text related */ int text_check_bracket(const char ch); int text_check_delim(const char ch); @@ -123,24 +115,6 @@ enum { /* Undo opcodes */ -/* Simple main cursor movement */ -#define UNDO_CLEFT 001 -#define UNDO_CRIGHT 002 -#define UNDO_CUP 003 -#define UNDO_CDOWN 004 - -/* Simple selection cursor movement */ -#define UNDO_SLEFT 005 -#define UNDO_SRIGHT 006 -#define UNDO_SUP 007 -#define UNDO_SDOWN 010 - -/* Complex movement (opcode is followed - * by 4 character line ID + a 2 character - * position ID and opcode (repeat)) */ -#define UNDO_CTO 011 -#define UNDO_STO 012 - /* Complex editing */ /* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */ /* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */ @@ -169,8 +143,6 @@ enum { #define UNDO_IBLOCK 030 /* Insert block */ /* Misc */ -#define UNDO_SWAP 031 /* Swap cursors */ - #define UNDO_INDENT 032 #define UNDO_UNINDENT 033 #define UNDO_COMMENT 034 @@ -181,10 +153,6 @@ enum { #define UNDO_DUPLICATE 040 -/* Marker flags */ -#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */ -#define TMARK_EDITALL 0x02 /* Edit all markers of the same group as one */ - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 06f8b89ec05..7c1e0e97565 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -32,7 +32,11 @@ extern "C" { #endif -/* currently unused but we may want to add macros here for BKE later */ +#define BKE_BIT_TEST_SET(value, test, flag) \ +{ \ + if (test) (value) |= flag; \ + else (value) &= ~flag; \ +} (void)0 #ifdef __cplusplus } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index c5dc7da8edf..2da9b402d59 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -255,13 +255,13 @@ if(WITH_BULLET) add_definitions(-DUSE_BULLET) endif() -if(WITH_MOD_CLOTH_ELTOPO) - list(APPEND INC - ../../../extern/eltopo - ../../../extern/eltopo/eltopo3d - ) - add_definitions(-DWITH_ELTOPO) -endif() +#if(WITH_MOD_CLOTH_ELTOPO) +# list(APPEND INC +# ../../../extern/eltopo +# ../../../extern/eltopo/eltopo3d +# ) +# add_definitions(-DWITH_ELTOPO) +#endif() if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index f7b8f59fa57..22be2f78ea7 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -4,6 +4,7 @@ import os sources = env.Glob('intern/*.c') sources.remove('intern' + os.sep + 'mask_rasterize.c') +sources.remove('intern' + os.sep + 'mask_evaluate.c') sources.remove('intern' + os.sep + 'mask.c') sources_mask = env.Glob('intern/mask*.c') @@ -40,11 +41,12 @@ if env['WITH_BF_PYTHON']: if env['BF_DEBUG']: defs.append('DEBUG') +''' if env['WITH_BF_ELTOPO']: incs += ' #/extern/eltopo' incs += ' #/extern/eltopo/eltopo3d' defs.append('WITH_ELTOPO') - +''' if env['WITH_BF_QUICKTIME']: incs += ' ../quicktime' diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index fd92b7b5d69..d09bea0f662 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -392,7 +392,7 @@ void DM_ensure_tessface(DerivedMesh *dm) } else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) { - BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX)); + BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX) || numTessFaces == 0); DM_update_tessface_data(dm); } @@ -1159,120 +1159,65 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, ColorBand *coba = stored_cb; /* warning, not a local var */ unsigned char *wtcol_v; -#if 0 /* See coment below. */ - unsigned char *wtcol_f = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); -#endif unsigned char(*wtcol_l)[4] = CustomData_get_layer(dm->getLoopDataLayout(dm), CD_PREVIEW_MLOOPCOL); -#if 0 /* See coment below. */ - MFace *mf = dm->getTessFaceArray(dm); -#endif MLoop *mloop = dm->getLoopArray(dm), *ml; MPoly *mp = dm->getPolyArray(dm); -#if 0 - int numFaces = dm->getNumTessFaces(dm); -#endif int numVerts = dm->getNumVerts(dm); int totloop; int i, j; -#if 0 /* See comment below */ - /* If no CD_PREVIEW_MCOL existed yet, add a new one! */ - if (!wtcol_f) - wtcol_f = CustomData_add_layer(&dm->faceData, CD_PREVIEW_MCOL, CD_CALLOC, NULL, numFaces); - - if (wtcol_f) { - unsigned char *wtcol_f_step = wtcol_f; -# else -#if 0 - /* XXX We have to create a CD_PREVIEW_MCOL, else it might sigsev (after a SubSurf mod, eg)... */ - if (!dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL)) - CustomData_add_layer(&dm->faceData, CD_PREVIEW_MCOL, CD_CALLOC, NULL, numFaces); -#endif - - { -#endif - - /* Weights are given by caller. */ - if (weights) { - float *w = weights; - /* If indices is not NULL, it means we do not have weights for all vertices, - * so we must create them (and set them to zero)... */ - if (indices) { - w = MEM_callocN(sizeof(float) * numVerts, "Temp weight array DM_update_weight_mcol"); - i = num; - while (i--) - w[indices[i]] = weights[i]; - } - - /* Convert float weights to colors. */ - wtcol_v = calc_colors_from_weights_array(numVerts, w); - - if (indices) - MEM_freeN(w); + /* Weights are given by caller. */ + if (weights) { + float *w = weights; + /* If indices is not NULL, it means we do not have weights for all vertices, + * so we must create them (and set them to zero)... */ + if (indices) { + w = MEM_callocN(sizeof(float) * numVerts, "Temp weight array DM_update_weight_mcol"); + i = num; + while (i--) + w[indices[i]] = weights[i]; } - /* No weights given, take them from active vgroup(s). */ - else - wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba); + /* Convert float weights to colors. */ + wtcol_v = calc_colors_from_weights_array(numVerts, w); - /* Now copy colors in all face verts. */ - /* first add colors to the tessellation faces */ - /* XXX Why update that layer? We have to update WEIGHT_MLOOPCOL anyway, - * and tessellation recreates mface layers from mloop/mpoly ones, so no - * need to fill WEIGHT_MCOL here. */ -#if 0 - for (i = 0; i < numFaces; i++, mf++, wtcol_f_step += (4 * 4)) { - /*origindex being NULL means we're operating on original mesh data*/ -#if 0 - unsigned int fidx = mf->v4 ? 3 : 2; - -#else /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */ - unsigned int fidx; - if (mf->v4) { - fidx = 3; - } - else { - fidx = 2; - *(int *)(&wtcol_f_step[3 * 4]) = 0; - } -#endif - - do { - copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4], - (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); - } while (fidx--); - } -#endif - /*now add to loops, so the data can be passed through the modifier stack*/ - /* If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */ - if (!wtcol_l) { - BLI_array_declare(wtcol_l); - totloop = 0; - for (i = 0; i < dm->numPolyData; i++, mp++) { - ml = mloop + mp->loopstart; - - BLI_array_grow_items(wtcol_l, mp->totloop); - for (j = 0; j < mp->totloop; j++, ml++, totloop++) { - copy_v4_v4_char((char *)&wtcol_l[totloop], - (char *)&wtcol_v[4 * ml->v]); - } - } - CustomData_add_layer(&dm->loopData, CD_PREVIEW_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop); - } - else { - totloop = 0; - for (i = 0; i < dm->numPolyData; i++, mp++) { - ml = mloop + mp->loopstart; - - for (j = 0; j < mp->totloop; j++, ml++, totloop++) { - copy_v4_v4_char((char *)&wtcol_l[totloop], - (char *)&wtcol_v[4 * ml->v]); - } - } - } - MEM_freeN(wtcol_v); + if (indices) + MEM_freeN(w); } + /* No weights given, take them from active vgroup(s). */ + else + wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba); + + /* now add to loops, so the data can be passed through the modifier stack */ + /* If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */ + if (!wtcol_l) { + BLI_array_declare(wtcol_l); + totloop = 0; + for (i = 0; i < dm->numPolyData; i++, mp++) { + ml = mloop + mp->loopstart; + + BLI_array_grow_items(wtcol_l, mp->totloop); + for (j = 0; j < mp->totloop; j++, ml++, totloop++) { + copy_v4_v4_char((char *)&wtcol_l[totloop], + (char *)&wtcol_v[4 * ml->v]); + } + } + CustomData_add_layer(&dm->loopData, CD_PREVIEW_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop); + } + else { + totloop = 0; + for (i = 0; i < dm->numPolyData; i++, mp++) { + ml = mloop + mp->loopstart; + + for (j = 0; j < mp->totloop; j++, ml++, totloop++) { + copy_v4_v4_char((char *)&wtcol_l[totloop], + (char *)&wtcol_v[4 * ml->v]); + } + } + } + MEM_freeN(wtcol_v); + dm->dirty |= DM_DIRTY_TESS_CDLAYERS; } @@ -1680,8 +1625,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos nextmask &= ~CD_MASK_ORCO; DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX | - (mti->requiredDataMask ? - mti->requiredDataMask(ob, md) : 0)); + (mti->requiredDataMask ? + mti->requiredDataMask(ob, md) : 0)); ndm = mti->applyModifier(md, ob, orcodm, app_flags & ~MOD_APPLY_USECACHE); if (ndm) { @@ -2167,6 +2112,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask, /* weight paint and face select need original indices because of selection buffer drawing */ int needMapping = (ob == obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT))); + BLI_assert(ob->type == OB_MESH); + clear_mesh_caches(ob); mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform, diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index e95451252d0..dd27cc70ba3 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -512,7 +512,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose) { if (pose) { switch (pose->iksolver) { - case IKSOLVER_LEGACY: + case IKSOLVER_STANDARD: return NULL; case IKSOLVER_ITASC: return "bItasc"; @@ -587,7 +587,7 @@ void BKE_pose_ikparam_init(bPose *pose) BKE_pose_itasc_init(itasc); pose->ikparam = itasc; break; - case IKSOLVER_LEGACY: + case IKSOLVER_STANDARD: default: pose->ikparam = NULL; break; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index dffe26bd782..9a2462e9724 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -76,8 +76,8 @@ /* --------------------- */ /* forward declarations */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, - int level, short flag); +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], + int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag); /* ******************************************************************** */ /* Animation Visualization */ @@ -706,31 +706,45 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua #define DUPLILIST_FOR_RENDER 2 #define DUPLILIST_ANIMATED 4 -static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short flag) +static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, + int persistent_id[MAX_DUPLI_RECUR], int level, int index, int type, short flag) { DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject"); - + int i; + BLI_addtail(lb, dob); dob->ob = ob; copy_m4_m4(dob->mat, mat); copy_m4_m4(dob->omat, ob->obmat); dob->origlay = ob->lay; - dob->index = index; - dob->particle_index = par_index; dob->type = type; dob->animated = (type == OB_DUPLIGROUP) && (flag & DUPLILIST_ANIMATED); ob->lay = lay; + + /* set persistent id, which is an array with a persistent index for each level + * (particle number, vertex number, ..). by comparing this we can find the same + * dupli object between frames, which is needed for motion blur. last level + * goes first in the array. */ + dob->persistent_id[0] = index; + for (i = 1; i < level; i++) + dob->persistent_id[i] = persistent_id[level - 1 - i]; + + /* metaballs never draw in duplis, they are instead merged into one by the basis + * mball outside of the group. this does mean that if that mball is not in the + * scene, they will not show up at all, limitation that should be solved once. */ + if (ob->type == OB_MBALL) + dob->no_draw = TRUE; return dob; } -static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, +static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { DupliObject *dob; Group *group; GroupObject *go; - float mat[4][4], tmat[4][4]; + float mat[4][4], tmat[4][4], id; if (ob->dup_group == NULL) return; group = ob->dup_group; @@ -750,7 +764,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (group_is_animated(ob, group)) flag |= DUPLILIST_ANIMATED; - for (go = group->gobject.first; go; go = go->next) { + for (go = group->gobject.first, id = 0; go; go = go->next, id++) { /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if (go->ob != ob) { @@ -764,7 +778,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } - dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, flag); + dob = new_dupli_object(lb, go->ob, mat, ob->lay, persistent_id, level, id, OB_DUPLIGROUP, flag); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ((dob->origlay & group->layer) == 0 || @@ -773,20 +787,17 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde { dob->no_draw = TRUE; } - else { - dob->no_draw = FALSE; - } if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); - object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, flag); + object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, persistent_id, level + 1, id, flag); copy_m4_m4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short flag) +static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { extern int enable_cu_speed; /* object.c */ Object copyob; @@ -834,7 +845,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); - dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, flag); + dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, persistent_id, level, scene->r.cfra, OB_DUPLIFRAMES, flag); copy_m4_m4(dob->omat, copyob.obmat); } } @@ -865,7 +876,7 @@ typedef struct VertexDupliData { Scene *scene; Object *ob, *par; float (*orco)[3]; - int par_index; + int *persistent_id; } VertexDupliData; /* ------------- */ @@ -902,7 +913,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], origlay = vdd->ob->lay; - dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->flag); + dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, vdd->persistent_id, vdd->level, index, OB_DUPLIVERTS, vdd->flag); /* restore the original layer so that each dupli will have proper dob->origlay */ vdd->ob->lay = origlay; @@ -914,12 +925,12 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], float tmpmat[4][4]; copy_m4_m4(tmpmat, vdd->ob->obmat); copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->flag); + object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->persistent_id, vdd->level + 1, index, vdd->flag); copy_m4_m4(vdd->ob->obmat, tmpmat); } } -static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, +static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *ob_iter; @@ -1004,7 +1015,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl vdd.scene = scene; vdd.par = par; copy_m4_m4(vdd.pmat, pmat); - vdd.par_index = par_index; + vdd.persistent_id = persistent_id; /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ @@ -1043,7 +1054,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl dm->release(dm); } -static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, +static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *ob_iter; @@ -1186,7 +1197,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_m4_m4(tmat, obmat); mul_m4_m4m3(obmat, tmat, mat); - dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); if (flag & DUPLILIST_FOR_RENDER) { w = 1.0f / (float)mp->totloop; @@ -1209,7 +1220,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float tmpmat[4][4]; copy_m4_m4(tmpmat, ob->obmat); copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, flag); + object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, persistent_id, level + 1, a, flag); copy_m4_m4(ob->obmat, tmpmat); } } @@ -1229,7 +1240,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, +static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], ParticleSystem *psys, int level, short flag) { GroupObject *go; @@ -1244,8 +1255,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0; float (*obmat)[4], (*oldobmat)[4]; - int a, b, counter, index, hair = 0; + int a, b, hair = 0; int totpart, totchild, totgroup = 0 /*, pa_num */; + int dupli_type_hack = !BKE_scene_use_new_shading_nodes(scene); int no_draw_flag = PARS_UNEXIST; @@ -1360,8 +1372,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else a = totpart; - index = 0; - for (pa = psys->particles, counter = 0; a < totpart + totchild; a++, pa++, counter++) { + for (pa = psys->particles; a < totpart + totchild; a++, pa++) { if (a < totpart) { /* handle parent particle */ if (pa->flag & no_draw_flag) @@ -1456,13 +1467,21 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else copy_m4_m4(mat, tmat); - dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, go->ob, mat, par->lay, persistent_id, level, a, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob->particle_system = psys; copy_m4_m4(dob->omat, obcopylist[b].obmat); if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { + int dupli_type = OB_DUPLIPARTS; + + /* blender internal needs this to be set to dupligroup to render + * groups correctly, but we don't want this hack for cycles */ + if(dupli_type_hack && GS(id->name) == ID_GR) + dupli_type = OB_DUPLIGROUP; + /* to give ipos in object correct offset */ BKE_object_where_is_calc_time(scene, ob, ctime - pa_time); @@ -1516,14 +1535,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, ob, mat, ob->lay, persistent_id, level, a, dupli_type, (flag & DUPLILIST_ANIMATED)); + dob->particle_system = psys; copy_m4_m4(dob->omat, oldobmat); if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } - - /* only counts visible particles */ - index++; } /* restore objects since they were changed in BKE_object_where_is_calc_time */ @@ -1570,7 +1587,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) } -static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short flag) +static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *obar[256] = {NULL}; Curve *cu; @@ -1609,7 +1626,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde copy_m4_m4(obmat, par->obmat); copy_v3_v3(obmat[3], vec); - new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, flag); + new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIVERTS, flag); } } @@ -1618,8 +1635,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde /* ------------- */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, - int level, short flag) +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], + int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag) { if ((ob->transflag & OB_DUPLI) == 0) return; @@ -1636,34 +1653,45 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas } } + /* keep track of persistent id */ + if (level > 0) + persistent_id[level - 1] = index; + if (ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; - for (; psys; psys = psys->next) - new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, flag); + int psysid = 0; + + /* particle system take up one level in id, the particles another */ + for (; psys; psys = psys->next, psysid++) { + persistent_id[level] = psysid; + new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, psys, level + 2, flag); + } + + persistent_id[level] = 0; } else if (ob->transflag & OB_DUPLIVERTS) { if (ob->type == OB_MESH) { - vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); + vertex_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag); } else if (ob->type == OB_FONT) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - font_duplilist(duplilist, scene, ob, par_index, level + 1, flag); + font_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); } } } else if (ob->transflag & OB_DUPLIFACES) { if (ob->type == OB_MESH) - face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); + face_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag); } else if (ob->transflag & OB_DUPLIFRAMES) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - frames_duplilist(duplilist, scene, ob, par_index, level + 1, flag); + frames_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); } } else if (ob->transflag & OB_DUPLIGROUP) { DupliObject *dob; - group_duplilist(duplilist, scene, ob, par_index, level + 1, flag); /* now recursive */ + group_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); /* now recursive */ if (level == 0) { for (dob = duplilist->first; dob; dob = dob->next) @@ -1671,6 +1699,10 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas copy_m4_m4(dob->ob->obmat, dob->mat); } } + + /* clear persistent id */ + if (level > 0) + persistent_id[level - 1] = 0; } /* Returns a list of DupliObject @@ -1678,13 +1710,14 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render) { ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist"); + int persistent_id[MAX_DUPLI_RECUR] = {0}; int flag = 0; if (update) flag |= DUPLILIST_DO_UPDATE; if (for_render) flag |= DUPLILIST_FOR_RENDER; duplilist->first = duplilist->last = NULL; - object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, flag); + object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, persistent_id, 0, 0, flag); return duplilist; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 66ed31c5b72..40b883e3f4e 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -781,7 +781,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex); /* lamps */ - ANIMDATA_IDS_CB(mainptr->lamp.first); + ANIMDATA_NODETREE_IDS_CB(mainptr->lamp.first, Lamp); /* materials */ ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material); @@ -823,7 +823,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u ANIMDATA_IDS_CB(mainptr->mask.first); /* worlds */ - ANIMDATA_IDS_CB(mainptr->world.first); + ANIMDATA_NODETREE_IDS_CB(mainptr->world.first, World); /* scenes */ ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); @@ -868,7 +868,7 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex); /* lamps */ - RENAMEFIX_ANIM_IDS(mainptr->lamp.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->lamp.first, Lamp); /* materials */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material); @@ -910,7 +910,7 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha RENAMEFIX_ANIM_IDS(mainptr->mask.first); /* worlds */ - RENAMEFIX_ANIM_IDS(mainptr->world.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->world.first, World); /* scenes */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); @@ -973,9 +973,8 @@ KeyingSet *BKE_keyingset_add(ListBase *list, const char idname[], const char nam /* allocate new KeyingSet */ ks = MEM_callocN(sizeof(KeyingSet), "KeyingSet"); - BLI_strncpy(ks->idname, idname ? idname : name ? name : "KeyingSet", sizeof(ks->idname)); - - BLI_strncpy(ks->name, name ? name : idname ? idname : "Keying Set", sizeof(ks->name)); + BLI_strncpy(ks->idname, (idname) ? idname : (name) ? name : "KeyingSet", sizeof(ks->idname)); + BLI_strncpy(ks->name, (name) ? name : (idname) ? idname : "Keying Set", sizeof(ks->name)); ks->flag = flag; ks->keyingflag = keyingflag; @@ -983,10 +982,10 @@ KeyingSet *BKE_keyingset_add(ListBase *list, const char idname[], const char nam /* add KeyingSet to list */ BLI_addtail(list, ks); - /* Make sure KeyingSet has a unique idname. */ + /* Make sure KeyingSet has a unique idname */ BLI_uniquename(list, ks, "KeyingSet", '.', offsetof(KeyingSet, idname), sizeof(ks->idname)); - /* Make sure KeyingSet has a unique label (this helps with identification). */ + /* Make sure KeyingSet has a unique label (this helps with identification) */ BLI_uniquename(list, ks, "Keying Set", '.', offsetof(KeyingSet, name), sizeof(ks->name)); /* return new KeyingSet for further editing */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index b3cbc1f2b16..1970df54339 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1822,8 +1822,15 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos */ /* only happens on reload file, but violates depsgraph still... fix! */ - if ((cu->path == NULL) || (cu->path->data == NULL)) + if (ELEM(NULL, cu->path, cu->path->data)) { BKE_displist_make_curveTypes(scene, ikData->tar, 0); + + /* path building may fail in EditMode after removing verts [#33268]*/ + if (ELEM(NULL, cu->path, cu->path->data)) { + /* BLI_assert(cu->path != NULL); */ + return; + } + } } /* find the root bone and the chain of bones from the root to the tip diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index e1e868b234e..f0d201ea3f7 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -70,6 +70,7 @@ #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_library.h" #include "BKE_main.h" @@ -113,6 +114,7 @@ void free_blender(void) BKE_spacetypes_free(); /* after free main, it uses space callbacks */ IMB_exit(); + BKE_images_exit(); BLI_callback_global_finalize(); @@ -266,7 +268,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath G.winpos = bfd->winpos; G.displaymode = bfd->displaymode; G.fileflags = bfd->fileflags; - CTX_wm_manager_set(C, bfd->main->wm.first); + CTX_wm_manager_set(C, G.main->wm.first); CTX_wm_screen_set(C, bfd->curscreen); CTX_data_scene_set(C, bfd->curscreen->scene); CTX_wm_area_set(C, NULL); @@ -276,7 +278,11 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* this can happen when active scene was lib-linked, and doesn't exist anymore */ if (CTX_data_scene(C) == NULL) { - CTX_data_scene_set(C, bfd->main->scene.first); + /* in case we don't even have a local scene, add one */ + if (!G.main->scene.first) + BKE_scene_add("Scene"); + + CTX_data_scene_set(C, G.main->scene.first); CTX_wm_screen(C)->scene = CTX_data_scene(C); curscene = CTX_data_scene(C); } diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index df7fb2c1807..0495e729937 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -247,12 +247,13 @@ int locateGlyph(bmFont *bmfont, unsigned short unicode) return(current); } -void matrixGlyph(ImBuf * ibuf, unsigned short unicode, - float *centerx, float *centery, - float *sizex, float *sizey, - float *transx, float *transy, - float *movex, float *movey, - float *advance) +void matrixGlyph( + ImBuf * ibuf, unsigned short unicode, + float *centerx, float *centery, + float *sizex, float *sizey, + float *transx, float *transy, + float *movex, float *movey, + float *advance) { int index; bmFont *bmfont; diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 98b206712d6..f310895f590 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1287,8 +1287,6 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); - BKE_image_get_ibuf(mtex->tex->ima, NULL); - /*do normalized cannonical view coords for texture*/ for (y = -1.0, iy = 0; iy < side; iy++, y += step) { for (x = -1.0, ix = 0; ix < side; ix++, x += step) { diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 9118baeae6f..57c88919021 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -267,6 +267,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView params->clipsta = -params->clipend; params->is_ortho = TRUE; + /* make sure any changes to this match ED_view3d_radius_to_ortho_dist() */ params->ortho_scale = rv3d->dist * sensor_size / v3d->lens; params->zoom = 2.0f; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 2e0b3a3c64a..54bbe4bf495 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -623,8 +623,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } colType = CD_TEXTURE_MCOL; @@ -653,12 +653,29 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, else { if (index_mf_to_mpoly) { orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i); - if (orig == ORIGINDEX_NONE) { if (nors) nors += 3; continue; } - if (drawParamsMapped) { draw_option = drawParamsMapped(userData, orig); } - else { if (nors) nors += 3; continue; } + if (orig == ORIGINDEX_NONE) { + /* XXX, this is not really correct + * it will draw the previous faces context for this one when we don't know its settings. + * but better then skipping it altogether. - campbell */ + draw_option = DM_DRAW_OPTION_NORMAL; + } + else if (drawParamsMapped) { + draw_option = drawParamsMapped(userData, orig); + } + else { + if (nors) { + nors += 3; continue; + } + } + } + else if (drawParamsMapped) { + draw_option = drawParamsMapped(userData, i); + } + else { + if (nors) { + nors += 3; continue; + } } - else if (drawParamsMapped) { draw_option = drawParamsMapped(userData, i); } - else { if (nors) nors += 3; continue; } } if (draw_option != DM_DRAW_OPTION_SKIP) { @@ -742,9 +759,12 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, if (index_mf_to_mpoly) { orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace); if (orig == ORIGINDEX_NONE) { - continue; + /* XXX, this is not really correct + * it will draw the previous faces context for this one when we don't know its settings. + * but better then skipping it altogether. - campbell */ + draw_option = DM_DRAW_OPTION_NORMAL; } - if (drawParamsMapped) { + else if (drawParamsMapped) { draw_option = drawParamsMapped(userData, orig); } } @@ -812,8 +832,8 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } @@ -828,8 +848,6 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, mcol = DM_get_tessface_data_layer(dm, colType); } - printf("%s: %p(%d/%d)\n", __func__, mcol, CD_ID_MCOL, colType); - cdDM_update_normals_from_pbvh(dm); /* back-buffer always uses legacy since VBO's would need the @@ -1050,8 +1068,8 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } cdDM_update_normals_from_pbvh(dm); @@ -1351,8 +1369,8 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } cdDM_update_normals_from_pbvh(dm); @@ -1956,12 +1974,11 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps, /* avoid this where possiblem, takes extra memory */ if (use_tessface) { - int *polyindex; BM_mesh_elem_index_ensure(bm, BM_FACE); index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - for (i = 0; i < dm->numTessFaceData; i++, index++, polyindex++) { + for (i = 0; i < dm->numTessFaceData; i++, index++) { MFace *mf = &mface[i]; const BMLoop **l = em_looptris[i]; efa = l[0]->f; @@ -2257,6 +2274,11 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) * this is a really horribly written function. ger. - joeedh * * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. + * + * Note: This function is currently only used by the Mirror modifier, so it + * skips any faces that have all vertices merged (to avoid creating pairs + * of faces sharing the same set of vertices). If used elsewhere, it may + * be necessary to make this functionality optional. */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) { @@ -2300,14 +2322,11 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) newv[i] = newv[vtargetmap[i]]; } } - - /* find-replace merged vertices with target vertices */ - ml = cddm->mloop; - for (i = 0; i < totloop; i++, ml++) { - if (vtargetmap[ml->v] != -1) { - ml->v = vtargetmap[ml->v]; - } - } + + /* Don't remap vertices in cddm->mloop, because we need to know the original + * indices in order to skip faces with all vertices merged. + * The "update loop indices..." section further down remaps vertices in mloop. + */ /* now go through and fix edges and faces */ med = cddm->medge; @@ -2341,6 +2360,24 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) ml = cddm->mloop + mp->loopstart; + /* skip faces with all vertices merged */ + { + int all_vertices_merged = TRUE; + + for (j = 0; j < mp->totloop; j++, ml++) { + if (vtargetmap[ml->v] == -1) { + all_vertices_merged = FALSE; + break; + } + } + + if (UNLIKELY(all_vertices_merged)) { + continue; + } + } + + ml = cddm->mloop + mp->loopstart; + c = 0; for (j = 0; j < mp->totloop; j++, ml++) { med = cddm->medge + ml->e; @@ -2499,7 +2536,7 @@ void CDDM_calc_edges(DerivedMesh *dm) EdgeHashIterator *ehi; MPoly *mp = cddm->mpoly; MLoop *ml; - MEdge *med; + MEdge *med, *origmed; EdgeHash *eh = BLI_edgehash_new(); int v1, v2; int *eindex; @@ -2532,6 +2569,7 @@ void CDDM_calc_edges(DerivedMesh *dm) CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + origmed = cddm->medge; med = CustomData_get_layer(&edgeData, CD_MEDGE); index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); @@ -2542,8 +2580,14 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - *index = j == 0 ? ORIGINDEX_NONE : eindex[j - 1]; + if (j == 0) { + med->flag = ME_EDGEDRAW | ME_EDGERENDER; + *index = ORIGINDEX_NONE; + } + else { + med->flag = ME_EDGEDRAW | ME_EDGERENDER | origmed[j - 1].flag; + *index = eindex[j - 1]; + } BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index b488e683947..4641a02265a 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -198,8 +198,10 @@ static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3 w3[0] = 1.0f - w1[0] - w2[0]; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 ) { @@ -371,7 +373,9 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM return result; } -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif //Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 75276adf518..529fe07cab3 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1008,8 +1008,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * const ColorManagedDisplaySettings *display_settings) { int x, y, c; - unsigned int n, nl; - double div, divl; + unsigned int nl, na, nr, ng, nb; + double divl, diva, divr, divg, divb; float *rf = NULL; unsigned char *rc = NULL; unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; @@ -1149,24 +1149,37 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * savedlines += 1; } + /* test for nicer distribution even - non standard, leave it out for a while */ +#if 0 + for (x = 0; x < 256; x++) { + bin_lum[x] = sqrt (bin_lum[x]); + bin_r[x] = sqrt(bin_r[x]); + bin_g[x] = sqrt(bin_g[x]); + bin_b[x] = sqrt(bin_b[x]); + bin_a[x] = sqrt(bin_a[x]); + } +#endif + /* convert hist data to float (proportional to max count) */ - n = 0; - nl = 0; + nl = na = nr = nb = ng = 0; for (x = 0; x < 256; x++) { if (bin_lum[x] > nl) nl = bin_lum[x]; - if (bin_r[x] > n) n = bin_r[x]; - if (bin_g[x] > n) n = bin_g[x]; - if (bin_b[x] > n) n = bin_b[x]; - if (bin_a[x] > n) n = bin_a[x]; + if (bin_r[x] > nr) nr = bin_r[x]; + if (bin_g[x] > ng) ng = bin_g[x]; + if (bin_b[x] > nb) nb = bin_b[x]; + if (bin_a[x] > na) na = bin_a[x]; } - div = 1.0 / (double)n; divl = 1.0 / (double)nl; + diva = 1.0 / (double)na; + divr = 1.0 / (double)nr; + divg = 1.0 / (double)ng; + divb = 1.0 / (double)nb; for (x = 0; x < 256; x++) { scopes->hist.data_luma[x] = bin_lum[x] * divl; - scopes->hist.data_r[x] = bin_r[x] * div; - scopes->hist.data_g[x] = bin_g[x] * div; - scopes->hist.data_b[x] = bin_b[x] * div; - scopes->hist.data_a[x] = bin_a[x] * div; + scopes->hist.data_r[x] = bin_r[x] * divr; + scopes->hist.data_g[x] = bin_g[x] * divg; + scopes->hist.data_b[x] = bin_b[x] * divb; + scopes->hist.data_a[x] = bin_a[x] * diva; } MEM_freeN(bin_lum); MEM_freeN(bin_r); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e300b5e0f19..97d750854f4 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -84,15 +84,9 @@ #include "BKE_movieclip.h" #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - - - /* ************************ Constraints - General Utilities *************************** */ /* These functions here don't act on any specific constraints, and are therefore should/will * not require any of the special function-pointers afforded by the relevant constraint diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 719ae7357b4..ffb93139358 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -44,6 +44,7 @@ #include "BLI_listbase.h" #include "BLI_string.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -245,6 +246,10 @@ static void *ctx_wm_python_context_get(const bContext *C, const char *member, vo (void)C, (void)member; #endif + /* don't allow UI context access from non-main threads */ + if (!BLI_thread_is_main()) + return NULL; + return fall_through; } @@ -264,6 +269,11 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res // return 1; } #endif + + /* don't allow UI context access from non-main threads */ + if (!BLI_thread_is_main()) + return done; + /* we check recursion to ensure that we do not get infinite * loops requesting data from ourselfs in a context callback */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 67aaaceaa38..754a4fbc0c8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1116,13 +1116,13 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float * *fp = basisu[i] * bp->vec[3]; sumdiv += *fp; } - if (sumdiv != 0.0f) if (sumdiv < 0.999f || sumdiv > 1.001f) { - /* is normalizing needed? */ - fp = sum; - for (i = istart; i <= iend; i++, fp++) { - *fp /= sumdiv; - } + if ((sumdiv != 0.0f) && (sumdiv < 0.999f || sumdiv > 1.001f)) { + /* is normalizing needed? */ + fp = sum; + for (i = istart; i <= iend; i++, fp++) { + *fp /= sumdiv; } + } /* one! (1.0) real point */ fp = sum; @@ -2481,8 +2481,8 @@ void BKE_curve_bevelList_make(Object *ob) else bevp2 = bevp1 + 1; - inp = (bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) + - (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0]); + inp = ((bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) + + (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0])); if (inp > 0.0f) sd->dir = 1; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 93c776ae30e..b2f8db0dcce 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -761,7 +761,7 @@ static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) { MLoopUV *min = vmin, *max = vmax, *luv = data; - DO_MINMAX2(luv->uv, min->uv, max->uv); + minmax_v2v2_v2(min->uv, max->uv, luv->uv); } static void layerAdd_mloopuv(void *data1, void *data2) @@ -833,7 +833,7 @@ static void layerDoMinMax_mloop_origspace(void *data, void *vmin, void *vmax) { OrigSpaceLoop *min = vmin, *max = vmax, *luv = data; - DO_MINMAX2(luv->uv, min->uv, max->uv); + minmax_v2v2_v2(min->uv, max->uv, luv->uv); } static void layerAdd_mloop_origspace(void *data1, void *data2) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 950a0ca3d60..3ed759392b6 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -45,6 +45,7 @@ #include "DNA_anim_types.h" #include "DNA_camera_types.h" #include "DNA_group_types.h" +#include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_key_types.h" #include "DNA_material_types.h" @@ -350,8 +351,8 @@ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node /* XXX: forward def for material driver handling... */ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma); -/* recursive handling for material nodetree drivers */ -static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree) +/* recursive handling for shader nodetree drivers */ +static void dag_add_shader_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree) { bNode *n; @@ -367,7 +368,7 @@ static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode * dag_add_material_driver_relations(dag, node, (Material *)n->id); } else if (n->type == NODE_GROUP) { - dag_add_material_nodetree_driver_relations(dag, node, (bNodeTree *)n->id); + dag_add_shader_nodetree_driver_relations(dag, node, (bNodeTree *)n->id); } } } @@ -386,21 +387,45 @@ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Mat ma->id.flag |= LIB_DOIT; /* material itself */ - if (ma->adt) { + if (ma->adt) dag_add_driver_relation(ma->adt, dag, node, 1); - } /* textures */ // TODO... //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id); /* material's nodetree */ - if (ma->nodetree) { - dag_add_material_nodetree_driver_relations(dag, node, ma->nodetree); - } + if (ma->nodetree) + dag_add_shader_nodetree_driver_relations(dag, node, ma->nodetree); } -static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield){ +/* recursive handling for lamp drivers */ +static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *la) +{ + /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited + * already (see build_dag()). This assumes la->id.flag & LIB_DOIT isn't set by anything else + * in the meantime... [#32017] + */ + if (la->id.flag & LIB_DOIT) + return; + else + la->id.flag |= LIB_DOIT; + + /* lamp itself */ + if (la->adt) + dag_add_driver_relation(la->adt, dag, node, 1); + + /* textures */ + // TODO... + //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id); + + /* lamp's nodetree */ + if (la->nodetree) + dag_add_shader_nodetree_driver_relations(dag, node, la->nodetree); +} + +static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield) +{ Base *base; DagNode *node2; @@ -646,6 +671,9 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } } + else if (ob->type == OB_LAMP) { + dag_add_lamp_driver_relations(dag, node, ob->data); + } /* particles */ psys = ob->particlesystem.first; @@ -816,6 +844,7 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* add base node for scene. scene is always the first node in DAG */ scenenode = dag_add_node(dag, sce); @@ -1911,13 +1940,13 @@ void DAG_scene_sort(Main *bmain, Scene *sce) static void lib_id_recalc_tag(Main *bmain, ID *id) { id->flag |= LIB_ID_RECALC; - bmain->id_tag_update[id->name[0]] = 1; + DAG_id_type_tag(bmain, GS(id->name)); } static void lib_id_recalc_data_tag(Main *bmain, ID *id) { id->flag |= LIB_ID_RECALC_DATA; - bmain->id_tag_update[id->name[0]] = 1; + DAG_id_type_tag(bmain, GS(id->name)); } /* node was checked to have lasttime != curtime and is if type ID_OB */ @@ -2789,6 +2818,7 @@ void DAG_ids_check_recalc(Main *bmain, Scene *scene, int time) void DAG_ids_clear_recalc(Main *bmain) { ListBase *lbarray[MAX_LIBARRAY]; + bNodeTree *ntree; int a; /* loop over all ID types */ @@ -2801,9 +2831,15 @@ void DAG_ids_clear_recalc(Main *bmain) /* we tag based on first ID type character to avoid * looping over all ID's in case there are no tags */ if (id && bmain->id_tag_update[id->name[0]]) { - for (; id; id = id->next) + for (; id; id = id->next) { if (id->flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)) id->flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA); + + /* some ID's contain semi-datablock nodetree */ + ntree = ntreeFromID(id); + if (ntree && (ntree->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA))) + ntree->id.flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA); + } } } @@ -2870,8 +2906,18 @@ void DAG_id_tag_update(ID *id, short flag) } } -void DAG_id_type_tag(struct Main *bmain, short idtype) +void DAG_id_type_tag(Main *bmain, short idtype) { + if (idtype == ID_NT) { + /* stupid workaround so parent datablocks of nested nodetree get looped + * over when we loop over tagged datablock types */ + DAG_id_type_tag(bmain, ID_MA); + DAG_id_type_tag(bmain, ID_TE); + DAG_id_type_tag(bmain, ID_LA); + DAG_id_type_tag(bmain, ID_WO); + DAG_id_type_tag(bmain, ID_SCE); + } + bmain->id_tag_update[((char *)&idtype)[0]] = 1; } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index e13d05d0a2f..083cb02fd3d 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -487,7 +487,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal) } /* XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { */ - if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, FALSE))) { + if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES))) { if (tot) { dlnew = MEM_callocN(sizeof(DispList), "filldisplist"); dlnew->type = DL_INDEX3; @@ -630,7 +630,7 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis * - first point left, last point right * - based on subdivided points in original curve, not on points in taper curve (still) */ -float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) +static float displist_calc_taper(Scene *scene, Object *taperobj, float fac) { DispList *dl; @@ -643,7 +643,6 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) dl = taperobj->disp.first; } if (dl) { - float fac = ((float)cur) / (float)(tot - 1); float minx, dx, *fp; int a; @@ -671,6 +670,13 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) return 1.0; } +float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) +{ + float fac = ((float)cur) / (float)(tot - 1); + + return displist_calc_taper(scene, taperobj, fac); +} + void BKE_displist_make_mball(Scene *scene, Object *ob) { if (!ob || ob->type != OB_MBALL) @@ -1240,7 +1246,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, } } -static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float widfac, float fac, float **data_r) +static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **data_r) { float *fp, *data = *data_r; int b; @@ -1248,22 +1254,48 @@ static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float wid fp = dlb->verts; for (b = 0; b < dlb->nr; b++, fp += 3, data += 3) { if (cu->flag & CU_3D) { - float vec[3]; + float vec[3], quat[4]; vec[0] = fp[1] + widfac; vec[1] = fp[2]; vec[2] = 0.0; - mul_qt_v3(bevp->quat, vec); + if (nbevp == NULL) { + copy_v3_v3(data, bevp->vec); + copy_qt_qt(quat, bevp->quat); + } + else { + interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend); + interp_qt_qtqt(quat, bevp->quat, nbevp->quat, bev_blend); + } - data[0] = bevp->vec[0] + fac * vec[0]; - data[1] = bevp->vec[1] + fac * vec[1]; - data[2] = bevp->vec[2] + fac * vec[2]; + mul_qt_v3(quat, vec); + + data[0] += fac * vec[0]; + data[1] += fac * vec[1]; + data[2] += fac * vec[2]; } else { - data[0] = bevp->vec[0] + fac * (widfac + fp[1]) * bevp->sina; - data[1] = bevp->vec[1] + fac * (widfac + fp[1]) * bevp->cosa; - data[2] = bevp->vec[2] + fac * fp[2]; + float sina, cosa; + + if (nbevp == NULL) { + copy_v3_v3(data, bevp->vec); + sina = bevp->sina; + cosa = bevp->cosa; + } + else { + interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend); + + /* perhaps we need to interpolate angles instead. but the thing is + * cosa and sina are not actually sine and cosine + */ + sina = nbevp->sina * bev_blend + bevp->sina * (1.0f - bev_blend); + cosa = nbevp->cosa * bev_blend + bevp->cosa * (1.0f - bev_blend); + } + + data[0] += fac * (widfac + fp[1]) * sina; + data[1] += fac * (widfac + fp[1]) * cosa; + data[2] += fac * fp[2]; } } @@ -1399,8 +1431,8 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba firstblend = 1.0f - (bevfac1 * (bl->nr - 1) - (int)(bevfac1 * (bl->nr - 1))); lastblend = bevfac2 * (bl->nr - 1) - (int)(bevfac2 * (bl->nr - 1)); - if (steps > bl->nr) { - steps = bl->nr; + if (start + steps > bl->nr) { + steps = bl->nr - start; lastblend = 1.0f; } @@ -1438,7 +1470,29 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba fac = bevp->radius; } else { - fac = BKE_displist_calc_taper(scene, cu->taperobj, i, bl->nr); + float len, taper_fac; + + if (cu->flag & CU_MAP_TAPER) { + len = (steps - 3) + firstblend + lastblend; + + if (a == 0) + taper_fac = 0.0f; + else if (a == steps - 1) + taper_fac = 1.0f; + else + taper_fac = ((float) a - (1.0f - firstblend)) / len; + } + else { + len = bl->nr - 1; + taper_fac = (float) i / len; + + if (a == 0) + taper_fac += (1.0f - firstblend) / len; + else if (a == steps - 1) + taper_fac -= (1.0f - lastblend) / len; + } + + fac = displist_calc_taper(scene, cu->taperobj, taper_fac); } if (bevp->split_tag) { @@ -1446,27 +1500,12 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } /* rotate bevel piece and write in data */ - rotateBevelPiece(cu, bevp, dlb, widfac, fac, &data); - - if (a == 1 || a == steps - 1) { - float *cur_fp = cur_data, *prev_fp = cur_data - 3 * dlb->nr; - int b; - - for (b = 0; b < dlb->nr; b++, prev_fp += 3, cur_fp += 3) { - float cur[3], prev[3]; - - copy_v3_v3(cur, cur_fp); - copy_v3_v3(prev, prev_fp); - - if (a == 1) - interp_v3_v3v3(prev, cur_fp, prev_fp, firstblend); - if (a == steps - 1) - interp_v3_v3v3(cur, prev_fp, cur_fp, lastblend); - - copy_v3_v3(cur_fp, cur); - copy_v3_v3(prev_fp, prev); - } - } + if (a == 0) + rotateBevelPiece(cu, bevp, bevp + 1, dlb, 1.0f - firstblend, widfac, fac, &data); + else if (a == steps - 1) + rotateBevelPiece(cu, bevp, bevp - 1, dlb, 1.0f - lastblend, widfac, fac, &data); + else + rotateBevelPiece(cu, bevp, NULL, dlb, 0.0f, widfac, fac, &data); if (cu->bevobj && (cu->flag & CU_FILL_CAPS)) { if (a == 1) diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 89d728c0419..ed85e5b627b 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -86,11 +86,13 @@ #include "RE_shader_ext.h" #ifdef _OPENMP -#include +# include #endif /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* precalculated gaussian factors for 5x super sampling */ static float gaussianFactors[5] = {0.996849f, @@ -3364,7 +3366,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, (!hit_found || (brush->flags & MOD_DPAINT_INVERSE_PROX))) { float proxDist = -1.0f; - float hitCo[3]; + float hitCo[3] = {0.0f, 0.0f, 0.0f}; short hQuad; int face; @@ -3721,6 +3723,8 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, float smooth_range = smooth * (1.0f - strength), dist; /* calculate max range that can have particles with higher influence than the nearest one */ float max_range = smooth - strength * smooth + solidradius; + /* Make gcc happy! */ + dist = max_range; particles = BLI_kdtree_range_search(tree, max_range, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest); diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 8d430eb58b5..321a61ce238 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -215,7 +215,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm) /* complete the loop */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); - totfilltri = BLI_scanfill_calc_ex(&sf_ctx, FALSE, efa->no); + totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no); BLI_array_grow_items(looptris, totfilltri); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 30427a81c4b..c3008d17bd1 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -47,39 +47,40 @@ typedef struct { } IDType; /* plural need to match rna_main.c's MainCollectionDef */ +/* WARNING! Keep it in sync with i18n contexts in BLF_translation.h */ static IDType idtypes[] = { - { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE}, - { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE}, - { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE}, - { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE}, - { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE}, /* rename gpencil */ - { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE}, - { ID_ID, "ID", "ids", 0}, /* plural is fake */ - { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE}, - { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE}, /* deprecated */ - { ID_KE, "Key", "shape_keys", 0}, - { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE}, - { ID_LI, "Library", "libraries", 0}, - { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE}, - { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE}, - { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE}, - { ID_PA, "ParticleSettings", "particles", 0}, - { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_SCR, "Screen", "screens", 0}, - { ID_SEQ, "Sequence", "sequences", 0}, /* not actually ID data */ - { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE}, - { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE}, - { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE}, - { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE}, - { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE}, - { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE}, - { ID_WM, "WindowManager", "window_managers", 0}, - { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE}, + { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE }, + { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE }, + { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE }, + { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE }, + { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */ + { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE }, + { ID_ID, "ID", "ids", 0 }, /* plural is fake */ + { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE }, + { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */ + { ID_KE, "Key", "shape_keys", 0 }, + { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE }, + { ID_LI, "Library", "libraries", 0 }, + { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE }, + { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE }, + { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE }, + { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE }, + { ID_PA, "ParticleSettings", "particles", 0 }, + { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_SCR, "Screen", "screens", 0 }, + { ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */ + { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE }, + { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE }, + { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE }, + { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE }, + { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE }, + { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE }, + { ID_WM, "WindowManager", "window_managers", 0 }, }; static int nidtypes = sizeof(idtypes) / sizeof(idtypes[0]); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ef751ce3493..f09f128e874 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -100,6 +100,8 @@ #include "WM_api.h" +static SpinLock image_spin; + /* max int, to indicate we don't store sequences in ibuf */ #define IMA_NO_INDEX 0x7FEFEFEF @@ -108,6 +110,16 @@ #define IMA_INDEX_FRAME(index) (index >> 10) #define IMA_INDEX_PASS(index) (index & ~1023) +void BKE_images_init(void) +{ + BLI_spin_init(&image_spin); +} + +void BKE_images_exit(void) +{ + BLI_spin_end(&image_spin); +} + /* ******** IMAGE PROCESSING ************* */ static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ @@ -168,13 +180,14 @@ static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ void BKE_image_de_interlace(Image *ima, int odd) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf) { if (odd) de_interlace_st(ibuf); else de_interlace_ng(ibuf); } + BKE_image_release_ibuf(ima, ibuf, NULL); } /* ***************** ALLOC & FREE, DATA MANAGING *************** */ @@ -260,8 +273,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) /* this function is intended to be thread safe. with IMA_NO_INDEX this * should be OK, but when iterating over the list this is more tricky * */ - if (index == IMA_NO_INDEX) + if (index == IMA_NO_INDEX) { return ima->ibufs.first; + } else { ImBuf *ibuf; @@ -269,9 +283,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) for (ibuf = ima->ibufs.first; ibuf; ibuf = ibuf->next) if (ibuf->index == index) return ibuf; - - return NULL; } + + return NULL; } /* no ima->ibuf anymore, but listbase */ @@ -534,7 +548,7 @@ int BKE_image_scale(Image *image, int width, int height) ibuf->userflags |= IB_BITMAPDIRTY; } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); return (ibuf != NULL); } @@ -649,6 +663,13 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char BKE_image_buf_fill_color(rect, rect_float, width, height, color); } + if (rect_float) { + /* both byte and float buffers are filling in sRGB space, need to linearize float buffer after BKE_image_buf_fill* functions */ + + IMB_buffer_float_from_float(rect_float, rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, + ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); + } + return ibuf; } @@ -1561,7 +1582,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* also a little of space to the background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and draw the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1578,7 +1599,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.note); @@ -1594,7 +1615,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.date); @@ -1610,7 +1631,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.rendertime); @@ -1625,7 +1646,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1641,7 +1662,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1656,7 +1677,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1671,7 +1692,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.camera); @@ -1684,7 +1705,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.cameralens); } @@ -1697,7 +1718,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1713,7 +1734,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.strip); @@ -2081,6 +2102,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) if (ima == NULL) return; + BLI_spin_lock(&image_spin); + switch (signal) { case IMA_SIGNAL_FREE: image_free_buffers(ima); @@ -2157,6 +2180,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) break; } + BLI_spin_unlock(&image_spin); + /* don't use notifiers because they are not 100% sure to succeeded * this also makes sure all scenes are accounted for. */ { @@ -2320,7 +2345,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) if (ibuf) { #ifdef WITH_OPENEXR - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { image_create_multilayer(ima, ibuf, frame); ima->type = IMA_TYPE_MULTILAYER; @@ -2482,7 +2507,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) } if (ibuf) { - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { image_create_multilayer(ima, ibuf, cfra); ima->type = IMA_TYPE_MULTILAYER; @@ -2751,38 +2776,32 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame * a big bottleneck */ } - *frame_r = frame; - *index_r = index; + if (frame_r) + *frame_r = frame; + + if (index_r) + *index_r = index; return ibuf; } -/* Checks optional ImageUser and verifies/creates ImBuf. */ -/* use this one if you want to get a render result in progress, - * if not, use BKE_image_get_ibuf which doesn't require a release */ -ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) +/* Checks optional ImageUser and verifies/creates ImBuf. + * + * not thread-safe, so callee should worry about thread locks + */ +static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf = NULL; float color[] = {0, 0, 0, 1}; int frame = 0, index = 0; - /* This function is intended to be thread-safe. It postpones the mutex lock - * until it needs to load the image, if the image is already there it - * should just get the pointer and return. The reason is that a lot of mutex - * locks appears to be very slow on certain multicore macs, causing a render - * with image textures to actually slow down as more threads are used. - * - * Note that all the image loading functions should also make sure they do - * things in a threadsafe way for image_get_ibuf_threadsafe to work correct. - * That means, the last two steps must be, 1) add the ibuf to the list and - * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */ - if (lock_r) *lock_r = NULL; /* quick reject tests */ if (ima == NULL) return NULL; + if (iuser) { if (iuser->ok == 0) return NULL; @@ -2790,95 +2809,71 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) else if (ima->ok == 0) return NULL; - /* try to get the ibuf without locking */ ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); if (ibuf == NULL) { - /* couldn't get ibuf and image is not ok, so let's lock and try to - * load the image */ - BLI_lock_thread(LOCK_IMAGE); - - /* need to check ok flag and loading ibuf again, because the situation - * might have changed in the meantime */ - if (iuser) { - if (iuser->ok == 0) { - BLI_unlock_thread(LOCK_IMAGE); - return NULL; + /* we are sure we have to load the ibuf, using source and type */ + if (ima->source == IMA_SRC_MOVIE) { + /* source is from single file, use flipbook to store ibuf */ + ibuf = image_load_movie_file(ima, iuser, frame); + } + else if (ima->source == IMA_SRC_SEQUENCE) { + if (ima->type == IMA_TYPE_IMAGE) { + /* regular files, ibufs in flipbook, allows saving */ + ibuf = image_load_sequence_file(ima, iuser, frame); + } + /* no else; on load the ima type can change */ + if (ima->type == IMA_TYPE_MULTILAYER) { + /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ + ibuf = image_load_sequence_multilayer(ima, iuser, frame); } } - else if (ima->ok == 0) { - BLI_unlock_thread(LOCK_IMAGE); - return NULL; + else if (ima->source == IMA_SRC_FILE) { + + if (ima->type == IMA_TYPE_IMAGE) + ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ + /* no else; on load the ima type can change */ + if (ima->type == IMA_TYPE_MULTILAYER) + /* keeps render result, stores ibufs in listbase, allows saving */ + ibuf = image_get_ibuf_multilayer(ima, iuser); + } - - ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); - - if (ibuf == NULL) { - /* we are sure we have to load the ibuf, using source and type */ - if (ima->source == IMA_SRC_MOVIE) { - /* source is from single file, use flipbook to store ibuf */ - ibuf = image_load_movie_file(ima, iuser, frame); + else if (ima->source == IMA_SRC_GENERATED) { + /* generated is: ibuf is allocated dynamically */ + /* UV testgrid or black or solid etc */ + if (ima->gen_x == 0) ima->gen_x = 1024; + if (ima->gen_y == 0) ima->gen_y = 1024; + ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, + color, &ima->colorspace_settings); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + ima->ok = IMA_OK_LOADED; + } + else if (ima->source == IMA_SRC_VIEWER) { + if (ima->type == IMA_TYPE_R_RESULT) { + /* always verify entirely, and potentially + * returns pointer to release later */ + ibuf = image_get_render_result(ima, iuser, lock_r); } - else if (ima->source == IMA_SRC_SEQUENCE) { - if (ima->type == IMA_TYPE_IMAGE) { - /* regular files, ibufs in flipbook, allows saving */ - ibuf = image_load_sequence_file(ima, iuser, frame); - } - /* no else; on load the ima type can change */ - if (ima->type == IMA_TYPE_MULTILAYER) { - /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ - ibuf = image_load_sequence_multilayer(ima, iuser, frame); - } - } - else if (ima->source == IMA_SRC_FILE) { + else if (ima->type == IMA_TYPE_COMPOSITE) { + /* requires lock/unlock, otherwise don't return image */ + if (lock_r) { + /* unlock in BKE_image_release_ibuf */ + BLI_lock_thread(LOCK_VIEWER); + *lock_r = ima; - if (ima->type == IMA_TYPE_IMAGE) - ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ - /* no else; on load the ima type can change */ - if (ima->type == IMA_TYPE_MULTILAYER) - /* keeps render result, stores ibufs in listbase, allows saving */ - ibuf = image_get_ibuf_multilayer(ima, iuser); + /* XXX anim play for viewer nodes not yet supported */ + frame = 0; // XXX iuser?iuser->framenr:0; + ibuf = image_get_ibuf(ima, 0, frame); - } - else if (ima->source == IMA_SRC_GENERATED) { - /* generated is: ibuf is allocated dynamically */ - /* UV testgrid or black or solid etc */ - if (ima->gen_x == 0) ima->gen_x = 1024; - if (ima->gen_y == 0) ima->gen_y = 1024; - ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, - color, &ima->colorspace_settings); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); - ima->ok = IMA_OK_LOADED; - } - else if (ima->source == IMA_SRC_VIEWER) { - if (ima->type == IMA_TYPE_R_RESULT) { - /* always verify entirely, and potentially - * returns pointer to release later */ - ibuf = image_get_render_result(ima, iuser, lock_r); - } - else if (ima->type == IMA_TYPE_COMPOSITE) { - /* requires lock/unlock, otherwise don't return image */ - if (lock_r) { - /* unlock in BKE_image_release_ibuf */ - BLI_lock_thread(LOCK_VIEWER); - *lock_r = ima; - - /* XXX anim play for viewer nodes not yet supported */ - frame = 0; // XXX iuser?iuser->framenr:0; - ibuf = image_get_ibuf(ima, 0, frame); - - if (!ibuf) { - /* Composite Viewer, all handled in compositor */ - /* fake ibuf, will be filled in compositor */ - ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); - image_assign_ibuf(ima, ibuf, 0, frame); - } + if (!ibuf) { + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); + image_assign_ibuf(ima, ibuf, 0, frame); } } } } - - BLI_unlock_thread(LOCK_IMAGE); } BKE_image_tag_time(ima); @@ -2886,23 +2881,79 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) return ibuf; } -void BKE_image_release_ibuf(Image *ima, void *lock) +/* return image buffer for given image and user + * + * - will lock render result if image type is render result and lock is not NULL + * - will return NULL if image type if render or composite result and lock is NULL + * + * references the result, BKE_image_release_ibuf should be used to de-reference + */ +ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { - /* for getting image during threaded render / compositing, need to release */ - if (lock == ima) { - BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + ImBuf *ibuf; + + BLI_spin_lock(&image_spin); + + ibuf = image_acquire_ibuf(ima, iuser, lock_r); + + if (ibuf) + IMB_refImBuf(ibuf); + + BLI_spin_unlock(&image_spin); + + return ibuf; +} + +void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock) +{ + if (lock) { + /* for getting image during threaded render / compositing, need to release */ + if (lock == ima) { + BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + } + else if (lock) { + RE_ReleaseResultImage(lock); /* render result */ + BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */ + } } - else if (lock) { - RE_ReleaseResultImage(lock); /* render result */ - BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */ + + if (ibuf) { + BLI_spin_lock(&image_spin); + IMB_freeImBuf(ibuf); + BLI_spin_unlock(&image_spin); } } -/* warning, this can allocate generated images */ -ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +/* checks whether there's an image buffer for given image and user */ +int BKE_image_has_ibuf(Image *ima, ImageUser *iuser) { - /* here (+fie_ima/2-1) makes sure that division happens correctly */ - return BKE_image_acquire_ibuf(ima, iuser, NULL); + ImBuf *ibuf; + + /* quick reject tests */ + if (ima == NULL) + return FALSE; + + if (iuser) { + if (iuser->ok == 0) + return FALSE; + } + else if (ima->ok == 0) + return FALSE; + + ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); + + if (!ibuf) { + BLI_spin_lock(&image_spin); + + ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); + + if (!ibuf) + ibuf = image_acquire_ibuf(ima, iuser, NULL); + + BLI_spin_unlock(&image_spin); + } + + return ibuf != NULL; } int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range) @@ -3020,7 +3071,7 @@ int BKE_image_has_alpha(struct Image *image) ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); planes = (ibuf ? ibuf->planes : 0); - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); if (planes == 32) return 1; @@ -3044,7 +3095,7 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) *height = IMG_SIZE_FALLBACK; } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); } void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float size[2]) diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 4782d09a7c8..2f37db846f3 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -33,9 +33,12 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" +#include "DNA_node_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "DNA_texture_types.h" #include "BLI_listbase.h" @@ -73,7 +76,7 @@ Lamp *BKE_lamp_add(const char *name) la->soft = 3.0f; la->compressthresh = 0.05f; la->ray_samp = la->ray_sampy = la->ray_sampz = 1; - la->area_size = la->area_sizey = la->area_sizez = 1.0f; + la->area_size = la->area_sizey = la->area_sizez = 0.1f; la->buffers = 1; la->buftype = LA_SHADBUF_HALFWAY; la->ray_samp_method = LA_SAMP_HALTON; @@ -232,3 +235,38 @@ void BKE_lamp_free(Lamp *la) la->id.icon_id = 0; } +/* Calculate all drivers for lamps, see material_drivers_update for why this is a bad hack */ + +static void lamp_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime) +{ + bNode *node; + + /* nodetree itself */ + if (ntree->adt && ntree->adt->drivers.first) + BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS); + + /* nodes */ + for (node = ntree->nodes.first; node; node = node->next) + if (node->id && node->type == NODE_GROUP) + lamp_node_drivers_update(scene, (bNodeTree *)node->id, ctime); +} + +void lamp_drivers_update(Scene *scene, Lamp *la, float ctime) +{ + /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited already + * (see BKE_scene_update_tagged()). This assumes la->id.flag & LIB_DOIT isn't set by anything else + * in the meantime... [#32017] */ + if (la->id.flag & LIB_DOIT) + return; + else + la->id.flag |= LIB_DOIT; + + /* lamp itself */ + if (la->adt && la->adt->drivers.first) + BKE_animsys_evaluate_animdata(scene, &la->id, la->adt, ctime, ADT_RECALC_DRIVERS); + + /* nodes */ + if (la->nodetree) + lamp_node_drivers_update(scene, la->nodetree, ctime); +} + diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 942e71b5052..eb0612a75bd 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -998,7 +998,6 @@ void free_main(Main *mainvar) #endif } } - a = set_listbasepointers(mainvar, lbarray); MEM_freeN(mainvar); } @@ -1521,7 +1520,9 @@ void test_idbutton(char *name) /* search for id */ idtest = BLI_findstring(lb, name, offsetof(ID, name) + 2); - if (idtest) if (new_id(lb, idtest, name) == 0) id_sort_by_name(lb, idtest); + if (idtest && (new_id(lb, idtest, name) == 0)) { + id_sort_by_name(lb, idtest); + } } void text_idbutton(struct ID *id, char *text) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index b7f4c4bd61e..bda924060d5 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1416,7 +1416,7 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do for (spline = masklay->splines.first; spline; spline = spline->next) { int i; - int has_auto = FALSE; + int need_handle_recalc = FALSE; BKE_mask_spline_ensure_deform(spline); @@ -1436,16 +1436,16 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do add_v2_v2(point_deform->bezt.vec[2], delta); } - if (point->bezt.h1 == HD_AUTO) { - has_auto = TRUE; + if (ELEM(point->bezt.h1, HD_AUTO, HD_VECT)) { + need_handle_recalc = TRUE; } } - /* if the spline has auto handles, these need to be recalculated after deformation */ - if (has_auto) { + /* if the spline has auto or vector handles, these need to be recalculated after deformation */ + if (need_handle_recalc) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point_deform = &spline->points_deform[i]; - if (point_deform->bezt.h1 == HD_AUTO) { + if (ELEM(point_deform->bezt.h1, HD_AUTO, HD_VECT)) { BKE_mask_calc_handle_point(spline, point_deform); } } diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index e67df9c6419..a2f6b3c1929 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -245,7 +245,7 @@ static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int e } else { bucket->segments = MEM_reallocN(bucket->segments, - (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); + (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); } bucket->alloc_segment += alloc_delta; @@ -289,10 +289,10 @@ static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_f /* collapse loop with smaller AABB */ for (k = 0; k < tot_feather_point; k++) { if (k >= check_b && k <= cur_a) { - DO_MINMAX2(feather_points[k], min_a, max_a); + minmax_v2v2_v2(min_a, max_a, feather_points[k]); } else { - DO_MINMAX2(feather_points[k], min_b, max_b); + minmax_v2v2_v2(min_b, max_b, feather_points[k]); } } @@ -379,7 +379,7 @@ void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*fe int next = i + 1; float delta; - DO_MINMAX2(feather_points[i], min, max); + minmax_v2v2_v2(min, max, feather_points[i]); if (next == tot_feather_point) { if (spline->flag & MASK_SPLINE_CYCLIC) diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 88393fab79c..2fa928e7c07 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -933,7 +933,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas } /* main scan-fill */ - sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, FALSE, zvec); + sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, 0, zvec); face_array = MEM_mallocN(sizeof(*face_array) * (sf_tri_tot + tot_feather_quads), "maskrast_face_index"); face_index = 0; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 6d44473583f..036f8f5e673 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2388,7 +2388,7 @@ void create_vert_poly_map(MeshElemMap **map, int **mem, * of edges that use that vertex as an endpoint. The lists are allocated * from one memory pool. */ void create_vert_edge_map(MeshElemMap **map, int **mem, - const MEdge *medge, int totvert, int totedge) + const MEdge *medge, int totvert, int totedge) { int i, *indices; @@ -2607,7 +2607,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, } BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first); - totfilltri = BLI_scanfill_calc(&sf_ctx, FALSE); + totfilltri = BLI_scanfill_calc(&sf_ctx, 0); if (totfilltri) { BLI_array_grow_items(mface_to_poly_map, totfilltri); BLI_array_grow_items(mface, totfilltri); @@ -3011,7 +3011,7 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, MLoop *l_iter = loopstart; float area, polynorm_local[3], (*vertexcos)[3]; const float *no = polynormal ? polynormal : polynorm_local; - BLI_array_fixedstack_declare(vertexcos, BM_NGON_STACK_SIZE, mpoly->totloop, __func__); + BLI_array_fixedstack_declare(vertexcos, BM_DEFAULT_NGON_STACK_SIZE, mpoly->totloop, __func__); /* pack vertex cos into an array for area_poly_v3 */ for (i = 0; i < mpoly->totloop; i++, l_iter++) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9c7cbc42bdd..25b70ce1793 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -249,13 +249,13 @@ int modifier_couldBeCage(struct Scene *scene, ModifierData *md) modifier_supportsMapping(md)); } -int modifier_sameTopology(ModifierData *md) +int modifier_isSameTopology(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical); } -int modifier_nonGeometrical(ModifierData *md) +int modifier_isNonGeometrical(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); return (mti->type == eModifierTypeType_NonGeometrical); diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 98eac9b95af..381e4350391 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -79,7 +79,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) /*do verts*/ mv = mvert = dm->dupVertArray(dm); for (i = 0; i < totvert; i++, mv++) { - v = BM_vert_create(bm, mv->co, NULL); + v = BM_vert_create(bm, mv->co, NULL, BM_CREATE_SKIP_CD); normal_short_to_float_v3(v->no, mv->no); v->head.hflag = BM_vert_flag_from_mflag(mv->flag); BM_elem_index_set(v, i); /* set_inline */ @@ -97,7 +97,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) me = medge = dm->dupEdgeArray(dm); for (i = 0; i < totedge; i++, me++) { //BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL); - e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, FALSE); + e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, BM_CREATE_SKIP_CD); e->head.hflag = BM_edge_flag_from_mflag(me->flag); BM_elem_index_set(e, i); /* set_inline */ @@ -134,7 +134,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) edges[j] = etable[ml->e]; } - f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, FALSE); + f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, BM_CREATE_SKIP_CD); if (UNLIKELY(f == NULL)) { continue; diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 6e8f2697ee1..4156b5b4367 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1176,13 +1176,16 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, TRUE, TRUE); - if (!search_ibuf->rect_float) { - /* sampling happens in float buffer */ - IMB_float_from_rect(search_ibuf); + if (search_ibuf) { + if (!search_ibuf->rect_float) { + /* sampling happens in float buffer */ + IMB_float_from_rect(search_ibuf); + } + + scopes->track_search = search_ibuf; } scopes->undist_marker = undist_marker; - scopes->track_search = search_ibuf; scopes->frame_width = ibuf->x; scopes->frame_height = ibuf->y; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 66f2ff12258..c737dccc5d2 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -984,7 +984,7 @@ static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *gri /* Construct 3x3 tangent-space matrix in 'mat' */ static void grid_tangent_matrix(float mat[3][3], const CCGKey *key, - int x, int y, CCGElem *grid) + int x, int y, CCGElem *grid) { grid_tangent(key, x, y, 0, grid, mat[0]); normalize_v3(mat[0]); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 153eb5271c5..17dcf34b71f 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -38,9 +38,13 @@ #include "DNA_action_types.h" #include "DNA_anim_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" #include "BLI_string.h" #include "BLI_math.h" @@ -406,13 +410,14 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) /* only shader nodes get pleasant preview updating this way, compo uses own system */ if (node->preview) { - if (ntree->type == NTREE_SHADER) { + if (ntree && (ntree->type == NTREE_SHADER)) { nnode->preview = MEM_dupallocN(node->preview); if (node->preview->rect) nnode->preview->rect = MEM_dupallocN(node->preview->rect); } - else + else { nnode->preview = NULL; + } } if (ntree) @@ -1153,6 +1158,18 @@ void ntreeSetOutput(bNodeTree *ntree) * might be different for editor or for "real" use... */ } +bNodeTree *ntreeFromID(ID *id) +{ + switch (GS(id->name)) { + case ID_MA: return ((Material*)id)->nodetree; + case ID_LA: return ((Lamp*)id)->nodetree; + case ID_WO: return ((World*)id)->nodetree; + case ID_TE: return ((Tex*)id)->nodetree; + case ID_SCE: return ((Scene*)id)->nodetree; + default: return NULL; + } +} + typedef struct MakeLocalCallData { ID *group_id; ID *new_id; @@ -2153,8 +2170,6 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_reroute(ttype); register_node_type_cmp_group(ttype); -// register_node_type_cmp_forloop(ttype); -// register_node_type_cmp_whileloop(ttype); register_node_type_cmp_rlayers(ttype); register_node_type_cmp_image(ttype); @@ -2184,6 +2199,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_normal(ttype); register_node_type_cmp_curve_vec(ttype); register_node_type_cmp_map_value(ttype); + register_node_type_cmp_map_range(ttype); register_node_type_cmp_normalize(ttype); register_node_type_cmp_filter(ttype); @@ -2254,8 +2270,6 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_reroute(ttype); register_node_type_sh_group(ttype); - //register_node_type_sh_forloop(ttype); - //register_node_type_sh_whileloop(ttype); register_node_type_sh_output(ttype); register_node_type_sh_material(ttype); @@ -2293,17 +2307,21 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_particle_info(ttype); register_node_type_sh_bump(ttype); register_node_type_sh_script(ttype); + register_node_type_sh_tangent(ttype); + register_node_type_sh_normal_map(ttype); register_node_type_sh_background(ttype); register_node_type_sh_bsdf_anisotropic(ttype); register_node_type_sh_bsdf_diffuse(ttype); register_node_type_sh_bsdf_glossy(ttype); register_node_type_sh_bsdf_glass(ttype); + register_node_type_sh_bsdf_refraction(ttype); register_node_type_sh_bsdf_translucent(ttype); register_node_type_sh_bsdf_transparent(ttype); register_node_type_sh_bsdf_velvet(ttype); register_node_type_sh_emission(ttype); register_node_type_sh_holdout(ttype); + register_node_type_sh_ambient_occlusion(ttype); //register_node_type_sh_volume_transparent(ttype); //register_node_type_sh_volume_isotropic(ttype); register_node_type_sh_mix_shader(ttype); @@ -2332,8 +2350,6 @@ static void registerTextureNodes(bNodeTreeType *ttype) register_node_type_reroute(ttype); register_node_type_tex_group(ttype); -// register_node_type_tex_forloop(ttype); -// register_node_type_tex_whileloop(ttype); register_node_type_tex_math(ttype); register_node_type_tex_mix_rgb(ttype); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0611e84bdf3..47ca502d247 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -196,18 +196,18 @@ int BKE_object_support_modifier_type_check(Object *ob, int modifier_type) return TRUE; } -void BKE_object_link_modifiers(struct Object *ob, struct Object *from) +void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) { ModifierData *md; - BKE_object_free_modifiers(ob); + BKE_object_free_modifiers(ob_dst); - if (!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { /* only objects listed above can have modifiers and linking them to objects * which doesn't have modifiers stack is quite silly */ return; } - for (md = from->modifiers.first; md; md = md->next) { + for (md = ob_src->modifiers.first; md; md = md->next) { ModifierData *nmd = NULL; if (ELEM4(md->type, @@ -219,16 +219,18 @@ void BKE_object_link_modifiers(struct Object *ob, struct Object *from) continue; } - if (!BKE_object_support_modifier_type_check(ob, md->type)) + if (!BKE_object_support_modifier_type_check(ob_dst, md->type)) continue; nmd = modifier_new(md->type); + BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); modifier_copyData(md, nmd); - BLI_addtail(&ob->modifiers, nmd); + BLI_addtail(&ob_dst->modifiers, nmd); + modifier_unique_name(&ob_dst->modifiers, nmd); } - BKE_object_copy_particlesystems(ob, from); - BKE_object_copy_softbody(ob, from); + BKE_object_copy_particlesystems(ob_dst, ob_src); + BKE_object_copy_softbody(ob_dst, ob_src); /* TODO: smoke?, cloth? */ } @@ -2654,6 +2656,8 @@ void BKE_object_handle_update(Scene *scene, Object *ob) } } } + else if (ob->type == OB_LAMP) + lamp_drivers_update(scene, ob->data, ctime); /* particles */ if (ob->particlesystem.first) { diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 7bc736d394e..e694a7e7eb3 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -183,7 +183,7 @@ MINLINE float catrom(float p0, float p1, float p2, float p3, float f) MINLINE float omega(float k, float depth) { - return sqrt(GRAVITY * k * tanh(k * depth)); + return sqrtf(GRAVITY * k * tanhf(k * depth)); } // modified Phillips spectrum @@ -256,8 +256,8 @@ static void add_comlex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl static void mul_complex_f(fftw_complex res, fftw_complex cmpl, float f) { - res[0] = cmpl[0] * f; - res[1] = cmpl[1] * f; + res[0] = cmpl[0] * (double)f; + res[1] = cmpl[1] * (double)f; } static void mul_complex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) @@ -289,8 +289,8 @@ static void exp_complex(fftw_complex res, fftw_complex cmpl) { float r = expf(cmpl[0]); - res[0] = cos(cmpl[1]) * r; - res[1] = sin(cmpl[1]) * r; + res[0] = cosf(cmpl[1]) * r; + res[1] = sinf(cmpl[1]) * r; } float BKE_ocean_jminus_to_foam(float jminus, float coverage) @@ -462,7 +462,7 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j) i = abs(i) % oc->_M; j = abs(j) % oc->_N; - ocr->disp[1] = oc->_do_disp_y ? oc->_disp_y[i * oc->_N + j] : 0.0f; + ocr->disp[1] = oc->_do_disp_y ? (float)oc->_disp_y[i * oc->_N + j] : 0.0f; if (oc->_do_chop) { ocr->disp[0] = oc->_disp_x[i * oc->_N + j]; @@ -546,7 +546,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -568,7 +568,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -589,7 +589,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -616,7 +616,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d645204d29c..5f5a713064d 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -822,8 +822,8 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea"); @@ -1645,8 +1645,8 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } mpoly = dm->getPolyArray(dm); @@ -3786,14 +3786,22 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co return 1; } -#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \ - if ((event & mtex->mapto) & type) { pvalue = texture_value_blend(def, pvalue, value, texfac, blend); } (void)0 +#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \ + if ((event & mtex->mapto) & type) { \ + pvalue = texture_value_blend(def, pvalue, value, texfac, blend); \ + } (void)0 -#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \ - if (event & type) { if (pvalue < 0.0f) pvalue = 1.0f + pvalue; CLAMP(pvalue, 0.0f, 1.0f); } (void)0 +#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \ + if (event & type) { \ + if (pvalue < 0.0f) \ + pvalue = 1.0f + pvalue; \ + CLAMP(pvalue, 0.0f, 1.0f); \ + } (void)0 -#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \ - if (event & type) { CLAMP(pvalue, -1.0f, 1.0f); } (void)0 +#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \ + if (event & type) { \ + CLAMP(pvalue, -1.0f, 1.0f); \ + } (void)0 static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra) { @@ -3802,8 +3810,8 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti float value, rgba[4], texvec[3]; ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = - ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = - ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; + ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = + ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f; ptex->length = 1.0f - part->randlength * PSYS_FRAND(child_index + 26); ptex->length *= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 2b95946f571..90889d7c09e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -367,11 +367,12 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems"); nodearray= MEM_callocN(sizeof(LinkNode *)*totelem, "psys node array"); - for (i=0, node=nodedmelem; ilink = SET_INT_IN_POINTER(i); - origindex_final = *origindex; + /* may be vertex or face origindex */ + origindex_final = origindex ? origindex[i] : ORIGINDEX_NONE; /* if we have a poly source, do an index lookup */ if (origindex_poly && origindex_final != ORIGINDEX_NONE) { @@ -466,13 +467,7 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) mv++; for (i=1; ico[0]); - min[1]=MIN2(min[1],mv->co[1]); - min[2]=MIN2(min[2],mv->co[2]); - - max[0]=MAX2(max[0],mv->co[0]); - max[1]=MAX2(max[1],mv->co[1]); - max[2]=MAX2(max[2],mv->co[2]); + minmax_v3v3_v3(min, max, mv->co); } sub_v3_v3v3(delta, max, min); @@ -2145,16 +2140,22 @@ static void psys_update_effectors(ParticleSimulationData *sim) precalc_guides(sim, sim->psys->effectors); } -static void integrate_particle(ParticleSettings *part, ParticleData *pa, float dtime, float *external_acceleration, void (*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse), void *forcedata) +static void integrate_particle(ParticleSettings *part, ParticleData *pa, float dtime, float *external_acceleration, + void (*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse), + void *forcedata) { +#define ZERO_F43 {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}} + ParticleKey states[5]; - float force[3],acceleration[3],impulse[3],dx[4][3],dv[4][3],oldpos[3]; + float force[3], acceleration[3], impulse[3], dx[4][3] = ZERO_F43, dv[4][3] = ZERO_F43, oldpos[3]; float pa_mass= (part->flag & PART_SIZEMASS ? part->mass * pa->size : part->mass); int i, steps=1; int integrator = part->integrator; +#undef ZERO_F43 + copy_v3_v3(oldpos, pa->state.co); - + /* Verlet integration behaves strangely with moving emitters, so do first step with euler. */ if (pa->prev_state.time < 0.f && integrator == PART_INT_VERLET) integrator = PART_INT_EULER; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index f195b3d71b0..965a1e2b4a6 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -686,7 +686,7 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) /* reallocate fluid if needed*/ if (reallocate) { - sds->active_fields = active_fields; + sds->active_fields = active_fields | cache_fields; smoke_reallocate_fluid(sds, ch_dx, ch_res, 1); sds->dx = ch_dx; VECCOPY(sds->res, ch_res); @@ -755,6 +755,7 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) if (cache_fields & SM_ACTIVE_FIRE) { ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len_big); ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char *)react, out_len_big); } if (cache_fields & SM_ACTIVE_COLORS) { ptcache_file_compressed_read(pf, (unsigned char *)r, out_len_big); @@ -2568,10 +2569,12 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) sbFreeSimulation(pid->calldata); else if (pid->type == PTCACHE_TYPE_PARTICLES) psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); - /*else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) +#if 0 + else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) smokeModifier_reset(pid->calldata); else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) - smokeModifier_reset_turbulence(pid->calldata);*/ + smokeModifier_reset_turbulence(pid->calldata); +#endif else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index a1918b77a1e..9bb2fb2de52 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -58,8 +58,10 @@ #include "BKE_anim.h" #include "BKE_animsys.h" +#include "BKE_action.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_idprop.h" @@ -115,6 +117,24 @@ void free_qtcodecdata(QuicktimeCodecData *qcd) } } +static void remove_sequencer_fcurves(Scene *sce) +{ + AnimData *adt = BKE_animdata_from_id(&sce->id); + + if (adt && adt->action) { + FCurve *fcu, *nextfcu; + + for (fcu = adt->action->curves.first; fcu; fcu = nextfcu) { + nextfcu = fcu->next; + + if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { + action_groups_remove_channel(adt->action, fcu); + free_fcurve(fcu); + } + } + } +} + Scene *BKE_scene_copy(Scene *sce, int type) { Scene *scen; @@ -179,6 +199,10 @@ Scene *BKE_scene_copy(Scene *sce, int type) BLI_strncpy(scen->sequencer_colorspace_settings.name, sce->sequencer_colorspace_settings.name, sizeof(scen->sequencer_colorspace_settings.name)); + + /* remove animation used by sequencer */ + if (type != SCE_COPY_FULL) + remove_sequencer_fcurves(scen); } /* tool settings */ @@ -377,6 +401,7 @@ Scene *BKE_scene_add(const char *name) sce->r.im_format.planes = R_IMF_PLANES_RGB; sce->r.im_format.imtype = R_IMF_IMTYPE_PNG; sce->r.im_format.quality = 90; + sce->r.im_format.compress = 90; sce->r.displaymode = R_OUTPUT_AREA; sce->r.framapto = 100; @@ -1019,8 +1044,10 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); - /* always update layer, so that animating layers works */ - base->lay = ob->lay; + /* always update layer, so that animating layers works (joshua july 2010) */ + /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes + * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */ + // base->lay = ob->lay; } /* scene drivers... */ @@ -1048,6 +1075,7 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene) * when trying to find materials with drivers that need evaluating [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* update all objects: drivers, matrices, displists, etc. flags set * by depgraph or manual, no layer check here, gets correct flushed @@ -1117,6 +1145,7 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) * when trying to find materials with drivers that need evaluating [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* BKE_object_handle_update() on all objects, groups and sets */ scene_update_tagged_recursive(bmain, sce, sce); diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 469881020c1..0b7fdaa7c1d 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -139,6 +139,9 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * IMB_rect_from_float(ibuf3); } + if (out->rect_float) + IMB_colormanagement_assign_float_colorspace(out, context.scene->sequencer_colorspace_settings.name); + return out; } diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index b0dcad64722..5b2e9f2bf23 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -349,9 +349,9 @@ static void hue_correct_apply_threaded(int width, int height, unsigned char *rec hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2); if (mask_rect_float) - copy_v3_v3(mask, mask_rect_float + pixel_index); + copy_v3_v3(mask, mask_rect_float + pixel_index); else if (mask_rect) - rgb_uchar_to_float(mask, mask_rect + pixel_index); + rgb_uchar_to_float(mask, mask_rect + pixel_index); result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0]; result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1]; @@ -427,17 +427,17 @@ static void brightcontrast_apply_threaded(int width, int height, unsigned char * unsigned char *pixel = rect + pixel_index; for (c = 0; c < 3; c++) { - i = pixel[c]; + i = (float) pixel[c] / 255.0f; v = a * i + b; if (mask_rect) { unsigned char *m = mask_rect + pixel_index; float t = (float) m[c] / 255.0f; - pixel[c] = pixel[c] * (1.0f - t) + v * t; + v = (float) pixel[c] * (1.0f - t) + v * t; } - else - pixel[c] = v; + + pixel[c] = FTOCHAR(v); } } else if (rect_float) { diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index af0cab98fe0..acce3740c98 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1835,6 +1835,8 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, StripCrop c = {0}; StripTransform t = {0}; int sx, sy, dx, dy; + double xscale = 1.0; + double yscale = 1.0; if (is_proxy_image) { double f = seq_rendersize_to_scale_factor(context.preview_render_size); @@ -1851,6 +1853,17 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, t = *seq->strip->transform; } + xscale = context.scene->r.xsch ? ((double)context.rectx / (double)context.scene->r.xsch) : 1.0; + yscale = context.scene->r.ysch ? ((double)context.recty / (double)context.scene->r.ysch) : 1.0; + + xscale /= (double)context.rectx / (double)ibuf->x; + yscale /= (double)context.recty / (double)ibuf->y; + + c.left *= xscale; c.right *= xscale; + c.top *= yscale; c.bottom *= yscale; + + t.xofs *= xscale; t.yofs *= yscale; + sx = ibuf->x - c.left - c.right; sy = ibuf->y - c.top - c.bottom; dx = sx; @@ -2338,12 +2351,15 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float */ const short is_rendering = G.is_rendering; + const short is_background = G.background; const int do_seq_gl = G.is_rendering ? 0 /* (context.scene->r.seq_flag & R_SEQ_GL_REND) */ : (context.scene->r.seq_flag & R_SEQ_GL_PREV); int do_seq; - int have_seq = FALSE; + // int have_seq = FALSE; /* UNUSED */ + int have_comp = FALSE; Scene *scene; + int is_thread_main = BLI_thread_is_main(); /* don't refer to seq->scene above this point!, it can be NULL */ if (seq->scene == NULL) { @@ -2353,7 +2369,8 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float scene = seq->scene; frame = scene->r.sfra + nr + seq->anim_startofs; - have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first; + // have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first; /* UNUSED */ + have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree; oldcfra = scene->r.cfra; scene->r.cfra = frame; @@ -2366,14 +2383,14 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float camera = scene->camera; } - if (have_seq == FALSE && camera == NULL) { + if (have_comp == FALSE && camera == NULL) { scene->r.cfra = oldcfra; return NULL; } /* prevent eternal loop */ do_seq = context.scene->r.scemode & R_DOSEQ; - context.scene->r.scemode &= ~R_DOSEQ; + scene->r.scemode &= ~R_DOSEQ; #ifdef DURIAN_CAMERA_SWITCH /* stooping to new low's in hackyness :( */ @@ -2383,10 +2400,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float (void)oldmarkers; #endif - if ((sequencer_view3d_cb && do_seq_gl && camera) && - (BLI_thread_is_main() == TRUE) && - ((have_seq == FALSE) || (scene == context.scene))) - { + if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) { char err_out[256] = "unknown"; /* for old scened this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ @@ -2405,11 +2419,19 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float Render *re = RE_GetRender(scene->id.name); RenderResult rres; - /* XXX: this if can be removed when sequence preview rendering uses the job system */ - if (is_rendering || context.scene != scene) { + /* XXX: this if can be removed when sequence preview rendering uses the job system + * + * disable rendered preview for sequencer while rendering -- it's very much possible + * that preview render will went into conflict with final render + * + * When rendering from command line renderer is called from main thread, in this + * case it's always safe to render scene here + */ + if (!is_thread_main || is_rendering == FALSE || is_background) { if (re == NULL) re = RE_NewRender(scene->id.name); + BKE_scene_update_for_newframe(context.bmain, scene, scene->lay); RE_BlenderFrame(re, context.bmain, scene, NULL, camera, scene->lay, frame, FALSE); /* restore previous state after it was toggled on & off by RE_BlenderFrame */ @@ -2440,7 +2462,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float } /* restore */ - context.scene->r.scemode |= do_seq; + scene->r.scemode |= do_seq; scene->r.cfra = oldcfra; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 96faec389df..72db34d339c 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -56,33 +56,16 @@ #include "BKE_mesh.h" #include "BKE_tessmesh.h" +/* for timing... */ +#if 0 +# include "PIL_time.h" +#else +# define TIMEIT_BENCH(expr, id) (expr) +#endif + /* Util macros */ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) -/* Benchmark macros */ -#if !defined(_WIN32) && 0 - -#include - -#define BENCH(a) \ - do { \ - double _t1, _t2; \ - struct timeval _tstart, _tend; \ - clock_t _clock_init = clock(); \ - gettimeofday ( &_tstart, NULL); \ - (a); \ - gettimeofday ( &_tend, NULL); \ - _t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); \ - _t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); \ - printf("%s: %fs (real) %fs (cpu)\n", #a, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\ - } while (0) - -#else - -#define BENCH(a) (a) - -#endif - /* get derived mesh */ /* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */ DerivedMesh *object_get_derived_final(Object *ob) @@ -143,7 +126,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) BVHTreeNearest nearest = NULL_BVHTreeNearest; - BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6)); + TIMEIT_BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6), bvhtree_verts); if (treeData.tree == NULL) { OUT_OF_MEMORY(); return; @@ -294,6 +277,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) /* Options about projection direction */ const char use_normal = calc->smd->shrinkOpts; + const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit; float proj_axis[3] = {0.0f, 0.0f, 0.0f}; /* Raycast and tree stuff */ @@ -410,6 +394,13 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) treeData.raycast_callback, &treeData); } + /* don't set the initial dist (which is more efficient), + * because its calculated in the targets space, we want the dist in our own space */ + if (proj_limit_squared != 0.0f) { + if (len_squared_v3v3(hit.co, co) > proj_limit_squared) { + hit.index = -1; + } + } if (hit.index != -1) { madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist); @@ -437,7 +428,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) BVHTreeNearest nearest = NULL_BVHTreeNearest; /* Create a bvh-tree of the given target */ - BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6)); + TIMEIT_BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6), bvhtree_faces); if (treeData.tree == NULL) { OUT_OF_MEMORY(); return; @@ -584,15 +575,15 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM if (calc.target) { switch (smd->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: - BENCH(shrinkwrap_calc_nearest_surface_point(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), deform_surface); break; case MOD_SHRINKWRAP_PROJECT: - BENCH(shrinkwrap_calc_normal_projection(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), deform_project); break; case MOD_SHRINKWRAP_NEAREST_VERTEX: - BENCH(shrinkwrap_calc_nearest_vertex(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), deform_vertex); break; } } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 443aed1fc41..53dfbdcfb85 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -165,7 +165,7 @@ void flame_get_spectrum(unsigned char *UNUSED(spec), int UNUSED(width), float UN void smoke_reallocate_fluid(SmokeDomainSettings *sds, float dx, int res[3], int free_old) { int use_heat = (sds->active_fields & SM_ACTIVE_HEAT); - int use_fire = (sds->active_fields & (SM_ACTIVE_HEAT | SM_ACTIVE_FIRE)); + int use_fire = (sds->active_fields & SM_ACTIVE_FIRE); int use_colors = (sds->active_fields & SM_ACTIVE_COLORS); if (free_old && sds->fluid) @@ -262,21 +262,21 @@ static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object * scale = res / size[0]; sds->scale = size[0] / ob->size[0]; sds->base_res[0] = res; - sds->base_res[1] = (int)(size[1] * scale + 0.5); - sds->base_res[2] = (int)(size[2] * scale + 0.5); + sds->base_res[1] = (int)(size[1] * scale + 0.5f); + sds->base_res[2] = (int)(size[2] * scale + 0.5f); } else if (size[1] > MAX2(size[0], size[2])) { scale = res / size[1]; sds->scale = size[1] / ob->size[1]; - sds->base_res[0] = (int)(size[0] * scale + 0.5); + sds->base_res[0] = (int)(size[0] * scale + 0.5f); sds->base_res[1] = res; - sds->base_res[2] = (int)(size[2] * scale + 0.5); + sds->base_res[2] = (int)(size[2] * scale + 0.5f); } else { scale = res / size[2]; sds->scale = size[2] / ob->size[2]; - sds->base_res[0] = (int)(size[0] * scale + 0.5); - sds->base_res[1] = (int)(size[1] * scale + 0.5); + sds->base_res[0] = (int)(size[0] * scale + 0.5f); + sds->base_res[1] = (int)(size[1] * scale + 0.5f); sds->base_res[2] = res; } @@ -1581,7 +1581,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value if (fuel && fuel[index]) { /* instead of using 1.0 for all new fuel add slight falloff * to reduce flow blockiness */ - float value = 1.0f - pow(1.0f - emission_value, 2.0f); + float value = 1.0f - powf(1.0f - emission_value, 2.0f); if (value > react[index]) { float f = fuel_flow / fuel[index]; @@ -1944,9 +1944,9 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, mul_v3_fl(retvel, mag); // TODO dg - do in force! - force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0); - force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0); - force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0); + force_x[index] = min_ff(max_ff(-1.0f, retvel[0] * 0.2f), 1.0f); + force_y[index] = min_ff(max_ff(-1.0f, retvel[1] * 0.2f), 1.0f); + force_z[index] = min_ff(max_ff(-1.0f, retvel[2] * 0.2f), 1.0f); } } } @@ -1999,7 +1999,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh * /* adapt timestep for different framerates, dt = 0.1 is at 25fps */ dt = DT_DEFAULT * (25.0f / fps); // maximum timestep/"CFL" constraint: dt < 5.0 *dx / maxVel - maxVel = (sds->dx * 5.0); + maxVel = (sds->dx * 5.0f); #if 0 for (i = 0; i < size; i++) { @@ -2009,7 +2009,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh * } #endif - maxVelMag = sqrt(maxVelMag) * dt * sds->time_scale; + maxVelMag = sqrtf(maxVelMag) * dt * sds->time_scale; totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */ totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps; totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps; @@ -2267,7 +2267,8 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object * } } -struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm){ +struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) +{ smokeModifier_process(smd, scene, ob, dm); /* return generated geometry for adaptive domain */ @@ -2285,7 +2286,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix const size_t index = smoke_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]); // T_ray *= T_vox - *tRay *= exp(input[index] * correct); + *tRay *= expf(input[index] * correct); if (result[index] < 0.0f) { @@ -2385,7 +2386,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene) float light[3]; int a, z, slabsize = sds->res[0] * sds->res[1], size = sds->res[0] * sds->res[1] * sds->res[2]; float *density = smoke_get_density(sds->fluid); - float correct = -7.0 * sds->dx; + float correct = -7.0f * sds->dx; if (!get_lamp(scene, light)) return; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index aad205bb5bf..af9d21d8cbc 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -353,17 +353,17 @@ void sound_load(struct Main *bmain, bSound *sound) } // XXX unused currently #if 0 - break; + break; + } + case SOUND_TYPE_BUFFER: + if (sound->child_sound && sound->child_sound->handle) + sound->handle = AUD_bufferSound(sound->child_sound->handle); + break; + case SOUND_TYPE_LIMITER: + if (sound->child_sound && sound->child_sound->handle) + sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end); + break; } - case SOUND_TYPE_BUFFER: - if (sound->child_sound && sound->child_sound->handle) - sound->handle = AUD_bufferSound(sound->child_sound->handle); - break; - case SOUND_TYPE_LIMITER: - if (sound->child_sound && sound->child_sound->handle) - sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end); - break; -} #endif if (sound->flags & SOUND_FLAGS_MONO) { void *handle = AUD_monoSound(sound->handle); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 8a669b89907..be8b572417e 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -3025,7 +3025,8 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) * when the ccgdm gets remade, the assumption is that the topology * does not change. */ ccgdm_create_grids(dm); - BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces); + BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces, + ccgdm->gridFlagMats, ccgdm->gridHidden); } ccgdm->pbvh = ob->sculpt->pbvh; diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c index 99e33594a3e..ff9774f85af 100644 --- a/source/blender/blenkernel/intern/suggestions.c +++ b/source/blender/blenkernel/intern/suggestions.c @@ -47,6 +47,7 @@ static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL}; static char *documentation = NULL; //static int doc_lines = 0; +/* TODO, replace with BLI_strncasecmp() */ static int txttl_cmp(const char *first, const char *second, int len) { int cmp, i; @@ -113,19 +114,18 @@ short texttool_text_is_active(Text *text) void texttool_suggest_add(const char *name, char type) { + const int len = strlen(name); + int cmp; SuggItem *newitem, *item; - int len, cmp; - newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem"); + newitem = MEM_mallocN(sizeof(SuggItem) + len + 1, "SuggItem"); if (!newitem) { printf("Failed to allocate memory for suggestion.\n"); return; } newitem->name = (char *) (newitem + 1); - len = strlen(name); - strncpy(newitem->name, name, len); - newitem->name[len] = '\0'; + memcpy(newitem->name, name, len + 1); newitem->type = type; newitem->prev = newitem->next = NULL; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index d230cf8f1fe..322b77e0462 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -96,17 +96,6 @@ * If the user moves the cursor the st containing that cursor should * be popped ... other st's retain their own top location. * - * Markers - * -- - * The mrk->flags define the behavior and relationships between markers. The - * upper two bytes are used to hold a group ID, the lower two are normal flags. If - * TMARK_EDITALL is set the group ID defines which other markers should be edited. - * - * The mrk->clr field is used to visually group markers where the flags may not - * match. A template system, for example, may allow editing of repeating tokens - * (in one group) but include other marked positions (in another group) all in the - * same template with the same color. - * * Undo * -- * Undo/Redo works by storing @@ -136,8 +125,7 @@ static void txt_pop_first(Text *text); static void txt_pop_last(Text *text); -static void txt_undo_add_op(Text *text, int op); -static void txt_undo_add_block(Text *text, int op, const char *buf); +static void txt_undo_add_blockop(Text *text, int op, const char *buf); static void txt_delete_line(Text *text, TextLine *line); static void txt_delete_sel(Text *text); static void txt_make_dirty(Text *text); @@ -175,7 +163,6 @@ void BKE_text_free(Text *text) } BLI_freelistN(&text->lines); - BLI_freelistN(&text->markers); if (text->name) MEM_freeN(text->name); MEM_freeN(text->undo_buf); @@ -203,7 +190,6 @@ Text *BKE_text_add(const char *name) ta->flags |= TXT_TABSTOSPACES; ta->lines.first = ta->lines.last = NULL; - ta->markers.first = ta->markers.last = NULL; tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line = (char *) MEM_mallocN(1, "textline_string"); @@ -399,7 +385,6 @@ Text *BKE_text_load(const char *file, const char *relpath) ta->id.us = 1; ta->lines.first = ta->lines.last = NULL; - ta->markers.first = ta->markers.last = NULL; ta->curl = ta->sell = NULL; if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0) @@ -496,7 +481,6 @@ Text *BKE_text_copy(Text *ta) tan->flags = ta->flags | TXT_ISDIRTY; tan->lines.first = tan->lines.last = NULL; - tan->markers.first = tan->markers.last = NULL; tan->curl = tan->sell = NULL; tan->nlines = ta->nlines; @@ -785,23 +769,6 @@ static void txt_curs_sel(Text *text, TextLine ***linep, int **charp) *linep = &text->sell; *charp = &text->selc; } -static void txt_curs_first(Text *text, TextLine **linep, int *charp) -{ - if (text->curl == text->sell) { - *linep = text->curl; - if (text->curc < text->selc) *charp = text->curc; - else *charp = text->selc; - } - else if (txt_get_span(text->lines.first, text->curl) < txt_get_span(text->lines.first, text->sell)) { - *linep = text->curl; - *charp = text->curc; - } - else { - *linep = text->sell; - *charp = text->selc; - } -} - /*****************************/ /* Cursor movement functions */ /*****************************/ @@ -843,13 +810,11 @@ void txt_move_up(Text *text, short sel) { TextLine **linep; int *charp; - /* int old; */ /* UNUSED */ if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - /* old = *charp; */ /* UNUSED */ if ((*linep)->prev) { int index = txt_utf8_offset_to_index((*linep)->line, *charp); @@ -857,8 +822,6 @@ void txt_move_up(Text *text, short sel) if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; else *charp = txt_utf8_index_to_offset((*linep)->line, index); - if (!undoing) - txt_undo_add_op(text, sel ? UNDO_SUP : UNDO_CUP); } else { txt_move_bol(text, sel); @@ -871,22 +834,17 @@ void txt_move_down(Text *text, short sel) { TextLine **linep; int *charp; - /* int old; */ /* UNUSED */ if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - /* old = *charp; */ /* UNUSED */ if ((*linep)->next) { int index = txt_utf8_offset_to_index((*linep)->line, *charp); *linep = (*linep)->next; if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; else *charp = txt_utf8_index_to_offset((*linep)->line, index); - - if (!undoing) - txt_undo_add_op(text, sel ? UNDO_SDOWN : UNDO_CDOWN); } else { txt_move_eol(text, sel); @@ -898,7 +856,7 @@ void txt_move_down(Text *text, short sel) void txt_move_left(Text *text, short sel) { TextLine **linep; - int *charp, oundoing = undoing; + int *charp; int tabsize = 0, i = 0; if (!text) return; @@ -906,8 +864,6 @@ void txt_move_left(Text *text, short sel) else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - undoing = 1; - if (*charp == 0) { if ((*linep)->prev) { txt_move_up(text, sel); @@ -939,24 +895,19 @@ void txt_move_left(Text *text, short sel) } } - undoing = oundoing; - if (!undoing) txt_undo_add_op(text, sel ? UNDO_SLEFT : UNDO_CLEFT); - if (!sel) txt_pop_sel(text); } void txt_move_right(Text *text, short sel) { TextLine **linep; - int *charp, oundoing = undoing, do_tab = FALSE, i; + int *charp, do_tab = FALSE, i; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - undoing = 1; - if (*charp == (*linep)->len) { if ((*linep)->next) { txt_move_down(text, sel); @@ -984,124 +935,103 @@ void txt_move_right(Text *text, short sel) else (*charp) += BLI_str_utf8_size((*linep)->line + *charp); } - undoing = oundoing; - if (!undoing) txt_undo_add_op(text, sel ? UNDO_SRIGHT : UNDO_CRIGHT); - if (!sel) txt_pop_sel(text); } void txt_jump_left(Text *text, short sel) { TextLine **linep; - int *charp, oldc; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - oldc = *charp; BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len, charp, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM); if (!sel) txt_pop_sel(text); - if (!undoing) { - int span = txt_get_span(text->lines.first, *linep); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp); - } } void txt_jump_right(Text *text, short sel) { TextLine **linep; - int *charp, oldc; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - oldc = *charp; BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len, charp, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM); if (!sel) txt_pop_sel(text); - if (!undoing) { - int span = txt_get_span(text->lines.first, *linep); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp); - } } void txt_move_bol(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *charp = 0; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_eol(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; - + *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_bof(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *linep = text->lines.first; *charp = 0; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_eof(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *linep = text->lines.last; *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_toline(Text *text, unsigned int line, short sel) @@ -1112,16 +1042,14 @@ void txt_move_toline(Text *text, unsigned int line, short sel) /* Moves to a certain byte in a line, not a certain utf8-character! */ void txt_move_to(Text *text, unsigned int line, unsigned int ch, short sel) { - TextLine **linep, *oldl; - int *charp, oldc; + TextLine **linep; + int *charp; unsigned int i; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - oldc = *charp; - oldl = *linep; *linep = text->lines.first; for (i = 0; i < line; i++) { @@ -1133,7 +1061,6 @@ void txt_move_to(Text *text, unsigned int line, unsigned int ch, short sel) *charp = ch; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } /****************************/ @@ -1152,8 +1079,6 @@ static void txt_curs_swap(Text *text) tmpc = text->curc; text->curc = text->selc; text->selc = tmpc; - - if (!undoing) txt_undo_add_op(text, UNDO_SWAP); } static void txt_pop_first(Text *text) @@ -1164,12 +1089,6 @@ static void txt_pop_first(Text *text) { txt_curs_swap(text); } - - if (!undoing) txt_undo_add_toop(text, UNDO_STO, - txt_get_span(text->lines.first, text->sell), - text->selc, - txt_get_span(text->lines.first, text->curl), - text->curc); txt_pop_sel(text); } @@ -1181,12 +1100,6 @@ static void txt_pop_last(Text *text) { txt_curs_swap(text); } - - if (!undoing) txt_undo_add_toop(text, UNDO_STO, - txt_get_span(text->lines.first, text->sell), - text->selc, - txt_get_span(text->lines.first, text->curl), - text->curc); txt_pop_sel(text); } @@ -1222,9 +1135,7 @@ int txt_has_sel(Text *text) static void txt_delete_sel(Text *text) { TextLine *tmpl; - TextMarker *mrk; char *buf; - int move, lineno; if (!text) return; if (!text->curl) return; @@ -1236,33 +1147,11 @@ static void txt_delete_sel(Text *text) if (!undoing) { buf = txt_sel_to_buf(text); - txt_undo_add_block(text, UNDO_DBLOCK, buf); + txt_undo_add_blockop(text, UNDO_DBLOCK, buf); MEM_freeN(buf); } buf = MEM_mallocN(text->curc + (text->sell->len - text->selc) + 1, "textline_string"); - - if (text->curl != text->sell) { - txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0); - move = txt_get_span(text->curl, text->sell); - } - else { - mrk = txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - if (mrk && (mrk->start > text->curc || mrk->end < text->selc)) - txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - move = 0; - } - - mrk = txt_find_marker_region(text, text->sell, text->selc - 1, text->sell->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - mrk->lineno -= move; - if (mrk->start > text->curc) mrk->start -= text->selc - text->curc; - mrk->end -= text->selc - text->curc; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } strncpy(buf, text->curl->line, text->curc); strcpy(buf + text->curc, text->sell->line + text->selc); @@ -1491,19 +1380,9 @@ char *txt_sel_to_buf(Text *text) return buf; } -static void txt_shift_markers(Text *text, int lineno, int count) -{ - TextMarker *marker; - - for (marker = text->markers.first; marker; marker = marker->next) - if (marker->lineno >= lineno) { - marker->lineno += count; - } -} - void txt_insert_buf(Text *text, const char *in_buffer) { - int l = 0, u, len, lineno = -1, count = 0; + int l = 0, u, len; size_t i = 0, j; TextLine *add; char *buffer; @@ -1517,7 +1396,7 @@ void txt_insert_buf(Text *text, const char *in_buffer) buffer = BLI_strdupn(in_buffer, len); len += txt_extended_ascii_as_utf8(&buffer); - if (!undoing) txt_undo_add_block(text, UNDO_IBLOCK, buffer); + if (!undoing) txt_undo_add_blockop(text, UNDO_IBLOCK, buffer); u = undoing; undoing = 1; @@ -1530,9 +1409,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) else { undoing = u; MEM_freeN(buffer); return; } i++; - /* Read as many full lines as we can */ - lineno = txt_get_span(text->lines.first, text->curl); - while (i < len) { l = 0; @@ -1544,14 +1420,8 @@ void txt_insert_buf(Text *text, const char *in_buffer) add = txt_new_linen(buffer + (i - l), l); BLI_insertlinkbefore(&text->lines, text->curl, add); i++; - count++; } else { - if (count) { - txt_shift_markers(text, lineno, count); - count = 0; - } - for (j = i - l; j < i && j < len; ) txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j)); break; @@ -1560,10 +1430,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) MEM_freeN(buffer); - if (count) { - txt_shift_markers(text, lineno, count); - } - undoing = u; } @@ -1599,6 +1465,7 @@ static void dump_buffer(Text *text) while (i++ < text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]); } +/* Note: this function is outdated and must be updated if needed for future use */ void txt_print_undo(Text *text) { int i = 0; @@ -1615,37 +1482,7 @@ void txt_print_undo(Text *text) while (i <= text->undo_pos) { op = text->undo_buf[i]; - if (op == UNDO_CLEFT) { - ops = "Cursor left"; - } - else if (op == UNDO_CRIGHT) { - ops = "Cursor right"; - } - else if (op == UNDO_CUP) { - ops = "Cursor up"; - } - else if (op == UNDO_CDOWN) { - ops = "Cursor down"; - } - else if (op == UNDO_SLEFT) { - ops = "Selection left"; - } - else if (op == UNDO_SRIGHT) { - ops = "Selection right"; - } - else if (op == UNDO_SUP) { - ops = "Selection up"; - } - else if (op == UNDO_SDOWN) { - ops = "Selection down"; - } - else if (op == UNDO_STO) { - ops = "Selection "; - } - else if (op == UNDO_CTO) { - ops = "Cursor "; - } - else if (op == UNDO_INSERT_1) { + if (op == UNDO_INSERT_1) { ops = "Insert ascii "; } else if (op == UNDO_INSERT_2) { @@ -1681,9 +1518,6 @@ void txt_print_undo(Text *text) else if (op == UNDO_DEL_4) { ops = "Delete unicode "; } - else if (op == UNDO_SWAP) { - ops = "Cursor swap"; - } else if (op == UNDO_DBLOCK) { ops = "Delete text block"; } @@ -1738,29 +1572,6 @@ void txt_print_undo(Text *text) } } } - else if (op == UNDO_STO || op == UNDO_CTO) { - i++; - - charp = text->undo_buf[i]; i++; - charp = charp + (text->undo_buf[i] << 8); i++; - - linep = text->undo_buf[i]; i++; - linep = linep + (text->undo_buf[i] << 8); i++; - linep = linep + (text->undo_buf[i] << 16); i++; - linep = linep + (text->undo_buf[i] << 24); i++; - - printf("to <%d, %d> ", linep, charp); - - charp = text->undo_buf[i]; i++; - charp = charp + (text->undo_buf[i] << 8); i++; - - linep = text->undo_buf[i]; i++; - linep = linep + (text->undo_buf[i] << 8); i++; - linep = linep + (text->undo_buf[i] << 16); i++; - linep = linep + (text->undo_buf[i] << 24); i++; - - printf("from <%d, %d>", linep, charp); - } else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) { i++; @@ -1811,16 +1622,6 @@ void txt_print_undo(Text *text) } } -static void txt_undo_add_op(Text *text, int op) -{ - if (!max_undo_test(text, 2)) - return; - - text->undo_pos++; - text->undo_buf[text->undo_pos] = op; - text->undo_buf[text->undo_pos + 1] = 0; -} - static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value) { undo_buf[*undo_pos] = (value) & 0xff; @@ -1841,17 +1642,41 @@ static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int va (*undo_pos)++; } -static void txt_undo_add_block(Text *text, int op, const char *buf) +/* store the cur cursor to the undo buffer */ +static void txt_undo_store_cur(Text *text) +{ + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->curc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->curl)); +} + +/* store the sel cursor to the undo buffer */ +static void txt_undo_store_sel(Text *text) +{ + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->selc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->sell)); +} + +/* store both cursors to the undo buffer */ +static void txt_undo_store_cursors(Text *text) +{ + txt_undo_store_cur(text); + txt_undo_store_sel(text); +} + +/* store an operator along with a block of data */ +static void txt_undo_add_blockop(Text *text, int op, const char *buf) { unsigned int length = strlen(buf); - if (!max_undo_test(text, length + 11)) + if (!max_undo_test(text, length + 11 + 12)) return; text->undo_pos++; text->undo_buf[text->undo_pos] = op; text->undo_pos++; + txt_undo_store_cursors(text); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length); strncpy(text->undo_buf + text->undo_pos, buf, length); @@ -1863,34 +1688,30 @@ static void txt_undo_add_block(Text *text, int op, const char *buf) text->undo_buf[text->undo_pos + 1] = 0; } -void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc) +/* store a regular operator */ +void txt_undo_add_op(Text *text, int op) { if (!max_undo_test(text, 15)) return; - if (froml == tol && fromc == toc) return; - text->undo_pos++; text->undo_buf[text->undo_pos] = op; text->undo_pos++; - txt_undo_store_uint16(text->undo_buf, &text->undo_pos, fromc); - txt_undo_store_uint32(text->undo_buf, &text->undo_pos, froml); - txt_undo_store_uint16(text->undo_buf, &text->undo_pos, toc); - txt_undo_store_uint32(text->undo_buf, &text->undo_pos, tol); + txt_undo_store_cursors(text); text->undo_buf[text->undo_pos] = op; - text->undo_buf[text->undo_pos + 1] = 0; } +/* store an operator for a single character */ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) { char utf8[BLI_UTF8_MAX]; size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8); - if (!max_undo_test(text, 3 + utf8_size)) + if (!max_undo_test(text, 3 + utf8_size + 12)) return; text->undo_pos++; @@ -1899,6 +1720,8 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) text->undo_buf[text->undo_pos] = op_start + utf8_size - 1; text->undo_pos++; + txt_undo_store_cur(text); + for (i = 0; i < utf8_size; i++) { text->undo_buf[text->undo_pos] = utf8[i]; text->undo_pos++; @@ -1909,6 +1732,9 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) else { text->undo_buf[text->undo_pos] = op_start + 3; text->undo_pos++; + + txt_undo_store_cursors(text); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c); text->undo_buf[text->undo_pos] = op_start + 3; } @@ -1934,6 +1760,29 @@ static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos) return val; } +/* read the cur cursor from the undo buffer */ +static void txt_undo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc) +{ + *curln = txt_undo_read_uint32(undo_buf, undo_pos); + *curc = txt_undo_read_uint16(undo_buf, undo_pos); +} + +/* read the sel cursor from the undo buffer */ +static void txt_undo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc) +{ + *selln = txt_undo_read_uint32(undo_buf, undo_pos); + *selc = txt_undo_read_uint16(undo_buf, undo_pos); +} + +/* read both cursors from the undo buffer */ +static void txt_undo_read_cursors(const char *undo_buf, int *undo_pos, + unsigned int *curln, unsigned short *curc, + unsigned int *selln, unsigned short *selc) +{ + txt_undo_read_sel(undo_buf, undo_pos, selln, selc); + txt_undo_read_cur(undo_buf, undo_pos, curln, curc); +} + static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) { unsigned int unicode; @@ -1986,6 +1835,29 @@ static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos) return val; } +/* redo read cur cursor from the undo buffer */ +static void txt_redo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc) +{ + *curc = txt_redo_read_uint16(undo_buf, undo_pos); + *curln = txt_redo_read_uint32(undo_buf, undo_pos); +} + +/* redo read sel cursor from the undo buffer */ +static void txt_redo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc) +{ + *selc = txt_redo_read_uint16(undo_buf, undo_pos); + *selln = txt_redo_read_uint32(undo_buf, undo_pos); +} + +/* redo read both cursors from the undo buffer */ +static void txt_redo_read_cursors(const char *undo_buf, int *undo_pos, + unsigned int *curln, unsigned short *curc, + unsigned int *selln, unsigned short *selc) +{ + txt_redo_read_cur(undo_buf, undo_pos, curln, curc); + txt_redo_read_sel(undo_buf, undo_pos, selln, selc); +} + static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) { unsigned int unicode; @@ -2024,9 +1896,10 @@ void txt_do_undo(Text *text) { int op = text->undo_buf[text->undo_pos]; unsigned int linep, i; + unsigned int uchar; + unsigned int curln, selln; + unsigned short curc, selc; unsigned short charp; - TextLine *holdl; - int holdc, holdln; char *buf; if (text->undo_pos < 0) { @@ -2038,88 +1911,60 @@ void txt_do_undo(Text *text) undoing = 1; switch (op) { - case UNDO_CLEFT: - txt_move_right(text, 0); - break; - - case UNDO_CRIGHT: - txt_move_left(text, 0); - break; - - case UNDO_CUP: - txt_move_down(text, 0); - break; - - case UNDO_CDOWN: - txt_move_up(text, 0); - break; - - case UNDO_SLEFT: - txt_move_right(text, 1); - break; - - case UNDO_SRIGHT: - txt_move_left(text, 1); - break; - - case UNDO_SUP: - txt_move_down(text, 1); - break; - - case UNDO_SDOWN: - txt_move_up(text, 1); - break; - - case UNDO_CTO: - case UNDO_STO: - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - - text->undo_pos--; - text->undo_pos--; - - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - - if (op == UNDO_CTO) { - txt_move_toline(text, linep, 0); - text->curc = charp; - txt_pop_sel(text); - } - else { - txt_move_toline(text, linep, 1); - text->selc = charp; - } - - text->undo_pos--; - break; - - case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: - txt_backspace_char(text); + case UNDO_INSERT_1: + case UNDO_INSERT_2: + case UNDO_INSERT_3: + case UNDO_INSERT_4: text->undo_pos -= op - UNDO_INSERT_1 + 1; - text->undo_pos--; - break; - - case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: - charp = op - UNDO_BS_1 + 1; - txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); - text->undo_pos--; - break; - case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: - charp = op - UNDO_DEL_1 + 1; - txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); - txt_move_left(text, 0); + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + txt_delete_char(text); + text->undo_pos--; break; - case UNDO_SWAP: - txt_curs_swap(text); + case UNDO_BS_1: + case UNDO_BS_2: + case UNDO_BS_3: + case UNDO_BS_4: + charp = op - UNDO_BS_1 + 1; + uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + txt_add_char(text, uchar); + + text->undo_pos--; + break; + + case UNDO_DEL_1: + case UNDO_DEL_2: + case UNDO_DEL_3: + case UNDO_DEL_4: + charp = op - UNDO_DEL_1 + 1; + uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + txt_add_char(text, uchar); + + txt_move_left(text, 0); + + text->undo_pos--; break; case UNDO_DBLOCK: + /* length of the string in the buffer */ linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); buf = MEM_mallocN(linep + 1, "dblock buffer"); @@ -2128,34 +1973,33 @@ void txt_do_undo(Text *text) text->undo_pos--; } buf[i] = 0; - - txt_curs_first(text, &holdl, &holdc); - holdln = txt_get_span(text->lines.first, holdl); - - txt_insert_buf(text, buf); - MEM_freeN(buf); - - text->curl = text->lines.first; - while (holdln > 0) { - if (text->curl->next) - text->curl = text->curl->next; - - holdln--; - } - text->curc = holdc; + /* skip over the length that was stored again */ text->undo_pos--; text->undo_pos--; text->undo_pos--; text->undo_pos--; + /* Get the cursor positions */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + + /* move cur to location that needs buff inserted */ + txt_move_to(text, curln, curc, 0); + + txt_insert_buf(text, buf); + MEM_freeN(buf); + + /* restore the cursors */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + text->undo_pos--; break; case UNDO_IBLOCK: + /* length of the string in the buffer */ linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - txt_delete_sel(text); /* txt_backspace_char removes utf8-characters, not bytes */ buf = MEM_mallocN(linep + 1, "iblock buffer"); @@ -2167,47 +2011,38 @@ void txt_do_undo(Text *text) linep = txt_utf8_len(buf); MEM_freeN(buf); - while (linep > 0) { - txt_backspace_char(text); - linep--; + /* skip over the length that was stored again */ + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + + /* get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + + if ((curln == selln) && (curc == selc)) { + for (i = 0; i < linep; i++) + txt_move_right(text, 1); } - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; + txt_delete_selected(text); text->undo_pos--; - break; case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the end line of the selection - - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - //charp is the last char selected or text->line->len - - //set the selection for this now - text->selc = charp; - text->sell = text->lines.first; - for (i = 0; i < linep; i++) { - text->sell = text->sell->next; - } - - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - //first line to be selected - - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - //first postion to be selected - text->curc = charp; - text->curl = text->lines.first; - for (i = 0; i < linep; i++) { - text->curl = text->curl->next; - } - + case UNDO_DUPLICATE: + case UNDO_MOVE_LINES_UP: + case UNDO_MOVE_LINES_DOWN: + /* get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); if (op == UNDO_INDENT) { txt_unindent(text); @@ -2221,37 +2056,24 @@ void txt_do_undo(Text *text) else if (op == UNDO_UNCOMMENT) { txt_comment(text); } + else if (op == UNDO_DUPLICATE) { + txt_delete_line(text, text->curl->next); + } + else if (op == UNDO_MOVE_LINES_UP) { + txt_move_lines(text, TXT_MOVE_LINE_DOWN); + } + else if (op == UNDO_MOVE_LINES_DOWN) { + txt_move_lines(text, TXT_MOVE_LINE_UP); + } text->undo_pos--; break; - case UNDO_DUPLICATE: - txt_delete_line(text, text->curl->next); - break; - case UNDO_MOVE_LINES_UP: - txt_move_lines(text, TXT_MOVE_LINE_DOWN); - break; - case UNDO_MOVE_LINES_DOWN: - txt_move_lines(text, TXT_MOVE_LINE_UP); - break; default: //XXX error("Undo buffer error - resetting"); text->undo_pos = -1; break; } - - /* next undo step may need evaluating */ - if (text->undo_pos >= 0) { - switch (text->undo_buf[text->undo_pos]) { - case UNDO_STO: - txt_do_undo(text); - txt_do_redo(text); /* selections need restoring */ - break; - case UNDO_SWAP: - txt_do_undo(text); /* swaps should appear transparent */ - break; - } - } undoing = 0; } @@ -2259,9 +2081,12 @@ void txt_do_undo(Text *text) void txt_do_redo(Text *text) { char op; - unsigned int linep, i; - unsigned short charp; char *buf; + unsigned int linep; + unsigned short charp; + unsigned int uchar; + unsigned int curln, selln; + unsigned short curc, selc; text->undo_pos++; op = text->undo_buf[text->undo_pos]; @@ -2274,104 +2099,91 @@ void txt_do_redo(Text *text) undoing = 1; switch (op) { - case UNDO_CLEFT: - txt_move_left(text, 0); - break; - - case UNDO_CRIGHT: - txt_move_right(text, 0); - break; - - case UNDO_CUP: - txt_move_up(text, 0); - break; - - case UNDO_CDOWN: - txt_move_down(text, 0); - break; - - case UNDO_SLEFT: - txt_move_left(text, 1); - break; - - case UNDO_SRIGHT: - txt_move_right(text, 1); - break; - - case UNDO_SUP: - txt_move_up(text, 1); - break; - - case UNDO_SDOWN: - txt_move_down(text, 1); - break; - - case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: + case UNDO_INSERT_1: + case UNDO_INSERT_2: + case UNDO_INSERT_3: + case UNDO_INSERT_4: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + charp = op - UNDO_INSERT_1 + 1; - txt_add_char(text, txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp)); + uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp); + + txt_add_char(text, uchar); break; - case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: + case UNDO_BS_1: + case UNDO_BS_2: + case UNDO_BS_3: + case UNDO_BS_4: text->undo_pos++; - txt_backspace_char(text); + + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + text->undo_pos += op - UNDO_BS_1 + 1; + + /* move right so we backspace the correct char */ + txt_move_right(text, 0); + txt_backspace_char(text); + break; - case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: + case UNDO_DEL_1: + case UNDO_DEL_2: + case UNDO_DEL_3: + case UNDO_DEL_4: text->undo_pos++; - txt_delete_char(text); + + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + text->undo_pos += op - UNDO_DEL_1 + 1; - break; - case UNDO_SWAP: - txt_curs_swap(text); - txt_do_redo(text); /* swaps should appear transparent a*/ - break; - - case UNDO_CTO: - case UNDO_STO: - text->undo_pos++; - text->undo_pos++; - - text->undo_pos++; - text->undo_pos++; - text->undo_pos++; - text->undo_pos++; - - text->undo_pos++; - - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - - if (op == UNDO_CTO) { - txt_move_toline(text, linep, 0); - text->curc = charp; - txt_pop_sel(text); - } - else { - txt_move_toline(text, linep, 1); - text->selc = charp; - } + txt_delete_char(text); break; case UNDO_DBLOCK: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + + /* length of the block */ linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - txt_delete_sel(text); text->undo_pos += linep; + /* skip over the length that was stored again */ text->undo_pos++; text->undo_pos++; text->undo_pos++; text->undo_pos++; + txt_delete_sel(text); + break; case UNDO_IBLOCK: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + /* length of the block */ linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); buf = MEM_mallocN(linep + 1, "iblock buffer"); @@ -2382,40 +2194,27 @@ void txt_do_redo(Text *text) txt_insert_buf(text, buf); MEM_freeN(buf); + /* skip over the length that was stored again */ text->undo_pos++; text->undo_pos++; text->undo_pos++; text->undo_pos++; + break; case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: + case UNDO_DUPLICATE: + case UNDO_MOVE_LINES_UP: + case UNDO_MOVE_LINES_DOWN: text->undo_pos++; - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - //charp is the first char selected or 0 - - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the first line of the selection - //set the selcetion for this now - text->curc = charp; - text->curl = text->lines.first; - for (i = 0; i < linep; i++) { - text->curl = text->curl->next; - } - - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - //last postion to be selected - - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //Last line to be selected - - text->selc = charp; - text->sell = text->lines.first; - for (i = 0; i < linep; i++) { - text->sell = text->sell->next; - } + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); if (op == UNDO_INDENT) { txt_indent(text); @@ -2429,15 +2228,28 @@ void txt_do_redo(Text *text) else if (op == UNDO_UNCOMMENT) { txt_uncomment(text); } - break; - case UNDO_DUPLICATE: - txt_duplicate_line(text); - break; - case UNDO_MOVE_LINES_UP: - txt_move_lines(text, TXT_MOVE_LINE_UP); - break; - case UNDO_MOVE_LINES_DOWN: - txt_move_lines(text, TXT_MOVE_LINE_DOWN); + else if (op == UNDO_DUPLICATE) { + txt_duplicate_line(text); + } + else if (op == UNDO_MOVE_LINES_UP) { + /* offset the cursor by + 1 */ + txt_move_to(text, curln + 1, curc, 0); + txt_move_to(text, selln + 1, selc, 1); + + txt_move_lines(text, TXT_MOVE_LINE_UP); + } + else if (op == UNDO_MOVE_LINES_DOWN) { + /* offset the cursor by - 1 */ + txt_move_to(text, curln - 1, curc, 0); + txt_move_to(text, selln - 1, selc, 1); + + txt_move_lines(text, TXT_MOVE_LINE_DOWN); + } + + /* re-restore the cursors since they got moved when redoing */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + break; default: //XXX error("Undo buffer error - resetting"); @@ -2456,31 +2268,15 @@ void txt_do_redo(Text *text) void txt_split_curline(Text *text) { TextLine *ins; - TextMarker *mrk; char *left, *right; - int lineno = -1; if (!text) return; if (!text->curl) return; txt_delete_sel(text); - /* Move markers */ - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk) { - if (mrk->lineno == lineno && mrk->start > text->curc) { - mrk->lineno++; - mrk->start -= text->curc; - mrk->end -= text->curc; - } - else if (mrk->lineno > lineno) { - mrk->lineno++; - } - mrk = mrk->next; - } - + if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n'); + /* Make the two half strings */ left = MEM_mallocN(text->curc + 1, "textline_string"); @@ -2512,28 +2308,13 @@ void txt_split_curline(Text *text) txt_clean_text(text); txt_pop_sel(text); - if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n'); } static void txt_delete_line(Text *text, TextLine *line) { - TextMarker *mrk = NULL, *nxt; - int lineno = -1; - if (!text) return; if (!text->curl) return; - lineno = txt_get_span(text->lines.first, line); - mrk = text->markers.first; - while (mrk) { - nxt = mrk->next; - if (mrk->lineno == lineno) - BLI_freelinkN(&text->markers, mrk); - else if (mrk->lineno > lineno) - mrk->lineno--; - mrk = nxt; - } - BLI_remlink(&text->lines, line); if (line->line) MEM_freeN(line->line); @@ -2548,25 +2329,12 @@ static void txt_delete_line(Text *text, TextLine *line) static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb) { char *tmp; - TextMarker *mrk = NULL; - int lineno = -1; - + if (!text) return; if (!linea || !lineb) return; - mrk = txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - mrk->lineno--; - mrk->start += linea->len; - mrk->end += linea->len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } - if (lineno == -1) lineno = txt_get_span(text->lines.first, lineb); - + tmp = MEM_mallocN(linea->len + lineb->len + 1, "textline_string"); strcpy(tmp, linea->line); @@ -2619,27 +2387,7 @@ void txt_delete_char(Text *text) } else { /* Just deleting a char */ size_t c_len = 0; - TextMarker *mrk; c = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len); - - mrk = txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); - if (mrk) { - int lineno = mrk->lineno; - if (mrk->end == text->curc) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } - else { - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start > text->curc) mrk->start -= c_len; - mrk->end -= c_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } memmove(text->curl->line + text->curc, text->curl->line + text->curc + c_len, text->curl->len - text->curc - c_len + 1); @@ -2683,28 +2431,8 @@ void txt_backspace_char(Text *text) } else { /* Just backspacing a char */ size_t c_len = 0; - TextMarker *mrk; char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc); c = BLI_str_utf8_as_unicode_and_size(prev, &c_len); - - mrk = txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); - if (mrk) { - int lineno = mrk->lineno; - if (mrk->start == text->curc) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } - else { - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start > text->curc - c_len) mrk->start -= c_len; - mrk->end -= c_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } /* source and destination overlap, don't use memcpy() */ memmove(text->curl->line + text->curc - c_len, @@ -2746,9 +2474,7 @@ static void txt_convert_tab_to_spaces(Text *text) static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) { - int lineno; char *tmp, ch[BLI_UTF8_MAX]; - TextMarker *mrk; size_t add_len; if (!text) return 0; @@ -2767,16 +2493,9 @@ static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) txt_delete_sel(text); + if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); + add_len = BLI_str_utf8_from_unicode(add, ch); - mrk = txt_find_marker_region(text, text->curl, text->curc - 1, text->curl->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - if (mrk->start > text->curc) mrk->start += add_len; - mrk->end += add_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } tmp = MEM_mallocN(text->curl->len + add_len + 1, "textline_string"); @@ -2793,7 +2512,6 @@ static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) txt_make_dirty(text); txt_clean_text(text); - if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); return 1; } @@ -2824,10 +2542,7 @@ int txt_replace_char(Text *text, unsigned int add) /* If text is selected or we're at the end of the line just use txt_add_char */ if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') { - int i = txt_add_char(text, add); - TextMarker *mrk = txt_find_marker(text, text->curl, text->curc, 0, 0); - if (mrk) BLI_freelinkN(&text->markers, mrk); - return i; + return txt_add_char(text, add); } del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size); @@ -2854,8 +2569,8 @@ int txt_replace_char(Text *text, unsigned int add) /* Should probably create a new op for this */ if (!undoing) { - txt_undo_add_charop(text, UNDO_DEL_1, del); txt_undo_add_charop(text, UNDO_INSERT_1, add); + txt_undo_add_charop(text, UNDO_DEL_1, del); } return 1; } @@ -2924,7 +2639,7 @@ void txt_indent(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_INDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_INDENT); } } @@ -2982,7 +2697,7 @@ void txt_unindent(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_UNINDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_UNINDENT); } } @@ -3031,7 +2746,7 @@ void txt_comment(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_COMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_COMMENT); } } @@ -3076,7 +2791,7 @@ void txt_uncomment(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_UNCOMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_UNCOMMENT); } } @@ -3165,157 +2880,6 @@ int setcurr_tab_spaces(Text *text, int space) return i; } -/*********************************/ -/* Text marker utility functions */ -/*********************************/ - -/* Creates and adds a marker to the list maintaining sorted order */ -void txt_add_marker(Text *text, TextLine *line, int start, int end, const unsigned char color[4], int group, int flags) -{ - TextMarker *tmp, *marker; - - marker = MEM_mallocN(sizeof(TextMarker), "text_marker"); - - marker->lineno = txt_get_span(text->lines.first, line); - marker->start = MIN2(start, end); - marker->end = MAX2(start, end); - marker->group = group; - marker->flags = flags; - - marker->color[0] = color[0]; - marker->color[1] = color[1]; - marker->color[2] = color[2]; - marker->color[3] = color[3]; - - for (tmp = text->markers.last; tmp; tmp = tmp->prev) - if (tmp->lineno < marker->lineno || (tmp->lineno == marker->lineno && tmp->start < marker->start)) - break; - - if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker); - else BLI_addhead(&text->markers, marker); -} - -/* Returns the first matching marker on the specified line between two points. - * If the group or flags fields are non-zero the returned flag must be in the - * specified group and have at least the specified flags set. */ -TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) -{ - TextMarker *marker, *next; - int lineno = txt_get_span(text->lines.first, line); - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start == marker->end && start <= marker->start && marker->start <= end) || - (marker->start < end && marker->end > start)) - { - return marker; - } - } - return NULL; -} - -/* Clears all markers on the specified line between two points. If the group or - * flags fields are non-zero the returned flag must be in the specified group - * and have at least the specified flags set. */ -short txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) -{ - TextMarker *marker, *next; - int lineno = txt_get_span(text->lines.first, line); - short cleared = 0; - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start == marker->end && start <= marker->start && marker->start <= end) || - (marker->start < end && marker->end > start)) - { - BLI_freelinkN(&text->markers, marker); - cleared = 1; - } - } - return cleared; -} - -/* Clears all markers in the specified group (if given) with at least the - * specified flags set. Useful for clearing temporary markers (group = 0, - * flags = TMARK_TEMP) */ -short txt_clear_markers(Text *text, int group, int flags) -{ - TextMarker *marker, *next; - short cleared = 0; - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if ((!group || marker->group == group) && - (marker->flags & flags) == flags) - { - BLI_freelinkN(&text->markers, marker); - cleared = 1; - } - } - return cleared; -} - -/* Finds the marker at the specified line and cursor position with at least the - * specified flags set in the given group (if non-zero). */ -TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int group, int flags) -{ - TextMarker *marker; - int lineno = txt_get_span(text->lines.first, line); - - for (marker = text->markers.first; marker; marker = marker->next) { - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if (marker->start <= curs && curs <= marker->end) - return marker; - } - return NULL; -} - -/* Finds the previous marker in the same group. If no other is found, the same - * marker will be returned */ -TextMarker *txt_prev_marker(Text *text, TextMarker *marker) -{ - TextMarker *tmp = marker; - while (tmp) { - if (tmp->prev) tmp = tmp->prev; - else tmp = text->markers.last; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if (marker == NULL) */ -} - -/* Finds the next marker in the same group. If no other is found, the same - * marker will be returned */ -TextMarker *txt_next_marker(Text *text, TextMarker *marker) -{ - TextMarker *tmp = marker; - while (tmp) { - if (tmp->next) tmp = tmp->next; - else tmp = text->markers.first; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if (marker == NULL) */ -} - - /*******************************/ /* Character utility functions */ /*******************************/ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 89446a1856f..30b48401046 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1124,10 +1124,10 @@ void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float { INIT_MINMAX2(min, max); - DO_MINMAX2(marker->pattern_corners[0], min, max); - DO_MINMAX2(marker->pattern_corners[1], min, max); - DO_MINMAX2(marker->pattern_corners[2], min, max); - DO_MINMAX2(marker->pattern_corners[3], min, max); + minmax_v2v2_v2(min, max, marker->pattern_corners[0]); + minmax_v2v2_v2(min, max, marker->pattern_corners[1]); + minmax_v2v2_v2(min, max, marker->pattern_corners[2]); + minmax_v2v2_v2(min, max, marker->pattern_corners[3]); } void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float framenr, float pos[2]) @@ -1624,6 +1624,9 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea double warped_position_x, warped_position_y; float *mask = NULL; + if (num_samples_x <= 0 || num_samples_y <= 0) + return NULL; + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); if (!search_ibuf->rect_float) { @@ -1690,10 +1693,15 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); - pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker, - FALSE, num_samples_x, num_samples_y, NULL); + if (search_ibuf) { + pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker, + FALSE, num_samples_x, num_samples_y, NULL); - IMB_freeImBuf(search_ibuf); + IMB_freeImBuf(search_ibuf); + } + else { + pattern_ibuf = NULL; + } return pattern_ibuf; } @@ -1718,6 +1726,9 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; + if (w <= 0 || h <= 0) + return NULL; + searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); @@ -2187,6 +2198,12 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE); + if (!searchibuf) { + *width_r = 0; + *height_r = 0; + return NULL; + } + width = searchibuf->x; height = searchibuf->y; @@ -2506,6 +2523,9 @@ int BKE_tracking_context_step(MovieTrackingContext *context) get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y); get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y); + if (!patch_new || !track_context->search_area) + continue; + /* run the tracker! */ tracked = libmv_trackRegion(&options, track_context->search_area, @@ -3141,7 +3161,7 @@ static int stabilization_median_point_get(MovieTracking *tracking, int framenr, if (track->flag & TRACK_USE_2D_STAB) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - DO_MINMAX2(marker->pos, min, max); + minmax_v2v2_v2(min, max, marker->pos); ok = TRUE; } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 3a8a14290dc..0f861a7ed37 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -111,6 +111,11 @@ static void delete_picture(AVFrame *f) } } +static int use_float_audio_buffer(int codec_id) +{ + return codec_id == CODEC_ID_AAC || codec_id == CODEC_ID_AC3 || codec_id == CODEC_ID_VORBIS; +} + #ifdef WITH_AUDASPACE static int write_audio_frame(void) { @@ -478,9 +483,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->time_base.den = 2997; c->time_base.num = 100; } - else if ((double) ((int) rd->frs_sec_base) == - rd->frs_sec_base) - { + else if ((float) ((int) rd->frs_sec_base) == rd->frs_sec_base) { c->time_base.den = rd->frs_sec; c->time_base.num = (int) rd->frs_sec_base; } @@ -601,12 +604,14 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex /* Prepare an audio stream for the output file */ -static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of) +static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size) { AVStream *st; AVCodecContext *c; AVCodec *codec; + error[0] = '\0'; + st = av_new_stream(of, 1); if (!st) return NULL; @@ -618,6 +623,10 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->bit_rate = ffmpeg_audio_bitrate * 1000; c->sample_fmt = AV_SAMPLE_FMT_S16; c->channels = rd->ffcodecdata.audio_channels; + if (use_float_audio_buffer(codec_id)) { + c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + c->sample_fmt = AV_SAMPLE_FMT_FLT; + } codec = avcodec_find_encoder(c->codec_id); if (!codec) { //XXX error("Couldn't find a valid audio codec"); @@ -628,6 +637,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex if (avcodec_open(c, codec) < 0) { //XXX error("Couldn't initialize audio codec"); + BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; } @@ -648,7 +658,12 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); - audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); + if (use_float_audio_buffer(codec_id)) { + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float)); + } + else { + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); + } audio_time = 0.0f; @@ -803,9 +818,12 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } if (ffmpeg_audio_codec != CODEC_ID_NONE) { - audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); + audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of, error, sizeof(error)); if (!audio_stream) { - BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); + if (error[0]) + BKE_report(reports, RPT_ERROR, error); + else + BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); av_dict_free(&opts); return 0; } @@ -945,7 +963,12 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, AVCodecContext *c = audio_stream->codec; AUD_DeviceSpecs specs; specs.channels = c->channels; - specs.format = AUD_FORMAT_S16; + if (use_float_audio_buffer(c->codec_id)) { + specs.format = AUD_FORMAT_FLOAT32; + } + else { + specs.format = AUD_FORMAT_S16; + } specs.rate = rd->ffcodecdata.audio_mixrate; audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE @@ -999,7 +1022,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i } #ifdef WITH_AUDASPACE - write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / rd->frs_sec_base)); + write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / (double)rd->frs_sec_base)); #endif return success; } diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index 84cfe89f1b8..a21778307c1 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -77,11 +77,13 @@ MEM_allocN_len(arr) / sizeof(*arr) \ ) +#define _bli_array_totalsize_static(arr) \ + (sizeof(_##arr##_static) / sizeof(*arr)) #define BLI_array_totalsize(arr) ( \ (size_t) \ (((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \ - (sizeof(_##arr##_static) / sizeof(*arr)) : \ + _bli_array_totalsize_static(arr) : \ BLI_array_totalsize_dyn(arr)) \ ) @@ -93,8 +95,18 @@ * * Allow for a large 'num' value when the new size is more then double * to allocate the exact sized array. */ -#define _bli_array_grow_items(arr, num) ( \ - (BLI_array_totalsize(arr) >= _##arr##_count + num) ? \ + +/* grow an array by a specified number of items */ +#define BLI_array_grow_items(arr, num) ( \ + (((void *)(arr) == NULL) && \ + ((void *)(_##arr##_static) != NULL) && \ + /* dont add _##arr##_count below because it must be zero */ \ + (_bli_array_totalsize_static(arr) >= _##arr##_count + num)) ? \ + /* we have an empty array and a static var big enough */ \ + ((arr = (void *)_##arr##_static), (_##arr##_count += (num))) \ + : \ + /* use existing static array or allocate */ \ + ((BLI_array_totalsize(arr) >= _##arr##_count + num) ? \ (_##arr##_count += num) : \ ( \ (void) (_##arr##_tmp = MEM_callocN( \ @@ -115,14 +127,7 @@ (void) (arr = _##arr##_tmp \ ), \ (_##arr##_count += num) \ - ) \ -) - -/* grow an array by a specified number of items */ -#define BLI_array_grow_items(arr, num) ( \ - ((void *)(arr) == NULL && (void *)(_##arr##_static) != NULL) ? \ - ((arr = (void *)_##arr##_static), (_##arr##_count += num)) : \ - _bli_array_grow_items(arr, num) \ + )) \ ) /* returns length of array */ diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h index a86b362c271..438bffb2fc5 100644 --- a/source/blender/blenlib/BLI_bpath.h +++ b/source/blender/blenlib/BLI_bpath.h @@ -48,6 +48,11 @@ void BLI_bpath_traverse_id_list(struct Main *bmain, struct ListBase *lb, BPathVi void BLI_bpath_traverse_main(struct Main *bmain, BPathVisitor visit_cb, const int flag, void *userdata); int BLI_bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src); +/* Functions for temp backup/restore of paths, path count must NOT change */ +void *BLI_bpath_list_backup(struct Main *bmain, const int flag); +void BLI_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle); +void BLI_bpath_list_free(void *ls_handle); + #define BLI_BPATH_TRAVERSE_ABS (1 << 0) /* convert paths to absolute */ #define BLI_BPATH_TRAVERSE_SKIP_LIBRARY (1 << 2) /* skip library paths */ #define BLI_BPATH_TRAVERSE_SKIP_PACKED (1 << 3) /* skip packed data */ diff --git a/source/blender/blenlib/BLI_endian_switch.h b/source/blender/blenlib/BLI_endian_switch.h index 7cb2790525d..f48b1b072c3 100644 --- a/source/blender/blenlib/BLI_endian_switch.h +++ b/source/blender/blenlib/BLI_endian_switch.h @@ -29,8 +29,7 @@ #ifdef __GNUC__ # define ATTR_ENDIAN_SWITCH \ - __attribute__((nonnull(1))) \ - __attribute__((pure)) + __attribute__((nonnull(1))) #else # define ATTR_ENDIAN_SWITCH #endif diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h index 4bc6d3828b9..358206f1177 100644 --- a/source/blender/blenlib/BLI_endian_switch_inline.h +++ b/source/blender/blenlib/BLI_endian_switch_inline.h @@ -38,41 +38,43 @@ /* *** 16 *** */ BLI_INLINE void BLI_endian_switch_int16(short *val) { - short tval = *val; - *val = (tval >> 8) | - (tval << 8); - + BLI_endian_switch_uint16((unsigned short *)val); } BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) { - BLI_endian_switch_int16((short *)val); + unsigned short tval = *val; + *val = (tval >> 8) | + (tval << 8); } /* *** 32 *** */ BLI_INLINE void BLI_endian_switch_int32(int *val) { - int tval = *val; + BLI_endian_switch_uint32((unsigned int *)val); +} +BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) +{ + unsigned int tval = *val; *val = ((tval >> 24)) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | ((tval << 24)); - -} -BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) -{ - BLI_endian_switch_int32((int *)val); } BLI_INLINE void BLI_endian_switch_float(float *val) { - BLI_endian_switch_int32((int *)val); + BLI_endian_switch_uint32((unsigned int *)val); } /* *** 64 *** */ BLI_INLINE void BLI_endian_switch_int64(int64_t *val) { - int64_t tval = *val; + BLI_endian_switch_uint64((uint64_t *)val); +} +BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) +{ + uint64_t tval = *val; *val = ((tval >> 56)) | ((tval << 40) & 0x00ff000000000000ll) | ((tval << 24) & 0x0000ff0000000000ll) | @@ -82,13 +84,9 @@ BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ((tval >> 40) & 0x000000000000ff00ll) | ((tval << 56)); } -BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) -{ - BLI_endian_switch_int64((int64_t *)val); -} BLI_INLINE void BLI_endian_switch_double(double *val) { - BLI_endian_switch_int64((int64_t *)val); + BLI_endian_switch_uint64((uint64_t *)val); } #endif /* __BLI_ENDIAN_SWITCH_INLINE_H__ */ diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index c26e6cd15b3..7eac1425a5c 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -71,7 +71,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val); void *BLI_ghash_lookup(GHash *gh, const void *key); int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); -int BLI_ghash_haskey(GHash *gh, void *key); +int BLI_ghash_haskey(GHash *gh, const void *key); int BLI_ghash_size(GHash *gh); /* *** */ diff --git a/source/blender/blenlib/BLI_math.h b/source/blender/blenlib/BLI_math.h index 89c37daae84..db2fed433da 100644 --- a/source/blender/blenlib/BLI_math.h +++ b/source/blender/blenlib/BLI_math.h @@ -58,6 +58,7 @@ #include "BLI_math_rotation.h" #include "BLI_math_vector.h" #include "BLI_math_geom.h" +#include "BLI_math_interp.h" #endif /* __BLI_MATH_H__ */ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 2b513cbec41..69d6478e0e2 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -170,7 +170,7 @@ } (void)0 #endif -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_base_inline.c" #endif @@ -203,7 +203,7 @@ MINLINE int is_power_of_2_i(int n); MINLINE int power_of_2_max_i(int n); MINLINE int power_of_2_min_i(int n); -MINLINE float shell_angle_to_dist(float angle); +MINLINE float shell_angle_to_dist(const float angle); #if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS) extern double copysign(double x, double y); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 7c8bf88943d..c71463da61d 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -121,7 +121,7 @@ MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3] void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power); -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_color_inline.c" #endif diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 80169e952bf..cfd163d4e57 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -36,7 +36,7 @@ extern "C" { #include "BLI_math_inline.h" -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_geom_inline.c" #endif @@ -187,6 +187,10 @@ int barycentric_inside_triangle_v2(const float w[3]); void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]); void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); +/* use to find the point of a UV on a face */ +void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]); +void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3]); + /***************************** View & Projection *****************************/ void lookat_m4(float mat[4][4], float vx, float vy, diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h index ce43d5fb941..6dad44644f2 100644 --- a/source/blender/blenlib/BLI_math_inline.h +++ b/source/blender/blenlib/BLI_math_inline.h @@ -35,9 +35,10 @@ extern "C" { #endif /* add platform/compiler checks here if it is not supported */ -#define __BLI_MATH_INLINE_H__ +/* all platforms support forcing inline so this is always enabled */ +#define BLI_MATH_DO_INLINE 1 -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE # ifdef _MSC_VER # define MINLINE static __forceinline # define MALWAYS_INLINE MINLINE diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h new file mode 100644 index 00000000000..21975763779 --- /dev/null +++ b/source/blender/blenlib/BLI_math_interp.h @@ -0,0 +1,44 @@ +/* + * ***** 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) 2012 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef BLI_MATH_INTERP +#define BLI_MATH_INTERP + +void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v); + +void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v); + +void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v); + +void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v); + +#endif diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 9e34631d460..f51bd1cf840 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -36,14 +36,18 @@ extern "C" { /********************************* Init **************************************/ -#define MAT4_UNITY {{ 1.0, 0.0, 0.0, 0.0}, \ - { 0.0, 1.0, 0.0, 0.0}, \ - { 0.0, 0.0, 1.0, 0.0}, \ - { 0.0, 0.0, 0.0, 1.0}} +#define MAT4_UNITY { \ + { 1.0, 0.0, 0.0, 0.0}, \ + { 0.0, 1.0, 0.0, 0.0}, \ + { 0.0, 0.0, 1.0, 0.0}, \ + { 0.0, 0.0, 0.0, 1.0} \ +} -#define MAT3_UNITY {{ 1.0, 0.0, 0.0}, \ - { 0.0, 1.0, 0.0}, \ - { 0.0, 0.0, 1.0}} +#define MAT3_UNITY { \ + { 1.0, 0.0, 0.0}, \ + { 0.0, 1.0, 0.0}, \ + { 0.0, 0.0, 1.0} \ +} void zero_m3(float R[3][3]); void zero_m4(float R[4][4]); @@ -98,6 +102,9 @@ void mul_m3_fl(float R[3][3], float f); void mul_m4_fl(float R[4][4], float f); void mul_mat3_m4_fl(float R[4][4], float f); +int invert_m3_ex(float m[3][3], const float epsilon); +int invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon); + int invert_m3(float R[3][3]); int invert_m3_m3(float R[3][3], float A[3][3]); int invert_m4(float R[4][4]); diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 77c0ec0a88f..f4572afec84 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -36,7 +36,7 @@ extern "C" { #include "BLI_math_inline.h" -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_vector_inline.c" #endif @@ -169,6 +169,7 @@ void interp_v4_v4v4v4v4(float p[4], const float v1[4], const float v2[4], const void mid_v3_v3v3(float r[3], const float a[3], const float b[3]); void mid_v2_v2v2(float r[2], const float a[2], const float b[2]); +void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]); /********************************* Comparison ********************************/ diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenlib/BLI_pbvh.h index 9483d068bb9..59ecdb359c9 100644 --- a/source/blender/blenlib/BLI_pbvh.h +++ b/source/blender/blenlib/BLI_pbvh.h @@ -153,7 +153,8 @@ void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]); void BLI_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]); void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface); void BLI_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems, - struct DMGridAdjacency *gridadj, void **gridfaces); + struct DMGridAdjacency *gridadj, void **gridfaces, + struct DMFlagMat *flagmats, unsigned int **grid_hidden); /* vertex deformer */ float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3]; diff --git a/source/blender/blenlib/BLI_quadric.h b/source/blender/blenlib/BLI_quadric.h index aec11ec2b44..e71a6473852 100644 --- a/source/blender/blenlib/BLI_quadric.h +++ b/source/blender/blenlib/BLI_quadric.h @@ -51,6 +51,6 @@ void BLI_quadric_mul(Quadric *a, const float scalar); /* solve */ float BLI_quadric_evaluate(const Quadric *q, const float v[3]); -int BLI_quadric_optimize(const Quadric *q, float v[3]); +int BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon); #endif /* __BLI_QUADRIC_H__ */ diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h index f84820e94f3..f2e26093711 100644 --- a/source/blender/blenlib/BLI_rect.h +++ b/source/blender/blenlib/BLI_rect.h @@ -33,6 +33,9 @@ * \ingroup bli */ +#include "DNA_vec_types.h" +#include "BLI_utildefines.h" + struct rctf; struct rcti; @@ -75,17 +78,6 @@ void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src); void print_rctf(const char *str, const struct rctf *rect); void print_rcti(const char *str, const struct rcti *rect); -/* hrmf, we need to work out this inline stuff */ -#if defined(_MSC_VER) -# define BLI_INLINE static __forceinline -#elif defined(__GNUC__) -# define BLI_INLINE static inline __attribute((always_inline)) -#else -/* #warning "MSC/GNUC defines not found, inline non-functional" */ -# define BLI_INLINE static -#endif - -#include "DNA_vec_types.h" BLI_INLINE float BLI_rcti_cent_x_fl(const struct rcti *rct) { return (float)(rct->xmin + rct->xmax) / 2.0f; } BLI_INLINE float BLI_rcti_cent_y_fl(const struct rcti *rct) { return (float)(rct->ymin + rct->ymax) / 2.0f; } BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct) { return (rct->xmin + rct->xmax) / 2; } diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index 892afdd0b27..c8fd72bbbd2 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -94,9 +94,18 @@ typedef struct ScanFillFace { struct ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]); struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2); +enum { + BLI_SCANFILL_CALC_QUADTRI_FASTPATH = (1 << 0), + + /* note: using BLI_SCANFILL_CALC_REMOVE_DOUBLES + * Assumes ordered edges, otherwise we risk an eternal loop + * removing double verts. - campbell */ + BLI_SCANFILL_CALC_REMOVE_DOUBLES = (1 << 1), +}; + int BLI_scanfill_begin(ScanFillContext *sf_ctx); -int BLI_scanfill_calc(ScanFillContext *sf_ctx, const short do_quad_tri_speedup); -int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup, +int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag); +int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]); void BLI_scanfill_end(ScanFillContext *sf_ctx); diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 73f138a750d..ecbc4cb1cd4 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -37,6 +37,7 @@ int BLI_utf8_invalid_byte(const char *str, int length); int BLI_utf8_invalid_strip(char *str, int length); int BLI_str_utf8_size(const char *p); /* warning, can return -1 on bad chars */ +int BLI_str_utf8_size_safe(const char *p); /* copied from glib */ unsigned int BLI_str_utf8_as_unicode(const char *p); unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index); diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 9cd801f819d..ec8e567c0ef 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -37,6 +37,10 @@ extern "C" { #include +#ifdef __APPLE__ +#include +#endif + /* for tables, button in UI, etc */ #define BLENDER_MAX_THREADS 64 @@ -92,6 +96,19 @@ void BLI_mutex_lock(ThreadMutex *mutex); void BLI_mutex_unlock(ThreadMutex *mutex); void BLI_mutex_end(ThreadMutex *mutex); +/* Spin Lock */ + +#ifdef __APPLE__ +typedef OSSpinLock SpinLock; +#else +typedef pthread_spinlock_t SpinLock; +#endif + +void BLI_spin_init(SpinLock *spin); +void BLI_spin_lock(SpinLock *spin); +void BLI_spin_unlock(SpinLock *spin); +void BLI_spin_end(SpinLock *spin); + /* Read/Write Mutex Lock */ #define THREAD_LOCK_READ 1 diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 056fa916da1..7c3b70545d6 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -257,6 +257,15 @@ #define IN_RANGE(a, b, c) ((b < c) ? ((b < a && a < c) ? 1 : 0) : ((c < a && a < b) ? 1 : 0)) #define IN_RANGE_INCL(a, b, c) ((b < c) ? ((b <= a && a <= c) ? 1 : 0) : ((c <= a && a <= b) ? 1 : 0)) +/* unpack vector for args */ +#define UNPACK2(a) ((a)[0]), ((a)[1]) +#define UNPACK3(a) ((a)[0]), ((a)[1]), ((a)[2]) +#define UNPACK4(a) ((a)[0]), ((a)[1]), ((a)[2]), ((a)[3]) +/* op may be '&' or '*' */ +#define UNPACK2OP(a, op) op((a)[0]), op((a)[1]) +#define UNPACK3OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]) +#define UNPACK4OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3]) + /* array helpers */ #define ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot) \ (arr_dtype *)((char *)arr_start + (elem_size * (tot - 1))) @@ -315,11 +324,13 @@ /*little macro so inline keyword works*/ #if defined(_MSC_VER) # define BLI_INLINE static __forceinline -#elif defined(__GNUC__) -# define BLI_INLINE static inline __attribute((always_inline)) #else -/* #warning "MSC/GNUC defines not found, inline non-functional" */ -# define BLI_INLINE static +# if (defined(__APPLE__) && defined(__ppc__)) +/* static inline __attribute__ here breaks osx ppc gcc42 build */ +# define BLI_INLINE static __attribute__((always_inline)) +# else +# define BLI_INLINE static inline __attribute__((always_inline)) +# endif #endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 6839f05bfbc..8a3b1c9675b 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -70,6 +70,7 @@ set(SRC intern/math_color_inline.c intern/math_geom.c intern/math_geom_inline.c + intern/math_interp.c intern/math_matrix.c intern/math_rotation.c intern/math_vector.c @@ -127,6 +128,7 @@ set(SRC BLI_math_color.h BLI_math_geom.h BLI_math_inline.h + BLI_math_interp.h BLI_math_matrix.h BLI_math_rotation.h BLI_math_vector.h @@ -173,3 +175,9 @@ if(WIN32) endif() blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}") + +if(MSVC) + # Quiet warning about inline math library files that do not export symbols. + # (normally you'd exclude from project, but we still want to see the files in MSVC) + set_target_properties(bf_blenlib PROPERTIES STATIC_LIBRARY_FLAGS /ignore:4221) +endif() diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h index b8f895c5c82..c3e7e8486d9 100644 --- a/source/blender/blenlib/PIL_time.h +++ b/source/blender/blenlib/PIL_time.h @@ -20,7 +20,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ @@ -76,6 +76,17 @@ void PIL_sleep_ms(int ms); fflush(stdout); \ } (void)0 +/** + * Given some function/expression: + * TIMEIT_BENCH(some_function(), some_unique_description); + */ +#define TIMEIT_BENCH(expr, id) \ + { \ + TIMEIT_START(id); \ + (expr); \ + TIMEIT_END(id); \ + } (void)0 + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 0cae9bab531..c4094920c2a 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -178,7 +178,7 @@ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) return NULL; } -int BLI_ghash_haskey(GHash *gh, void *key) +int BLI_ghash_haskey(GHash *gh, const void *key) { unsigned int hash = gh->hashfp(key) % gh->nbuckets; Entry *e; diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 70617453eff..6cf167b8823 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1117,7 +1117,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap) * max_ii(tree1->totleaf, tree2->totleaf)); data[j]->tree1 = tree1; data[j]->tree2 = tree2; - data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf); + data[j]->max_overlap = max_ii(tree1->totleaf, tree2->totleaf); data[j]->i = 0; data[j]->start_axis = min_axis(tree1->start_axis, tree2->start_axis); data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); @@ -1410,7 +1410,7 @@ static float ray_nearest_hit(BVHRayCastData *data, const float bv[6]) * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] * - * TODO this doens't has data->ray.radius in consideration */ + * TODO this doesn't take data->ray.radius into consideration */ static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node) { const float *bv = node->bv; diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 8ae2b941fa8..c650438a31e 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -64,6 +64,8 @@ #include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_text_types.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" #include "DNA_texture_types.h" #include "DNA_vfont_types.h" #include "DNA_scene_types.h" @@ -76,6 +78,7 @@ #include "BKE_font.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_node.h" #include "BKE_report.h" #include "BKE_sequencer.h" #include "BKE_image.h" /* so we can check the image's type */ @@ -382,7 +385,6 @@ static int rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *ab /* Run visitor function 'visit' on all paths contained in 'id'. */ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data) { - Image *ima; const char *absbase = (flag & BLI_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL; if ((flag & BLI_BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) { @@ -391,6 +393,8 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int switch (GS(id->name)) { case ID_IM: + { + Image *ima; ima = (Image *)id; if (ima->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) { if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { @@ -398,15 +402,20 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } } break; + } case ID_BR: { Brush *brush = (Brush *)id; if (brush->icon_filepath[0]) { rewrite_path_fixed(brush->icon_filepath, visit_cb, absbase, bpath_user_data); } + break; } - break; case ID_OB: + { + Object *ob = (Object *)id; + ModifierData *md; + ParticleSystem *psys; #define BPATH_TRAVERSE_POINTCACHE(ptcaches) \ { \ @@ -421,62 +430,56 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } \ } (void)0 - - { - Object *ob = (Object *)id; - ModifierData *md; - ParticleSystem *psys; - - /* do via modifiers instead */ + /* do via modifiers instead */ #if 0 - if (ob->fluidsimSettings) { - rewrite_path_fixed(ob->fluidsimSettings->surfdataPath, visit_cb, absbase, bpath_user_data); - } + if (ob->fluidsimSettings) { + rewrite_path_fixed(ob->fluidsimSettings->surfdataPath, visit_cb, absbase, bpath_user_data); + } #endif - for (md = ob->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_Fluidsim) { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)md; - if (fluidmd->fss) { - rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data); - } - } - else if (md->type == eModifierType_Smoke) { - SmokeModifierData *smd = (SmokeModifierData *)md; - if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { - BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]); - } - } - else if (md->type == eModifierType_Cloth) { - ClothModifierData *clmd = (ClothModifierData *) md; - BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches); - } - else if (md->type == eModifierType_Ocean) { - OceanModifierData *omd = (OceanModifierData *) md; - rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data); + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Fluidsim) { + FluidsimModifierData *fluidmd = (FluidsimModifierData *)md; + if (fluidmd->fss) { + rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data); } } + else if (md->type == eModifierType_Smoke) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { + BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]); + } + } + else if (md->type == eModifierType_Cloth) { + ClothModifierData *clmd = (ClothModifierData *) md; + BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches); + } + else if (md->type == eModifierType_Ocean) { + OceanModifierData *omd = (OceanModifierData *) md; + rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data); + } + } - if (ob->soft) { - BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches); - } + if (ob->soft) { + BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches); + } - for (psys = ob->particlesystem.first; psys; psys = psys->next) { - BPATH_TRAVERSE_POINTCACHE(psys->ptcaches); - } + for (psys = ob->particlesystem.first; psys; psys = psys->next) { + BPATH_TRAVERSE_POINTCACHE(psys->ptcaches); } #undef BPATH_TRAVERSE_POINTCACHE break; + } case ID_SO: { bSound *sound = (bSound *)id; if (sound->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) { rewrite_path_fixed(sound->name, visit_cb, absbase, bpath_user_data); } + break; } - break; case ID_TXT: if (((Text *)id)->name) { rewrite_path_alloc(&((Text *)id)->name, visit_cb, absbase, bpath_user_data); @@ -490,17 +493,49 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int rewrite_path_fixed(((VFont *)id)->name, visit_cb, absbase, bpath_user_data); } } + break; + } + case ID_MA: + { + Material *ma = (Material *)id; + bNodeTree *ntree = ma->nodetree; + + if (ntree) { + bNode *node; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_SCRIPT) { + NodeShaderScript *nss = (NodeShaderScript *)node->storage; + rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data); + } + } + } + break; + } + case ID_NT: + { + bNodeTree *ntree = (bNodeTree *)id; + bNode *node; + + if (ntree->type == NTREE_SHADER) { + /* same as lines above */ + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_SCRIPT) { + NodeShaderScript *nss = (NodeShaderScript *)node->storage; + rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data); + } + } + } + break; } - break; case ID_TE: { Tex *tex = (Tex *)id; if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format)) { rewrite_path_fixed(tex->vd->source_path, visit_cb, absbase, bpath_user_data); } + break; } - break; - case ID_SCE: { Scene *scene = (Scene *)id; @@ -539,30 +574,30 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } SEQ_END } + break; } - break; case ID_ME: { Mesh *me = (Mesh *)id; if (me->ldata.external) { rewrite_path_fixed(me->ldata.external->filename, visit_cb, absbase, bpath_user_data); } + break; } - break; case ID_LI: { Library *lib = (Library *)id; if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) { BKE_library_filepath_set(lib, lib->name); } + break; } - break; case ID_MC: { MovieClip *clip = (MovieClip *)id; rewrite_path_fixed(clip->name, visit_cb, absbase, bpath_user_data); + break; } - break; default: /* Nothing to do for other IDs that don't contain file paths. */ break; @@ -618,3 +653,73 @@ int BLI_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *pat return FALSE; } } + + +/* -------------------------------------------------------------------- */ +/** + * Backup/Restore/Free functions, + * \note These functions assume the data won't chane order. + */ + +struct PathStore { + struct PathStore *next, *prev; +} PathStore; + +static int bpath_list_append(void *userdata, char *UNUSED(path_dst), const char *path_src) +{ + /* store the path and string in a single alloc */ + ListBase *ls = userdata; + size_t path_size = strlen(path_src) + 1; + struct PathStore *path_store = MEM_mallocN(sizeof(PathStore) + path_size, __func__); + char *filepath = (char *)(path_store + 1); + + memcpy(filepath, path_src, path_size); + BLI_addtail(ls, path_store); + return FALSE; +} + +static int bpath_list_restore(void *userdata, char *path_dst, const char *path_src) +{ + /* assume ls->first wont be NULL because the number of paths can't change! + * (if they do caller is wrong) */ + ListBase *ls = userdata; + struct PathStore *path_store = ls->first; + const char *filepath = (char *)(path_store + 1); + int ret; + + if (strcmp(path_src, filepath) == 0) { + ret = FALSE; + } + else { + BLI_strncpy(path_dst, filepath, FILE_MAX); + ret = TRUE; + } + + BLI_freelinkN(ls, path_store); + return ret; +} + +/* return ls_handle */ +void *BLI_bpath_list_backup(Main *bmain, const int flag) +{ + ListBase *ls = MEM_callocN(sizeof(ListBase), __func__); + + BLI_bpath_traverse_main(bmain, bpath_list_append, flag, ls); + + return ls; +} + +void BLI_bpath_list_restore(Main *bmain, const int flag, void *ls_handle) +{ + ListBase *ls = ls_handle; + + BLI_bpath_traverse_main(bmain, bpath_list_restore, flag, ls); +} + +void BLI_bpath_list_free(void *ls_handle) +{ + ListBase *ls = ls_handle; + BLI_assert(ls->first == NULL); /* assumes we were used */ + BLI_freelistN(ls); + MEM_freeN(ls); +} diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index f27da759482..b9866f9c6e6 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -27,6 +27,8 @@ * \ingroup bli */ +#ifndef __MATH_BASE_INLINE_C__ +#define __MATH_BASE_INLINE_C__ #include #include @@ -35,9 +37,6 @@ #include "BLI_math.h" -#ifndef __MATH_BASE_INLINE_C__ -#define __MATH_BASE_INLINE_C__ - /* A few small defines. Keep'em local! */ #define SMALL_NUMBER 1.e-8f @@ -139,6 +138,25 @@ MINLINE int power_of_2_min_i(int n) return n; } +MINLINE unsigned int highest_order_bit_i(unsigned int n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + return n - (n >> 1); +} + +MINLINE unsigned short highest_order_bit_s(unsigned short n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + return n - (n >> 1); +} + MINLINE float min_ff(float a, float b) { return (a < b) ? a : b; diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index f520b2318e5..4c8bd43ef73 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -164,7 +164,11 @@ MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const f for (i = 0; i < 3; ++i) { t = linear[i] * inv_alpha; - srgb[i] = (t < 1.0f) ? (unsigned short) (to_srgb_table_lookup(t) * alpha) : FTOUSHORT(linearrgb_to_srgb(t) * alpha); + srgb[i] = (t <= 1.0f) ? + /* warning - converts: float -> short -> float -> short */ + (unsigned short) (to_srgb_table_lookup(t) * alpha) : + /* if FTOUSHORT was an inline function this could be done less confusingly */ + ((t = linearrgb_to_srgb(t) * alpha), FTOUSHORT(t)); } srgb[3] = FTOUSHORT(linear[3]); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index e10229f11da..74abd7e8c7e 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1453,9 +1453,16 @@ float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3 float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]) { float h[2], u[2]; + float dot; sub_v2_v2v2(u, l2, l1); sub_v2_v2v2(h, p, l1); +#if 0 return (dot_v2v2(u, h) / dot_v2v2(u, u)); +#else + /* better check for zero */ + dot = dot_v2v2(u, u); + return (dot != 0.0f) ? (dot_v2v2(u, h) / dot) : 0.0f; +#endif } /* ensure the distance between these points is no greater then 'dist' @@ -2399,6 +2406,33 @@ void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const #undef IS_ZERO +/* reverse of the functions above */ +void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]) +{ + float vec[3]; + + copy_v3_v3(res, data[0]); + mul_v3_fl(res, (1 - u) * (1 - v)); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, u * (1 - v)); add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, u * v); add_v3_v3(res, vec); + copy_v3_v3(vec, data[3]); + mul_v3_fl(vec, (1 - u) * v); add_v3_v3(res, vec); +} + +void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3]) +{ + float vec[3]; + + copy_v3_v3(res, data[0]); + mul_v3_fl(res, u); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, v); add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, 1.0f - u - v); add_v3_v3(res, vec); +} + /***************************** View & Projection *****************************/ void orthographic_m4(float matrix[][4], const float left, const float right, const float bottom, const float top, diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c index 01585c93bc8..ba9770e1bd1 100644 --- a/source/blender/blenlib/intern/math_geom_inline.c +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -27,11 +27,12 @@ * \ingroup bli */ +#ifndef __MATH_GEOM_INLINE_C__ +#define __MATH_GEOM_INLINE_C__ #include "BLI_math.h" -#ifndef __MATH_GEOM_INLINE_C__ -#define __MATH_GEOM_INLINE_C__ +#include /****************************** Spherical Harmonics **************************/ diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c new file mode 100644 index 00000000000..5a9e8244a46 --- /dev/null +++ b/source/blender/blenlib/intern/math_interp.c @@ -0,0 +1,351 @@ +/* + * ***** 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) 2012 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include + +#include "BLI_math.h" + +/************************************************************************** + * INTERPOLATIONS + * + * Reference and docs: + * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms + ***************************************************************************/ + +/* BICUBIC Interpolation functions + * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation + * function assumes out to be zero'ed, only does RGBA */ + +static float P(float k) +{ + float p1, p2, p3, p4; + p1 = MAX2(k + 2.0f, 0); + p2 = MAX2(k + 1.0f, 0); + p3 = MAX2(k, 0); + p4 = MAX2(k - 1.0f, 0); + return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); +} + + +#if 0 +/* older, slower function, works the same as above */ +static float P(float k) +{ + return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f)); +} +#endif + +static void vector_from_float(const float *data, float vector[4], int components) +{ + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + copy_v3_v3(vector, data); + } + else { + copy_v4_v4(vector, data); + } +} + +static void vector_from_byte(const unsigned char *data, float vector[4], int components) +{ + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + } + else { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + vector[3] = data[3]; + } +} + +/* BICUBIC INTERPOLATION */ +BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const float *float_buffer, + unsigned char *byte_output, float *float_output, int width, int height, + int components, float u, float v) +{ + int i, j, n, m, x1, y1; + float a, b, w, wx, wy[4], out[4]; + + /* sample area entirely outside image? */ + if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { + return; + } + + i = (int)floor(u); + j = (int)floor(v); + a = u - i; + b = v - j; + + zero_v4(out); + +/* Optimized and not so easy to read */ + + /* avoid calling multiple times */ + wy[0] = P(b - (-1)); + wy[1] = P(b - 0); + wy[2] = P(b - 1); + wy[3] = P(b - 2); + + for (n = -1; n <= 2; n++) { + x1 = i + n; + CLAMP(x1, 0, width - 1); + wx = P(n - a); + for (m = -1; m <= 2; m++) { + float data[4]; + + y1 = j + m; + CLAMP(y1, 0, height - 1); + /* normally we could do this */ + /* w = P(n-a) * P(b-m); */ + /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ + w = wx * wy[m + 1]; + + if (float_output) { + const float *float_data = float_buffer + width * y1 * components + components * x1; + + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + + vector_from_byte(byte_data, data, components); + } + + if (components == 1) { + out[0] += data[0] * w; + } + else if (components == 3) { + out[0] += data[0] * w; + out[1] += data[1] * w; + out[2] += data[2] * w; + } + else { + out[0] += data[0] * w; + out[1] += data[1] * w; + out[2] += data[2] * w; + out[3] += data[3] * w; + } + } + } + +/* Done with optimized part */ + +#if 0 + /* older, slower function, works the same as above */ + for (n = -1; n <= 2; n++) { + for (m = -1; m <= 2; m++) { + x1 = i + n; + y1 = j + m; + if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) { + float data[4]; + + if (float_output) { + const float *float_data = float_buffer + width * y1 * components + components * x1; + + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + + vector_from_byte(byte_data, data, components); + } + + if (components == 1) { + out[0] += data[0] * P(n - a) * P(b - m); + } + else if (components == 3) { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + out[2] += data[2] * P(n - a) * P(b - m); + } + else { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + out[2] += data[2] * P(n - a) * P(b - m); + out[3] += data[3] * P(n - a) * P(b - m); + } + } + } + } +#endif + + if (float_output) { + if (components == 1) { + float_output[0] = out[0]; + } + else if (components == 3) { + copy_v3_v3(float_output, out); + } + else { + copy_v4_v4(float_output, out); + } + } + else { + if (components == 1) { + byte_output[0] = out[0]; + } + else if (components == 3) { + byte_output[0] = out[0]; + byte_output[1] = out[1]; + byte_output[2] = out[2]; + } + else { + byte_output[0] = out[0]; + byte_output[1] = out[1]; + byte_output[2] = out[2]; + byte_output[3] = out[3]; + } + } +} + +void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v) +{ + bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); +} + +void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v) +{ + bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); +} + +/* BILINEAR INTERPOLATION */ +BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const float *float_buffer, + unsigned char *byte_output, float *float_output, int width, int height, + int components, float u, float v) +{ + float a, b; + float a_b, ma_b, a_mb, ma_mb; + int y1, y2, x1, x2; + + /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ + + x1 = (int)floor(u); + x2 = (int)ceil(u); + y1 = (int)floor(v); + y2 = (int)ceil(v); + + /* sample area entirely outside image? */ + if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) { + return; + } + + if (float_output) { + const float *row1, *row2, *row3, *row4; + float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = float_buffer + width * y1 * components + components * x1; + + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = float_buffer + width * y2 * components + components * x1; + + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = float_buffer + width * y1 * components + components * x2; + + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = float_buffer + width * y2 * components + components * x2; + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + float_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } + } + else { + const unsigned char *row1, *row2, *row3, *row4; + unsigned char empty[4] = {0, 0, 0, 0}; + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = byte_buffer + width * y1 * components + components * x1; + + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = byte_buffer + width * y2 * components + components * x1; + + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = byte_buffer + width * y1 * components + components * x2; + + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = byte_buffer + width * y2 * components + components * x2; + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + byte_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } + } +} + +void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v) +{ + bilinear_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); +} + +void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v) +{ + bilinear_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); +} diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index f622a5ace35..38214f9c6b0 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -504,6 +504,51 @@ void sub_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) m1[i][j] = m2[i][j] - m3[i][j]; } +/* why not make this a standard part of the API? */ +static float determinant_m3_local(float m[3][3]) +{ + return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) - + m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) + + m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1])); +} + +int invert_m3_ex(float m[3][3], const float epsilon) +{ + float tmp[3][3]; + int success; + + success = invert_m3_m3_ex(tmp, m, epsilon); + copy_m3_m3(m, tmp); + + return success; +} + +int invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon) +{ + float det; + int a, b, success; + + BLI_assert(epsilon >= 0.0f); + + /* calc adjoint */ + adjoint_m3_m3(m1, m2); + + /* then determinant old matrix! */ + det = determinant_m3_local(m2); + + success = (fabsf(det) > epsilon); + + if (LIKELY(det != 0.0f)) { + det = 1.0f / det; + for (a = 0; a < 3; a++) { + for (b = 0; b < 3; b++) { + m1[a][b] *= det; + } + } + } + return success; +} + int invert_m3(float m[3][3]) { float tmp[3][3]; @@ -524,17 +569,16 @@ int invert_m3_m3(float m1[3][3], float m2[3][3]) adjoint_m3_m3(m1, m2); /* then determinant old matrix! */ - det = (m2[0][0] * (m2[1][1] * m2[2][2] - m2[1][2] * m2[2][1]) - - m2[1][0] * (m2[0][1] * m2[2][2] - m2[0][2] * m2[2][1]) + - m2[2][0] * (m2[0][1] * m2[1][2] - m2[0][2] * m2[1][1])); + det = determinant_m3_local(m2); - success = (det != 0); + success = (det != 0.0f); - if (det == 0) det = 1; - det = 1 / det; - for (a = 0; a < 3; a++) { - for (b = 0; b < 3; b++) { - m1[a][b] *= det; + if (LIKELY(det != 0.0f)) { + det = 1.0f / det; + for (a = 0; a < 3; a++) { + for (b = 0; b < 3; b++) { + m1[a][b] *= det; + } } } diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index b0c4724e1ec..3069542107e 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -84,7 +84,7 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4]) * \note: * Assumes a unit quaternion? * - * in fact not, but you may wan't to use a unit quat, read on... + * in fact not, but you may want to use a unit quat, read on... * * Shortcut for 'q v q*' when \a v is actually a quaternion. * This removes the need for converting a vector to a quaternion, diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 976895fe6fc..812e2b3e63d 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -115,6 +115,13 @@ void mid_v2_v2v2(float v[2], const float v1[2], const float v2[2]) v[1] = 0.5f * (v1[1] + v2[1]); } +void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]) +{ + v[0] = (v1[0] + v2[0] + v3[0]) / 3.0f; + v[1] = (v1[1] + v2[1] + v3[1]) / 3.0f; + v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f; +} + /********************************** Angles ***********************************/ /* Return the angle in radians between vecs 1-2 and 2-3 in radians @@ -201,6 +208,13 @@ float angle_signed_v2v2(const float v1[2], const float v2[2]) float angle_normalized_v3v3(const float v1[3], const float v2[3]) { + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v3(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); + BLI_assert(fabsf((test = len_squared_v3(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ if (dot_v3v3(v1, v2) < 0.0f) { float vec[3]; @@ -217,6 +231,13 @@ float angle_normalized_v3v3(const float v1[3], const float v2[3]) float angle_normalized_v2v2(const float v1[2], const float v2[2]) { + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v2(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); + BLI_assert(fabsf((test = len_squared_v2(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ if (dot_v2v2(v1, v2) < 0.0f) { float vec[2]; @@ -401,6 +422,12 @@ void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[ const float costheta = cos(angle); const float sintheta = sin(angle); + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v3(axis)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + r[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) + (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) + (((1 - costheta) * axis[0] * axis[2] + axis[1] * sintheta) * p[2]); diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 191b0e16025..3ede8636aa5 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -27,12 +27,11 @@ * \ingroup bli */ - -#include "BLI_math.h" - #ifndef __MATH_VECTOR_INLINE_C__ #define __MATH_VECTOR_INLINE_C__ +#include "BLI_math.h" + /********************************** Init *************************************/ MINLINE void zero_v2(float r[2]) diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index fb33d7ce127..f37e1e03f39 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -398,7 +398,8 @@ static float orgBlenderNoise(float x, float y, float z) h = hashvectf + 3 * hash[b21 + b11]; n += i * (h[0] * jx + h[1] * jy + h[2] * jz); - if (n < 0.0f) n = 0.0f; else if (n > 1.0f) n = 1.0f; + if (n < 0.0f) n = 0.0f; + else if (n > 1.0f) n = 1.0f; return n; } @@ -456,16 +457,50 @@ float BLI_turbulence1(float noisesize, float x, float y, float z, int nr) /* ********************* FROM PERLIN HIMSELF: ******************** */ -static char p[512 + 2] = { - 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, - 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, - 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, - 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, - 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, - 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, - 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, - 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, - 0xA2, 0xA0 +static const char p[512 + 2] = { + 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, + 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, + 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, + 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, + 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, + 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, + 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, + 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, + 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, + 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, + 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, 0xBF, 0x33, 0x9C, 0x5F, + 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, + 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, + 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, + 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, + 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, + 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, + 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, + 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, + 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, + 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, + 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, + 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, + 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, + 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, + 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, + 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, + 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, + 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, + 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, + 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, + 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, + 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, + 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, + 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, + 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, + 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, + 0xB9, 0xCE, 0xC9, 0x8D, 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, + 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, + 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, + 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, + 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, + 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0 }; @@ -1856,7 +1891,8 @@ float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity y *= lacunarity; z *= lacunarity; weight = signal * gain; - if (weight > 1.0f) weight = 1.0f; else if (weight < 0.0f) weight = 0.0f; + if (weight > 1.0f) weight = 1.0f; + else if (weight < 0.0f) weight = 0.0f; signal = offset - fabsf(noisefunc(x, y, z)); signal *= signal; signal *= weight; diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 7637c60ec16..6fa6d86589f 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -1707,11 +1707,22 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], } } -void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces) +void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces, + DMFlagMat *flagmats, BLI_bitmap *grid_hidden) { + int a; + bvh->grids = grids; bvh->gridadj = gridadj; bvh->gridfaces = gridfaces; + + if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) { + bvh->grid_flag_mats = flagmats; + bvh->grid_hidden = grid_hidden; + + for (a = 0; a < bvh->totnode; ++a) + BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]); + } } float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3] diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c index bb39cb61e78..b06534d282a 100644 --- a/source/blender/blenlib/intern/quadric.c +++ b/source/blender/blenlib/intern/quadric.c @@ -107,18 +107,13 @@ float BLI_quadric_evaluate(const Quadric *q, const float v[3]) q->d2); } -int BLI_quadric_optimize(const Quadric *q, float v[3]) +int BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon) { float m[3][3]; - float det; BLI_quadric_to_tensor_m3(q, m); - det = determinant_m3(m[0][0], m[0][1], m[0][2], - m[1][0], m[1][1], m[1][2], - m[2][0], m[2][1], m[2][2]); - if (fabsf(det) > FLT_EPSILON) { - invert_m3(m); + if (invert_m3_ex(m, epsilon)) { BLI_quadric_to_vector_v3(q, v); mul_m3_v3(m, v); negate_v3(v); diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 362a87782c6..defe500cb21 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -503,8 +503,7 @@ static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *tempe } } - -static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) +static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) { ScanFillVertLink *sc = NULL, *sc1; ScanFillVert *eve, *v1, *v2, *v3; @@ -530,26 +529,28 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) #endif /* STEP 0: remove zero sized edges */ - eed = sf_ctx->filledgebase.first; - while (eed) { - if (equals_v2v2(eed->v1->xy, eed->v2->xy)) { - if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) { - eed->v2->f = SF_VERT_ZERO_LEN; - eed->v2->tmp.v = eed->v1->tmp.v; - } - else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) { - eed->v1->f = SF_VERT_ZERO_LEN; - eed->v1->tmp.v = eed->v2->tmp.v; - } - else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) { - eed->v1->tmp.v = eed->v2->tmp.v; - } - else { - eed->v2->f = SF_VERT_ZERO_LEN; - eed->v2->tmp.v = eed->v1; + if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) { + eed = sf_ctx->filledgebase.first; + while (eed) { + if (equals_v2v2(eed->v1->xy, eed->v2->xy)) { + if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) { + eed->v2->f = SF_VERT_ZERO_LEN; + eed->v2->tmp.v = eed->v1->tmp.v; + } + else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) { + eed->v1->f = SF_VERT_ZERO_LEN; + eed->v1->tmp.v = eed->v2->tmp.v; + } + else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) { + eed->v1->tmp.v = eed->v2->tmp.v; + } + else { + eed->v2->f = SF_VERT_ZERO_LEN; + eed->v2->tmp.v = eed->v1; + } } + eed = eed->next; } - eed = eed->next; } /* STEP 1: make using FillVert and FillEdge lists a sorted @@ -572,28 +573,42 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) qsort(sf_ctx->_scdata, verts, sizeof(ScanFillVertLink), vergscdata); - eed = sf_ctx->filledgebase.first; - while (eed) { - nexted = eed->next; - BLI_remlink(&sf_ctx->filledgebase, eed); - /* This code is for handling zero-length edges that get - * collapsed in step 0. It was removed for some time to - * fix trunk bug #4544, so if that comes back, this code - * may need some work, or there will have to be a better - * fix to #4544. */ - if (eed->v1->f == SF_VERT_ZERO_LEN) { - v1 = eed->v1; - while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v)) - eed->v1 = eed->v1->tmp.v; + if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) { + for (eed = sf_ctx->filledgebase.first; eed; eed = nexted) { + nexted = eed->next; + BLI_remlink(&sf_ctx->filledgebase, eed); + /* This code is for handling zero-length edges that get + * collapsed in step 0. It was removed for some time to + * fix trunk bug #4544, so if that comes back, this code + * may need some work, or there will have to be a better + * fix to #4544. + * + * warning, this can hang on un-ordered edges, see: [#33281] + * for now disable 'BLI_SCANFILL_CALC_REMOVE_DOUBLES' for ngons. + */ + if (eed->v1->f == SF_VERT_ZERO_LEN) { + v1 = eed->v1; + while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v)) + eed->v1 = eed->v1->tmp.v; + } + if (eed->v2->f == SF_VERT_ZERO_LEN) { + v2 = eed->v2; + while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v)) + eed->v2 = eed->v2->tmp.v; + } + if (eed->v1 != eed->v2) { + addedgetoscanlist(sf_ctx, eed, verts); + } } - if (eed->v2->f == SF_VERT_ZERO_LEN) { - v2 = eed->v2; - while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v)) - eed->v2 = eed->v2->tmp.v; + } + else { + for (eed = sf_ctx->filledgebase.first; eed; eed = nexted) { + nexted = eed->next; + BLI_remlink(&sf_ctx->filledgebase, eed); + if (eed->v1 != eed->v2) { + addedgetoscanlist(sf_ctx, eed, verts); + } } - if (eed->v1 != eed->v2) addedgetoscanlist(sf_ctx, eed, verts); - - eed = nexted; } #if 0 sc = scdata; @@ -775,12 +790,12 @@ int BLI_scanfill_begin(ScanFillContext *sf_ctx) return 1; } -int BLI_scanfill_calc(ScanFillContext *sf_ctx, const short do_quad_tri_speedup) +int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag) { - return BLI_scanfill_calc_ex(sf_ctx, do_quad_tri_speedup, NULL); + return BLI_scanfill_calc_ex(sf_ctx, flag, NULL); } -int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup, const float nor_proj[3]) +int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]) { /* * - fill works with its own lists, so create that first (no faces!) @@ -810,30 +825,32 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu a += 1; } - if (do_quad_tri_speedup && (a == 3)) { - eve = sf_ctx->fillvertbase.first; + if (flag & BLI_SCANFILL_CALC_QUADTRI_FASTPATH) { + if (a == 3) { + eve = sf_ctx->fillvertbase.first; - addfillface(sf_ctx, eve, eve->next, eve->next->next); - return 1; - } - else if (do_quad_tri_speedup && (a == 4)) { - float vec1[3], vec2[3]; - - eve = sf_ctx->fillvertbase.first; - /* no need to check 'eve->next->next->next' is valid, already counted */ - /* use shortest diagonal for quad */ - sub_v3_v3v3(vec1, eve->co, eve->next->next->co); - sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co); - - if (dot_v3v3(vec1, vec1) < dot_v3v3(vec2, vec2)) { addfillface(sf_ctx, eve, eve->next, eve->next->next); - addfillface(sf_ctx, eve->next->next, eve->next->next->next, eve); + return 1; } - else { - addfillface(sf_ctx, eve->next, eve->next->next, eve->next->next->next); - addfillface(sf_ctx, eve->next->next->next, eve, eve->next); + else if (a == 4) { + float vec1[3], vec2[3]; + + eve = sf_ctx->fillvertbase.first; + /* no need to check 'eve->next->next->next' is valid, already counted */ + /* use shortest diagonal for quad */ + sub_v3_v3v3(vec1, eve->co, eve->next->next->co); + sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co); + + if (dot_v3v3(vec1, vec1) < dot_v3v3(vec2, vec2)) { + addfillface(sf_ctx, eve, eve->next, eve->next->next); + addfillface(sf_ctx, eve->next->next, eve->next->next->next, eve); + } + else { + addfillface(sf_ctx, eve->next, eve->next->next, eve->next->next->next); + addfillface(sf_ctx, eve->next->next->next, eve, eve->next); + } + return 2; } - return 2; } /* first test vertices if they are in edges */ @@ -985,7 +1002,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu /* CURRENT STATUS: - * - eve->f :1 = availalble in edges + * - eve->f :1 = available in edges * - eve->xs :polynumber * - eve->h :amount of edges connected to vertex * - eve->tmp.v :store! original vertex number @@ -1091,7 +1108,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu for (a = 0; a < poly; a++) { if (pf->edges > 1) { splitlist(sf_ctx, &tempve, &temped, pf->nr); - totfaces += scanfill(sf_ctx, pf); + totfaces += scanfill(sf_ctx, pf, flag); } pf++; } diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c index 92125c6e988..64bb503fa3c 100644 --- a/source/blender/blenlib/intern/smallhash.c +++ b/source/blender/blenlib/intern/smallhash.c @@ -43,8 +43,22 @@ #define SMHASH_CELL_UNUSED ((void *)0x7FFFFFFF) #define SMHASH_CELL_FREE ((void *)0x7FFFFFFD) -#define SMHASH_NONZERO(n) ((n) + !(n)) -#define SMHASH_NEXT(h, hoff) ABS(((h) + ((hoff = SMHASH_NONZERO(hoff * 2) + 1), hoff))) +BLI_INLINE int smhash_nonzero(const int n) +{ + return n + !n; +} + +BLI_INLINE int smhash_abs_i(const int n) +{ + return (n > 0) ? n : -n; +} + +/* typically this re-assigns 'h' */ +#define SMHASH_NEXT(h, hoff) ( \ + CHECK_TYPE_INLINE(&(h), int), \ + CHECK_TYPE_INLINE(&(hoff), int), \ + smhash_abs_i((h) + (((hoff) = smhash_nonzero((hoff) * 2) + 1), (hoff))) \ + ) extern unsigned int hashsizes[]; diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index ff589764287..f23f75f69d9 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -56,7 +56,7 @@ char *BLI_strdup(const char *str) return BLI_strdupn(str, strlen(str)); } -char *BLI_strdupcat(const char *str1, const char *str2) +char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) { size_t len; char *n; @@ -69,7 +69,7 @@ char *BLI_strdupcat(const char *str1, const char *str2) return n; } -char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) +char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { size_t srclen = strlen(src); size_t cpylen = (srclen > (maxncpy - 1)) ? (maxncpy - 1) : srclen; @@ -81,10 +81,14 @@ char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) return dst; } -size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg) +size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg) { size_t n; + BLI_assert(buffer != NULL); + BLI_assert(count > 0); + BLI_assert(format != NULL); + n = vsnprintf(buffer, count, format, arg); if (n != -1 && n < count) { @@ -97,7 +101,7 @@ size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg return n; } -size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...) +size_t BLI_snprintf(char *__restrict buffer, size_t count, const char *__restrict format, ...) { size_t n; va_list arg; @@ -109,12 +113,14 @@ size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...) return n; } -char *BLI_sprintfN(const char *format, ...) +char *BLI_sprintfN(const char *__restrict format, ...) { DynStr *ds; va_list arg; char *n; + BLI_assert(format != NULL); + va_start(arg, format); ds = BLI_dynstr_new(); @@ -133,7 +139,7 @@ char *BLI_sprintfN(const char *format, ...) * TODO: support more fancy string escaping. current code is primitive * this basically is an ascii version of PyUnicode_EncodeUnicodeEscape() * which is a useful reference. */ -size_t BLI_strescape(char *dst, const char *src, const size_t maxncpy) +size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { size_t len = 0; @@ -186,7 +192,7 @@ escape_finish: * * TODO, return the offset and a length so as to avoid doing an allocation. */ -char *BLI_str_quoted_substrN(const char *str, const char *prefix) +char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) { size_t prefixLen = strlen(prefix); char *startMatch, *endMatch; @@ -207,7 +213,7 @@ char *BLI_str_quoted_substrN(const char *str, const char *prefix) /* A rather wasteful string-replacement utility, though this shall do for now... * Feel free to replace this with an even safe + nicer alternative */ -char *BLI_replacestr(char *str, const char *oldText, const char *newText) +char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText) { DynStr *ds = NULL; size_t lenOld = strlen(oldText); diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c index bab144266a4..65763f21b0f 100644 --- a/source/blender/blenlib/intern/string_cursor_utf8.c +++ b/source/blender/blenlib/intern/string_cursor_utf8.c @@ -38,7 +38,7 @@ typedef enum strCursorDelimType { STRCUR_DELIM_NONE, - STRCUR_DELIM_ALPHA, + STRCUR_DELIM_ALPHANUMERIC, STRCUR_DELIM_PUNCT, STRCUR_DELIM_BRACE, STRCUR_DELIM_OPERATOR, @@ -47,21 +47,12 @@ typedef enum strCursorDelimType { STRCUR_DELIM_OTHER } strCursorDelimType; -/* return 1 if char ch is special character, otherwise return 0 */ -static strCursorDelimType test_special_char(const char *ch_utf8) +static strCursorDelimType cursor_delim_type(const char *ch_utf8) { /* for full unicode support we really need to have large lookup tables to figure * out whats what in every possible char set - and python, glib both have these. */ unsigned int uch = BLI_str_utf8_as_unicode(ch_utf8); - if ((uch >= 'a' && uch <= 'z') || - (uch >= 'A' && uch <= 'Z') || - (uch == '_') /* not quite correct but allow for python, could become configurable */ - ) - { - return STRCUR_DELIM_ALPHA; - } - switch (uch) { case ',': case '.': @@ -86,10 +77,11 @@ static strCursorDelimType test_special_char(const char *ch_utf8) case '^': case '*': case '&': + case '|': return STRCUR_DELIM_OPERATOR; case '\'': - case '\"': // " - an extra closing one for Aligorith's text editor + case '\"': return STRCUR_DELIM_QUOTE; case ' ': @@ -97,20 +89,22 @@ static strCursorDelimType test_special_char(const char *ch_utf8) return STRCUR_DELIM_WHITESPACE; case '\\': - case '!': case '@': case '#': case '$': case ':': case ';': case '?': + case '!': + case 0xA3: /* pound */ + case 0x80: /* euro */ /* case '_': *//* special case, for python */ return STRCUR_DELIM_OTHER; default: break; } - return STRCUR_DELIM_NONE; + return STRCUR_DELIM_ALPHANUMERIC; /* Not quite true, but ok for now */ } int BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos) @@ -153,14 +147,14 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen, BLI_str_cursor_step_next_utf8(str, maxlen, pos); if (jump != STRCUR_JUMP_NONE) { - const strCursorDelimType is_special = (*pos) < maxlen ? test_special_char(&str[*pos]) : STRCUR_DELIM_NONE; + const strCursorDelimType delim_type = (*pos) < maxlen ? cursor_delim_type(&str[*pos]) : STRCUR_DELIM_NONE; /* jump between special characters (/,\,_,-, etc.), - * look at function test_special_char() for complete + * look at function cursor_delim_type() for complete * list of special character, ctr -> */ while ((*pos) < maxlen) { if (BLI_str_cursor_step_next_utf8(str, maxlen, pos)) { - if ((jump != STRCUR_JUMP_ALL) && (is_special != test_special_char(&str[*pos]))) - break; + if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type(&str[*pos]))) + break; } else { break; /* unlikely but just in case */ @@ -172,13 +166,13 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen, BLI_str_cursor_step_prev_utf8(str, maxlen, pos); if (jump != STRCUR_JUMP_NONE) { - const strCursorDelimType is_special = (*pos) > 1 ? test_special_char(&str[(*pos) - 1]) : STRCUR_DELIM_NONE; + const strCursorDelimType delim_type = (*pos) > 1 ? cursor_delim_type(&str[(*pos) - 1]) : STRCUR_DELIM_NONE; /* jump between special characters (/,\,_,-, etc.), - * look at function test_special_char() for complete + * look at function cursor_delim_type() for complete * list of special character, ctr -> */ while ((*pos) > 0) { if (BLI_str_cursor_step_prev_utf8(str, maxlen, pos)) { - if ((jump != STRCUR_JUMP_ALL) && (is_special != test_special_char(&str[*pos]))) + if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type(&str[*pos]))) break; } else { diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 0b737e0eff5..bf98f2ae77c 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -184,7 +184,7 @@ static const size_t utf8_skip_data[256] = { *dst = '\0'; \ } (void)0 -char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) +char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) { char *dst_r = dst; @@ -196,7 +196,7 @@ char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) return dst_r; } -char *BLI_strncat_utf8(char *dst, const char *src, size_t maxncpy) +char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) { while (*dst && maxncpy > 0) { dst++; @@ -213,7 +213,7 @@ char *BLI_strncat_utf8(char *dst, const char *src, size_t maxncpy) /* --------------------------------------------------------------------------*/ /* wchar_t / utf8 functions */ -size_t BLI_strncpy_wchar_as_utf8(char *dst, const wchar_t *src, const size_t maxncpy) +size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxncpy) { size_t len = 0; @@ -289,7 +289,7 @@ size_t BLI_strnlen_utf8(const char *start, const size_t maxlen) return len; } -size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size_t maxncpy) +size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__restrict src_c, const size_t maxncpy) { int len = 0; @@ -317,12 +317,12 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size /* end wchar_t / utf8 functions */ /* --------------------------------------------------------------------------*/ -/* copied from glib's gutf8.c */ +/* copied from glib's gutf8.c, added 'Err' arg */ /* note, glib uses unsigned int for unicode, best we do the same, * though we don't typedef it - campbell */ -#define UTF8_COMPUTE(Char, Mask, Len) \ +#define UTF8_COMPUTE(Char, Mask, Len, Err) \ if (Char < 128) { \ Len = 1; \ Mask = 0x7f; \ @@ -348,7 +348,7 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size Mask = 0x01; \ } \ else { \ - Len = -1; \ + Len = Err; /* -1 is the typical error value or 1 to skip */ \ } (void)0 /* same as glib define but added an 'Err' arg */ @@ -371,7 +371,20 @@ int BLI_str_utf8_size(const char *p) int mask = 0, len; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); + + (void)mask; /* quiet warning */ + + return len; +} + +/* use when we want to skip errors */ +int BLI_str_utf8_size_safe(const char *p) +{ + int mask = 0, len; + unsigned char c = (unsigned char) *p; + + UTF8_COMPUTE (c, mask, len, 1); (void)mask; /* quiet warning */ @@ -381,10 +394,10 @@ int BLI_str_utf8_size(const char *p) /* was g_utf8_get_char */ /** * BLI_str_utf8_as_unicode: - * @p a pointer to Unicode character encoded as UTF-8 + * \param p a pointer to Unicode character encoded as UTF-8 * * Converts a sequence of bytes encoded as UTF-8 to a Unicode character. - * If @p does not point to a valid UTF-8 encoded character, results are + * If \a p does not point to a valid UTF-8 encoded character, results are * undefined. If you are not sure that the bytes are complete * valid Unicode characters, you should use g_utf8_get_char_validated() * instead. @@ -397,7 +410,7 @@ unsigned int BLI_str_utf8_as_unicode(const char *p) unsigned int result; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) return BLI_UTF8_ERR; UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); @@ -406,13 +419,13 @@ unsigned int BLI_str_utf8_as_unicode(const char *p) } /* variant that increments the length */ -unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index) +unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) { int i, mask = 0, len; unsigned int result; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) return BLI_UTF8_ERR; UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); @@ -422,7 +435,7 @@ unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index) /* another variant that steps over the index, * note, currently this also falls back to latin1 for text drawing. */ -unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) +unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) { int i, mask = 0, len; unsigned int result; @@ -431,7 +444,7 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) p += *index; c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) { /* when called with NULL end, result will never be NULL, * checks for a NULL character */ @@ -523,14 +536,14 @@ size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf) /* was g_utf8_find_prev_char */ /** * BLI_str_find_prev_char_utf8: - * @str: pointer to the beginning of a UTF-8 encoded string - * @p pointer to some position within @str + * \param str pointer to the beginning of a UTF-8 encoded string + * \param p pointer to some position within \a str * - * Given a position @p with a UTF-8 encoded string @str, find the start - * of the previous UTF-8 character starting before. @p Returns %NULL if no - * UTF-8 characters are present in @str before @p + * Given a position \a p with a UTF-8 encoded string \a str, find the start + * of the previous UTF-8 character starting before. \a p Returns %NULL if no + * UTF-8 characters are present in \a str before \a p * - * @p does not have to be at the beginning of a UTF-8 character. No check + * \a p does not have to be at the beginning of a UTF-8 character. No check * is made to see if the character found is actually valid other than * it starts with an appropriate byte. * @@ -549,13 +562,13 @@ char * BLI_str_find_prev_char_utf8(const char *str, const char *p) /* was g_utf8_find_next_char */ /** * BLI_str_find_next_char_utf8: - * @p a pointer to a position within a UTF-8 encoded string - * @end a pointer to the byte following the end of the string, + * \param p a pointer to a position within a UTF-8 encoded string + * \param end a pointer to the byte following the end of the string, * or %NULL to indicate that the string is nul-terminated. * - * Finds the start of the next UTF-8 character in the string after @p + * Finds the start of the next UTF-8 character in the string after \a p * - * @p does not have to be at the beginning of a UTF-8 character. No check + * \a p does not have to be at the beginning of a UTF-8 character. No check * is made to see if the character found is actually valid other than * it starts with an appropriate byte. * @@ -581,13 +594,13 @@ char *BLI_str_find_next_char_utf8(const char *p, const char *end) /* was g_utf8_prev_char */ /** * BLI_str_prev_char_utf8: - * @p a pointer to a position within a UTF-8 encoded string + * \param p a pointer to a position within a UTF-8 encoded string * - * Finds the previous UTF-8 character in the string before @p + * Finds the previous UTF-8 character in the string before \a p * - * @p does not have to be at the beginning of a UTF-8 character. No check + * \a p does not have to be at the beginning of a UTF-8 character. No check * is made to see if the character found is actually valid other than - * it starts with an appropriate byte. If @p might be the first + * it starts with an appropriate byte. If \a p might be the first * character of the string, you must use g_utf8_find_prev_char() instead. * * Return value: a pointer to the found character. diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 66527b9b92a..146e1d531f1 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -400,6 +400,42 @@ void BLI_mutex_end(ThreadMutex *mutex) pthread_mutex_destroy(mutex); } +/* Spin Locks */ + +void BLI_spin_init(SpinLock *spin) +{ +#ifdef __APPLE__ + *spin = OS_SPINLOCK_INIT; +#else + pthread_spin_init(spin, 0); +#endif +} + +void BLI_spin_lock(SpinLock *spin) +{ +#ifdef __APPLE__ + OSSpinLockLock(spin); +#else + pthread_spin_lock(spin); +#endif +} + +void BLI_spin_unlock(SpinLock *spin) +{ +#ifdef __APPLE__ + OSSpinLockUnlock(spin); +#else + pthread_spin_unlock(spin); +#endif +} + +void BLI_spin_end(SpinLock *spin) +{ +#ifndef __APPLE__ + pthread_spin_destroy(spin); +#endif +} + /* Read/Write Mutex Lock */ void BLI_rw_mutex_init(ThreadRWMutex *mutex) diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi.c index 0d411038b3e..601b07c9a5d 100644 --- a/source/blender/blenlib/intern/voronoi.c +++ b/source/blender/blenlib/intern/voronoi.c @@ -609,9 +609,9 @@ static int voronoi_getNextSideCoord(ListBase *edges, float coord[2], int dim, in static void voronoi_createBoundaryEdges(ListBase *edges, int width, int height) { const float corners[4][2] = {{width - 1, 0.0f}, - {width - 1, height - 1}, - {0.0f, height - 1}, - {0.0f, 0.0f}}; + {width - 1, height - 1}, + {0.0f, height - 1}, + {0.0f, 0.0f}}; int i, dim = 0, dir = 1; float coord[2] = {0.0f, 0.0f}; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2ea3fb75709..203af1d8316 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -360,36 +360,39 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) } /* for libdata, nr has ID code, no increment */ -static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) +static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) { - int i; - - if (addr == NULL) return NULL; - + if (addr == NULL) { + return NULL; + } + /* lasthit works fine for non-libdata, linking there is done in same sequence as writing */ if (onm->sorted) { OldNew entry_s, *entry; - + entry_s.old = addr; - + entry = bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap); if (entry) { ID *id = entry->newp; - + if (id && (!lib || id->lib)) { - return entry->newp; + return id; } } } - - for (i = 0; i < onm->nentries; i++) { - OldNew *entry = &onm->entries[i]; - - if (entry->old == addr) { - ID *id = entry->newp; - - if (id && (!lib || id->lib)) { - return entry->newp; + else { + /* note, this can be a bottle neck when loading some files */ + unsigned int nentries = (unsigned int)onm->nentries; + unsigned int i; + OldNew *entry; + + for (i = 0, entry = onm->entries; i < nentries; i++, entry++) { + if (entry->old == addr) { + ID *id = id = entry->newp; + if (id && (!lib || id->lib)) { + return id; + } } } } @@ -2406,6 +2409,8 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) ntree->adt = newdataadr(fd, ntree->adt); direct_link_animdata(fd, ntree->adt); + ntree->id.flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA); + link_list(fd, &ntree->nodes); for (node = ntree->nodes.first; node; node = node->next) { node->typeinfo = NULL; @@ -2980,7 +2985,6 @@ static void direct_link_text(FileData *fd, Text *text) #endif link_list(fd, &text->lines); - link_list(fd, &text->markers); text->curl = newdataadr(fd, text->curl); text->sell = newdataadr(fd, text->sell); @@ -3040,7 +3044,7 @@ static void direct_link_image(FileData *fd, Image *ima) link_ibuf_list(fd, &ima->ibufs); else ima->ibufs.first = ima->ibufs.last = NULL; - + /* if not restored, we keep the binded opengl index */ if (ima->ibufs.first == NULL) { ima->bindcode = 0; @@ -7168,7 +7172,36 @@ static void do_version_logic_264(ListBase *regionbase) } - + +static void do_versions_affine_tracker_track(MovieTrackingTrack *track) +{ + int i; + + for (i = 0; i < track->markersnr; i++) { + MovieTrackingMarker *marker = &track->markers[i]; + + if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) && + is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3])) + { + marker->pattern_corners[0][0] = track->pat_min[0]; + marker->pattern_corners[0][1] = track->pat_min[1]; + + marker->pattern_corners[1][0] = track->pat_max[0]; + marker->pattern_corners[1][1] = track->pat_min[1]; + + marker->pattern_corners[2][0] = track->pat_max[0]; + marker->pattern_corners[2][1] = track->pat_max[1]; + + marker->pattern_corners[3][0] = track->pat_min[0]; + marker->pattern_corners[3][1] = track->pat_max[1]; + } + + if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) { + copy_v2_v2(marker->search_min, track->search_min); + copy_v2_v2(marker->search_max, track->search_max); + } + } +} static void do_versions(FileData *fd, Library *lib, Main *main) @@ -7939,32 +7972,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) track = clip->tracking.tracks.first; while (track) { - int i; - - for (i = 0; i < track->markersnr; i++) { - MovieTrackingMarker *marker = &track->markers[i]; - - if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) && - is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3])) - { - marker->pattern_corners[0][0] = track->pat_min[0]; - marker->pattern_corners[0][1] = track->pat_min[1]; - - marker->pattern_corners[1][0] = track->pat_max[0]; - marker->pattern_corners[1][1] = track->pat_min[1]; - - marker->pattern_corners[2][0] = track->pat_max[0]; - marker->pattern_corners[2][1] = track->pat_max[1]; - - marker->pattern_corners[3][0] = track->pat_min[0]; - marker->pattern_corners[3][1] = track->pat_max[1]; - } - - if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) { - copy_v2_v2(marker->search_min, track->search_min); - copy_v2_v2(marker->search_max, track->search_max); - } - } + do_versions_affine_tracker_track(track); track = track->next; } @@ -8306,11 +8314,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (scene = main->scene.first; scene; scene = scene->id.next) { if (scene->r.tilex == 0 || scene->r.tiley == 1) { - /* scene could be set for panoramic rendering, so clamp with the - * lowest possible tile size value - */ - scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8); - scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8); + if (scene->r.xparts && scene->r.yparts) { + /* scene could be set for panoramic rendering, so clamp with the + * lowest possible tile size value + */ + scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8); + scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8); + } + else { + /* happens when mixing using current trunk and previous release */ + scene->r.tilex = scene->r.tiley = 64; + } } } } @@ -8332,12 +8346,42 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (clip = main->movieclip.first; clip; clip = clip->id.next) { if (clip->tracking.settings.reconstruction_success_threshold == 0.0f) { - clip->tracking.settings.reconstruction_success_threshold = 1e-3; + clip->tracking.settings.reconstruction_success_threshold = 1e-3f; } } } } + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) { + MovieClip *clip; + + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + MovieTrackingTrack *track; + MovieTrackingObject *object; + + for (track = clip->tracking.tracks.first; track; track = track->next) { + do_versions_affine_tracker_track(track); + } + + for (object = clip->tracking.objects.first; object; object = object->next) { + for (track = object->tracks.first; track; track = track->next) { + do_versions_affine_tracker_track(track); + } + } + } + } + + if (main->versionfile < 265) { + Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + if (ob->step_height == 0.0f) { + ob->step_height = 0.15f; + ob->jump_speed = 10.0f; + ob->fall_speed = 55.0f; + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index d75339252d9..1521739258e 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -901,7 +901,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) ob->matbits = MEM_callocN(sizeof(char)*ob->totcol, "ob->matbits"); for (a = 0; a < ob->totcol; a++) - ob->matbits[a] = ob->colbits & (1<matbits[a] = (ob->colbits & (1<first; while (text) { @@ -2631,13 +2630,6 @@ static void write_texts(WriteData *wd, ListBase *idbase) writedata(wd, DATA, tmp->len+1, tmp->line); tmp= tmp->next; } - - /* write markers */ - mrk= text->markers.first; - while (mrk) { - writestruct(wd, DATA, "TextMarker", 1, mrk); - mrk= mrk->next; - } } @@ -2890,7 +2882,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) fg.winpos= G.winpos; /* prevent to save this, is not good convention, and feature with concerns... */ - fg.fileflags= (fileflags & ~(G_FILE_NO_UI|G_FILE_RELATIVE_REMAP|G_FILE_MESH_COMPAT)); + fg.fileflags= (fileflags & ~G_FILE_FLAGS_RUNTIME); fg.globalf= G.f; BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename)); @@ -3039,6 +3031,10 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL char tempname[FILE_MAX+1]; int file, err, write_user_block; + /* path backup/restore */ + void *path_list_backup = NULL; + const int path_list_flag = (BLI_BPATH_TRAVERSE_SKIP_LIBRARY | BLI_BPATH_TRAVERSE_SKIP_MULTIFILE); + /* open temporary file, so we preserve the original in case we crash */ BLI_snprintf(tempname, sizeof(tempname), "%s@", filepath); @@ -3048,6 +3044,11 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL return 0; } + /* check if we need to backup and restore paths */ + if (UNLIKELY((write_flags & G_FILE_RELATIVE_REMAP) && (G_FILE_SAVE_COPY & write_flags))) { + path_list_backup = BLI_bpath_list_backup(mainvar, path_list_flag); + } + /* remapping of relative paths to new file location */ if (write_flags & G_FILE_RELATIVE_REMAP) { char dir1[FILE_MAX]; @@ -3083,6 +3084,11 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL err= write_file_handle(mainvar, file, NULL, NULL, write_user_block, write_flags, thumb); close(file); + if (UNLIKELY(path_list_backup)) { + BLI_bpath_list_restore(mainvar, path_list_flag, path_list_backup); + BLI_bpath_list_free(path_list_backup); + } + if (err) { BKE_report(reports, RPT_ERROR, strerror(errno)); remove(tempname); diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index d7858ebbc0d..2a23658f5d0 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -68,10 +68,6 @@ set(SRC intern/bmesh_construct.h intern/bmesh_core.c intern/bmesh_core.h - intern/bmesh_decimate_collapse.c - intern/bmesh_decimate_dissolve.c - intern/bmesh_decimate_unsubdivide.c - intern/bmesh_decimate.h intern/bmesh_inline.h intern/bmesh_interp.c intern/bmesh_interp.h @@ -109,6 +105,12 @@ set(SRC intern/bmesh_error.h tools/BME_bevel.c + tools/bmesh_bevel.c + tools/bmesh_bevel.h + tools/bmesh_decimate_collapse.c + tools/bmesh_decimate_dissolve.c + tools/bmesh_decimate_unsubdivide.c + tools/bmesh_decimate.h bmesh.h bmesh_class.h diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index a672ec0b6a7..6257aa4bf3e 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -252,7 +252,6 @@ extern "C" { #include "intern/bmesh_construct.h" #include "intern/bmesh_core.h" -#include "intern/bmesh_decimate.h" #include "intern/bmesh_interp.h" #include "intern/bmesh_iterators.h" #include "intern/bmesh_marking.h" @@ -267,6 +266,9 @@ extern "C" { #include "intern/bmesh_inline.h" +#include "tools/bmesh_decimate.h" +#include "tools/bmesh_bevel.h" + #ifdef __cplusplus } #endif diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index cff7da78ef2..9d797c1e602 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -48,6 +48,8 @@ struct Object; * hrm. it doesn't but stull works ok, remove the comment above? - campbell. */ +// #pragma GCC diagnostic error "-Wpadded" + /** * BMHeader * @@ -69,10 +71,19 @@ typedef struct BMHeader { * this is abused by various tools which set it dirty. * - For loops this is used for sorting during tessellation. */ - char htype; /* element geometric type (verts/edges/loops/faces) */ - char hflag; /* this would be a CD layer, see below */ + char htype; /* element geometric type (verts/edges/loops/faces) */ + char hflag; /* this would be a CD layer, see below */ + + /* internal use only! + * note,.we are very picky about not bloating this struct + * but in this case its padded up to 16 bytes anyway, + * so adding a flag here gives no increase in size */ + char api_flag; +// char _pad; } BMHeader; +BLI_STATIC_ASSERT((sizeof(BMHeader) <= 16), "BMHeader size has grown!"); + /* note: need some way to specify custom locations for custom data layers. so we can * make them point directly into structs. and some way to make it only happen to the * active layer, and properly update when switching active layers.*/ @@ -122,7 +133,10 @@ typedef struct BMLoop { /* can cast BMFace/BMEdge/BMVert, but NOT BMLoop, since these don't have a flag layer */ typedef struct BMElemF { BMHeader head; - struct BMFlagLayer *oflags; /* keep after header, an array of flags, mostly used by the operator stack */ + + /* keep directly after header, + * optional array of flags, only used by the operator stack */ + struct BMFlagLayer *oflags; } BMElemF; /* can cast anything to this, including BMLoop */ @@ -142,21 +156,24 @@ typedef struct BMFace { BMHeader head; struct BMFlagLayer *oflags; /* an array of flags, mostly used by the operator stack */ - int len; /*includes all boundary loops*/ #ifdef USE_BMESH_HOLES int totbounds; /*total boundaries, is one plus the number of holes in the face*/ ListBase loops; #else BMLoop *l_first; #endif - float no[3]; /*yes, we do store this here*/ + int len; /* includes all boundary loops */ + float no[3]; /* yes, we do store this here */ short mat_nr; +// short _pad[3]; } BMFace; typedef struct BMFlagLayer { - short f, pflag; /* flags */ + short f; /* flags */ } BMFlagLayer; +// #pragma GCC diagnostic ignored "-Wpadded" + typedef struct BMesh { int totvert, totedge, totloop, totface; int totvertsel, totedgesel, totfacesel; @@ -166,7 +183,7 @@ typedef struct BMesh { * valid flags are - BM_VERT | BM_EDGE | BM_FACE. * BM_LOOP isn't handled so far. */ char elem_index_dirty; - + /*element pools*/ struct BLI_mempool *vpool, *epool, *lpool, *fpool; @@ -192,7 +209,7 @@ typedef struct BMesh { int walkers, totflags; ListBase selected, error_stack; - + BMFace *act_face; ListBase errorstack; @@ -209,6 +226,7 @@ enum { }; #define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE) +#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE) /* BMHeader->hflag (char) */ enum { @@ -243,10 +261,16 @@ enum { # define BM_FACE_FIRST_LOOP(p) ((p)->l_first) #endif -/* size to use for static arrays when dealing with NGons, +/** + * size to use for stack arrays when dealing with NGons, * alloc after this limit is reached. * this value is rather arbitrary */ -#define BM_NGON_STACK_SIZE 32 +#define BM_DEFAULT_NGON_STACK_SIZE 32 +/** + * size to use for stack arrays dealing with connected mesh data + * verts of faces, edges of vert - etc. + * often used with #BM_iter_as_arrayN() */ +#define BM_DEFAULT_ITER_STACK_SIZE 16 /* avoid inf loop, this value is arbitrary * but should not error on valid cases */ diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index d86a26e19ac..8b7fac1eacd 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -99,23 +99,23 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa if (nodouble) { /* check if face exists or overlaps */ - is_overlap = BM_face_exists(bm, verts, len, &f); + is_overlap = BM_face_exists(verts, len, &f); } /* make new face */ if ((f == NULL) && (!is_overlap)) { BMEdge *edar[4] = {NULL}; - edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE); - edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, TRUE); + edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); + edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, BM_CREATE_NO_DOUBLE); if (len == 4) { - edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, TRUE); - edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, TRUE); + edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, BM_CREATE_NO_DOUBLE); + edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, BM_CREATE_NO_DOUBLE); } else { - edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, TRUE); + edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, BM_CREATE_NO_DOUBLE); } - f = BM_face_create(bm, verts, edar, len, FALSE); + f = BM_face_create(bm, verts, edar, len, 0); if (example && f) { BM_elem_attrs_copy(bm, bm, example, f); @@ -171,12 +171,12 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f) * #BM_face_create should be considered over this function as it * avoids some unnecessary work. */ -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble) +BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag) { BMEdge **edges2 = NULL; - BLI_array_staticdeclare(edges2, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges2, BM_DEFAULT_NGON_STACK_SIZE); BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); BMFace *f = NULL; BMEdge *e; BMVert *v, *ev1, *ev2; @@ -187,8 +187,10 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i * _and_ the old bmesh_mf functions, so its kindof smashed together * - joeedh */ - if (!len || !v1 || !v2 || !edges || !bm) + if (!len || !v1 || !v2 || !edges || !bm) { + BLI_assert(0); return NULL; + } /* put edges in correct order */ for (i = 0; i < len; i++) { @@ -280,7 +282,7 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i BM_ELEM_API_FLAG_DISABLE(verts[i], _FLAG_MV); } - f = BM_face_create(bm, verts, edges2, len, nodouble); + f = BM_face_create(bm, verts, edges2, len, create_flag); /* clean up flags */ for (i = 0; i < len; i++) { @@ -336,7 +338,7 @@ static int angle_index_pair_cmp(const void *e1, const void *e2) * * \note Since this is a vcloud there is no direction. */ -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int nodouble) +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const int create_flag) { BMFace *f; @@ -397,11 +399,11 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n /* more of a weight then a distance */ far_cross_dist = (/* first we want to have a value close to zero mapped to 1 */ - 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) * + 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) * - /* second we multiply by the distance - * so points close to the center are not preferred */ - far_cross_dist); + /* second we multiply by the distance + * so points close to the center are not preferred */ + far_cross_dist); if (far_cross_dist > far_cross_best || far_cross == NULL) { far_cross = vert_arr[i]->co; @@ -462,7 +464,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n i_prev = totv - 1; for (i = 0; i < totv; i++) { - edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, TRUE); + edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, BM_CREATE_NO_DOUBLE); /* the edge may exist already and be attached to a face * in this case we can find the best winding to use for the new face */ @@ -491,7 +493,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n /* --- */ /* create the face */ - f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, nodouble); + f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, create_flag); MEM_freeN(edge_arr); MEM_freeN(vert_arr_map); @@ -854,7 +856,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) v = BM_iter_new(&iter, bm_old, BM_VERTS_OF_MESH, NULL); for (i = 0; v; v = BM_iter_step(&iter), i++) { - v2 = BM_vert_create(bm_new, v->co, NULL); /* copy between meshes so cant use 'example' argument */ + v2 = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD); /* copy between meshes so cant use 'example' argument */ BM_elem_attrs_copy(bm_old, bm_new, v, v2); vtable[i] = v2; BM_elem_index_set(v, i); /* set_inline */ @@ -871,7 +873,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) e2 = BM_edge_create(bm_new, vtable[BM_elem_index_get(e->v1)], vtable[BM_elem_index_get(e->v2)], - e, FALSE); + e, BM_CREATE_SKIP_CD); BM_elem_attrs_copy(bm_old, bm_new, e, e2); etable[i] = e2; @@ -907,7 +909,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) v2 = vtable[BM_elem_index_get(loops[0]->v)]; } - f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, FALSE); + f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, BM_CREATE_SKIP_CD); if (UNLIKELY(f2 == NULL)) { continue; } diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index 29b84046884..60c465e5f5a 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -36,9 +36,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, B void BM_face_copy_shared(BMesh *bm, BMFace *f); -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble); +BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag); -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, int nodouble); +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag); void BMO_remove_tagged_faces(BMesh *bm, const short oflag); void BMO_remove_tagged_edges(BMesh *bm, const short oflag); diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 0910dd82701..14fab7abdc9 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -54,7 +54,7 @@ /** * \brief Main function for creating a new vertex. */ -BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) +BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag) { BMVert *v = BLI_mempool_calloc(bm->vpool); @@ -64,6 +64,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) BM_elem_index_set(v, -1); /* set_ok_invalid */ #endif + /* disallow this flag for verts - its meaningless */ + BLI_assert((create_flag & BM_CREATE_NO_DOUBLE) == 0); + bm->elem_index_dirty |= BM_VERT; /* may add to middle of the pool */ bm->totvert++; @@ -76,19 +79,24 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) } /* allocate flag */ - v->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + v->oflags = BLI_mempool_calloc(bm->toolflagpool); + } - CustomData_bmesh_set_default(&bm->vdata, &v->head.data); - - if (example) { - int *keyi; + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + int *keyi; - BM_elem_attrs_copy(bm, bm, example, v); + BM_elem_attrs_copy(bm, bm, example, v); - /* exception: don't copy the original shapekey index */ - keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); - if (keyi) { - *keyi = ORIGINDEX_NONE; + /* exception: don't copy the original shapekey index */ + keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); + if (keyi) { + *keyi = ORIGINDEX_NONE; + } + } + else { + CustomData_bmesh_set_default(&bm->vdata, &v->head.data); } } @@ -103,11 +111,11 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) * \note Duplicate edges are supported by the API however users should _never_ see them. * so unless you need a unique edge or know the edge won't exist, you should call with \a nodouble = TRUE */ -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble) +BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag) { BMEdge *e; - if (nodouble && (e = BM_edge_exists(v1, v2))) + if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2))) return e; e = BLI_mempool_calloc(bm->epool); @@ -125,27 +133,35 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, e->head.htype = BM_EDGE; /* allocate flag */ - e->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + e->oflags = BLI_mempool_calloc(bm->toolflagpool); + } e->v1 = v1; e->v2 = v2; - BM_elem_flag_enable(e, BM_ELEM_SMOOTH); - - CustomData_bmesh_set_default(&bm->edata, &e->head.data); + BM_elem_flag_enable(e, BM_ELEM_SMOOTH | BM_ELEM_DRAW); bmesh_disk_edge_append(e, e->v1); bmesh_disk_edge_append(e, e->v2); - if (example) - BM_elem_attrs_copy(bm, bm, example, e); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + BM_elem_attrs_copy(bm, bm, example, e); + } + else { + CustomData_bmesh_set_default(&bm->edata, &e->head.data); + } + } + BM_CHECK_ELEMENT(e); return e; } -static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const BMLoop *example) +static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, + const BMLoop *example, const eBMCreateFlag create_flag) { BMLoop *l = NULL; @@ -160,22 +176,24 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const bm->totloop++; - if (example) { - CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data); - } - else { - CustomData_bmesh_set_default(&bm->ldata, &l->head.data); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data); + } + else { + CustomData_bmesh_set_default(&bm->ldata, &l->head.data); + } } return l; } -static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte) +static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, const int create_flag) { #ifdef USE_BMESH_HOLES BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool); #endif - BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL); + BMLoop *l = bm_loop_create(bm, startv, starte, f, starte->l, create_flag); bmesh_radial_append(starte, l); @@ -195,8 +213,8 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co { BMVert **verts = NULL; BMEdge **edges = NULL; - BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__); - BLI_array_fixedstack_declare(edges, BM_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(edges, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); BMLoop *l_iter; BMLoop *l_first; BMLoop *l_copy; @@ -207,7 +225,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co i = 0; do { if (copyverts) { - verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v); + verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0); } else { verts[i] = l_iter->v; @@ -230,7 +248,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co v1 = verts[(i + 1) % f->len]; } - edges[i] = BM_edge_create(bm, v1, v2, l_iter->e, FALSE); + edges[i] = BM_edge_create(bm, v1, v2, l_iter->e, 0); } else { edges[i] = l_iter->e; @@ -238,7 +256,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co i++; } while ((l_iter = l_iter->next) != l_first); - f_copy = BM_face_create(bm, verts, edges, f->len, FALSE); + f_copy = BM_face_create(bm, verts, edges, f->len, BM_CREATE_SKIP_CD); BM_elem_attrs_copy(bm, bm, f, f_copy); @@ -259,7 +277,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co * only create the face, since this calloc's the length is initialized to 0, * leave adding loops to the caller. */ -BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) +BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag create_flag) { BMFace *f; @@ -278,9 +296,13 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) f->head.htype = BM_FACE; /* allocate flag */ - f->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + f->oflags = BLI_mempool_calloc(bm->toolflagpool); + } - CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + } #ifdef USE_BMESH_HOLES f->totbounds = 0; @@ -292,7 +314,7 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) /** * \brief Main face creation function */ -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble) +BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag) { BMFace *f = NULL; BMLoop *l, *startl, *lastl; @@ -303,9 +325,9 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, return NULL; } - if (nodouble) { + if (create_flag & BM_CREATE_NO_DOUBLE) { /* Check if face already exists */ - overlap = BM_face_exists(bm, verts, len, &f); + overlap = BM_face_exists(verts, len, &f); if (overlap) { return f; } @@ -314,14 +336,14 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, } } - f = bm_face_create__internal(bm); + f = bm_face_create__internal(bm, create_flag); - startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0]); + startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag); startl->v = verts[0]; startl->e = edges[0]; for (i = 1; i < len; i++) { - l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l); + l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l, create_flag); l->f = f; bmesh_radial_append(edges[i], l); @@ -495,7 +517,9 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v) if (v->head.data) CustomData_bmesh_free_block(&bm->vdata, &v->head.data); - BLI_mempool_free(bm->toolflagpool, v->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, v->oflags); + } BLI_mempool_free(bm->vpool, v); } @@ -513,7 +537,9 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e) if (e->head.data) CustomData_bmesh_free_block(&bm->edata, &e->head.data); - BLI_mempool_free(bm->toolflagpool, e->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, e->oflags); + } BLI_mempool_free(bm->epool, e); } @@ -534,7 +560,9 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f) if (f->head.data) CustomData_bmesh_free_block(&bm->pdata, &f->head.data); - BLI_mempool_free(bm->toolflagpool, f->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f->oflags); + } BLI_mempool_free(bm->fpool, f); } @@ -558,7 +586,7 @@ static void bm_kill_only_loop(BMesh *bm, BMLoop *l) void BM_face_edges_kill(BMesh *bm, BMFace *f) { BMEdge **edges = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); BMLoop *l_iter; BMLoop *l_first; int i; @@ -582,7 +610,7 @@ void BM_face_edges_kill(BMesh *bm, BMFace *f) void BM_face_verts_kill(BMesh *bm, BMFace *f) { BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); BMLoop *l_iter; BMLoop *l_first; int i; @@ -734,7 +762,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f const int do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS); BMLoop *l_iter, *oldprev, *oldnext; BMEdge **edar = NULL; - BLI_array_fixedstack_declare(edar, BM_NGON_STACK_SIZE, len, __func__); + BLI_array_fixedstack_declare(edar, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); int i, j, edok; for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) { @@ -937,9 +965,9 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del BMEdge **edges = NULL; BMEdge **deledges = NULL; BMVert **delverts = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); - BLI_array_staticdeclare(deledges, BM_NGON_STACK_SIZE); - BLI_array_staticdeclare(delverts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE); BMVert *v1 = NULL, *v2 = NULL; const char *err = NULL; int i, tote = 0; @@ -1021,7 +1049,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del } /* create region face */ - newf = BM_face_create_ngon(bm, v1, v2, edges, tote, FALSE); + newf = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL; if (UNLIKELY(!newf || BMO_error_occurred(bm))) { if (!BMO_error_occurred(bm)) err = N_("Invalid boundary region to join faces"); @@ -1127,7 +1155,7 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *UNUSED(example)) BMLoopList *lst; #endif - f = bm_face_create__internal(bm); + f = bm_face_create__internal(bm, 0); #ifdef USE_BMESH_HOLES lst = BLI_mempool_calloc(bm->looplistpool); @@ -1211,11 +1239,11 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, } /* allocate new edge between v1 and v2 */ - e = BM_edge_create(bm, v1, v2, example, nodouble); + e = BM_edge_create(bm, v1, v2, example, nodouble ? BM_CREATE_NO_DOUBLE : 0); f2 = bm_face_create__sfme(bm, f); - f1loop = bm_loop_create(bm, v2, e, f, v2loop); - f2loop = bm_loop_create(bm, v1, e, f2, v1loop); + f1loop = bm_loop_create(bm, v2, e, f, v2loop, 0); + f2loop = bm_loop_create(bm, v1, e, f2, v1loop, 0); f1loop->prev = v2loop->prev; f2loop->prev = v1loop->prev; @@ -1322,10 +1350,10 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, * will be attached to that end and is returned in \a r_e. * * \par Examples: + * *

  *                     E
  *     Before: OV-------------TV
- *
  *                 E       RE
  *     After:  OV------NV-----TV
  * 
@@ -1347,8 +1375,8 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) valence2 = bmesh_disk_count(tv); - nv = BM_vert_create(bm, tv->co, tv); - ne = BM_edge_create(bm, nv, tv, e, FALSE); + nv = BM_vert_create(bm, tv->co, tv, 0); + ne = BM_edge_create(bm, nv, tv, e, 0); bmesh_disk_edge_remove(ne, tv); bmesh_disk_edge_remove(ne, nv); @@ -1391,7 +1419,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) nextl = nextl != nextl->radial_next ? nextl->radial_next : NULL; bmesh_radial_loop_remove(l, NULL); - nl = bm_loop_create(bm, NULL, NULL, l->f, l); + nl = bm_loop_create(bm, NULL, NULL, l->f, l, 0); nl->prev = l; nl->next = (l->next); nl->prev->next = nl; @@ -1587,7 +1615,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou if (LIKELY(radlen)) { BMLoop **loops = NULL; - BLI_array_fixedstack_declare(loops, BM_NGON_STACK_SIZE, radlen, __func__); + BLI_array_fixedstack_declare(loops, BM_DEFAULT_NGON_STACK_SIZE, radlen, __func__); killoop = ke->l; @@ -1773,14 +1801,18 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2); /* deallocate edge and its two loops as well as f2 */ - BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + } BLI_mempool_free(bm->epool, f1loop->e); bm->totedge--; BLI_mempool_free(bm->lpool, f1loop); bm->totloop--; BLI_mempool_free(bm->lpool, f2loop); bm->totloop--; - BLI_mempool_free(bm->toolflagpool, f2->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f2->oflags); + } BLI_mempool_free(bm->fpool, f2); bm->totface--; /* account for both above */ @@ -1808,23 +1840,28 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) */ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) { - BMEdge *e; - + void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE]; BMLoop **loops; int i, loops_tot; + BMEdge *e; + /* verts already spliced */ if (v == v_target) { return FALSE; } /* we can't modify the vert while iterating so first allocate an array of loops */ - loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot); - if (loops) { + loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot, + loops_stack, BM_DEFAULT_ITER_STACK_SIZE); + + if (LIKELY(loops != NULL)) { for (i = 0; i < loops_tot; i++) { loops[i]->v = v_target; } - MEM_freeN(loops); + if (loops != (BMLoop **)loops_stack) { + MEM_freeN(loops); + } } /* move all the edges from v's disk to vtarget's disk */ @@ -1898,7 +1935,7 @@ int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__); verts[0] = v; for (i = 1; i < maxindex; i++) { - verts[i] = BM_vert_create(bm, v->co, v); + verts[i] = BM_vert_create(bm, v->co, v, 0); } /* Replace v with the new verts in each group */ @@ -2064,7 +2101,7 @@ int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) e->l = l_sep->radial_next; } - ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE); + ne = BM_edge_create(bm, e->v1, e->v2, e, 0); bmesh_radial_loop_remove(l_sep, e); bmesh_radial_append(ne, l_sep); l_sep->e = ne; diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 0667ed9ea1c..5fd4a6ec7df 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -29,9 +29,18 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges); -BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example); -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble); -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble); +typedef enum eBMCreateFlag { + /* faces and edges only */ + BM_CREATE_NO_DOUBLE = (1 << 1), + /* Skip CustomData - for all element types data, + * use if we immediately write customdata into the element so this skips copying from 'example' + * args or setting defaults, speeds up conversion when data is converted all at once. */ + BM_CREATE_SKIP_CD = (1 << 2), +} eBMCreateFlag; + +BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag); +BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag); +BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag); void BM_face_edges_kill(BMesh *bm, BMFace *f); void BM_face_verts_kill(BMesh *bm, BMFace *f); diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 508b3b8fcdf..caf9f3c70d5 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -174,9 +174,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source) void **blocks = NULL; float (*cos)[3] = NULL, *w = NULL; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); int i; BM_elem_attrs_copy(bm, bm, source, target); @@ -613,10 +613,10 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source, void **vblocks = NULL; float (*cos)[3] = NULL, co[3], *w = NULL; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(vblocks, BM_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(vblocks, BM_DEFAULT_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__); int i, ax, ay; BM_elem_attrs_copy(bm, bm, source, target->f); @@ -689,9 +689,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source) void **blocks = NULL; float (*cos)[3] = NULL, *w = NULL; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); int i; i = 0; diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 1cb95d94e9b..c3f33eb95e1 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -116,10 +116,14 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons * * Caller needs to free the array. */ -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size) { BMIter iter; + BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); + /* we can't rely on coun't being set */ switch (itype) { case BM_VERTS_OF_MESH: @@ -137,7 +141,9 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { BMElem *ele; - BMElem **array = MEM_mallocN(sizeof(ele) * iter.count, __func__); + BMElem **array = iter.count > stack_array_size ? + MEM_mallocN(sizeof(ele) * iter.count, __func__) : + stack_array; int i = 0; *r_len = iter.count; /* set before iterating */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 3c42b3d610c..7291bca6356 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -107,14 +107,14 @@ typedef struct BMIter { BMesh *bm; void (*begin)(struct BMIter *iter); void *(*step)(struct BMIter *iter); - /* +#if 0 union { void *p; int i; long l; float f; } filter; - */ +#endif int count; /* note, only some iterators set this, don't rely on it */ char itype; } BMIter; @@ -125,7 +125,8 @@ __attribute__((warn_unused_result)) #endif ; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, + void **stack_array, int stack_array_size) #ifdef __GNUC__ __attribute__((warn_unused_result)) #endif diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index d3e3bcd3556..590edc45d07 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -42,8 +42,8 @@ #include "intern/bmesh_private.h" /* used as an extern, defined in bmesh.h */ -BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512}; -BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512}; +const BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512}; +const BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512}; static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) { @@ -59,9 +59,45 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) #ifdef USE_BMESH_HOLES bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, 0); #endif +} - /* allocate one flag pool that we don't get rid of. */ - bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), 512, 512, 0); +void BM_mesh_elem_toolflags_ensure(BMesh *bm) +{ + if (bm->toolflagpool == NULL) { + const int totflagpool_size = max_ii(512, bm->totvert + bm->totedge + bm->totface); + BLI_mempool *toolflagpool; + + BMIter iter; + BMElemF *ele; + const char iter_types[3] = {BM_VERTS_OF_MESH, + BM_EDGES_OF_MESH, + BM_FACES_OF_MESH}; + + int i; + + BLI_assert(bm->totflags == 0); + + /* allocate one flag pool that we don't get rid of. */ + toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), totflagpool_size, 512, 0); + + + for (i = 0; i < 3; i++) { + BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { + ele->oflags = BLI_mempool_calloc(toolflagpool); + } + } + + bm->toolflagpool = toolflagpool; + bm->totflags = 1; + } +} + +void BM_mesh_elem_toolflags_clear(BMesh *bm) +{ + if (bm->toolflagpool) { + BLI_mempool_destroy(bm->toolflagpool); + bm->toolflagpool = NULL; + } } /** @@ -73,7 +109,7 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) * * \note ob is needed by multires */ -BMesh *BM_mesh_create(BMAllocTemplate *allocsize) +BMesh *BM_mesh_create(const BMAllocTemplate *allocsize) { /* allocate the structure */ BMesh *bm = MEM_callocN(sizeof(BMesh), __func__); @@ -83,7 +119,7 @@ BMesh *BM_mesh_create(BMAllocTemplate *allocsize) /* allocate one flag pool that we don't get rid of. */ bm->stackdepth = 1; - bm->totflags = 1; + bm->totflags = 0; CustomData_reset(&bm->vdata); CustomData_reset(&bm->edata); @@ -143,7 +179,7 @@ void BM_mesh_data_free(BMesh *bm) BLI_mempool_destroy(bm->fpool); /* destroy flag pool */ - BLI_mempool_destroy(bm->toolflagpool); + BM_mesh_elem_toolflags_clear(bm); #ifdef USE_BMESH_HOLES BLI_mempool_destroy(bm->looplistpool); @@ -170,6 +206,11 @@ void BM_mesh_clear(BMesh *bm) bm->stackdepth = 1; bm->totflags = 1; + + CustomData_reset(&bm->vdata); + CustomData_reset(&bm->edata); + CustomData_reset(&bm->ldata); + CustomData_reset(&bm->pdata); } /** diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 8b6ef9aa3e0..8baba568fb8 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -29,7 +29,9 @@ struct BMAllocTemplate; -BMesh *BM_mesh_create(struct BMAllocTemplate *allocsize); +void BM_mesh_elem_toolflags_ensure(BMesh *bm); +void BM_mesh_elem_toolflags_clear(BMesh *bm); +BMesh *BM_mesh_create(const struct BMAllocTemplate *allocsize); void BM_mesh_free(BMesh *bm); void BM_mesh_data_free(BMesh *bm); @@ -55,7 +57,11 @@ typedef struct BMAllocTemplate { int totvert, totedge, totloop, totface; } BMAllocTemplate; -extern BMAllocTemplate bm_mesh_allocsize_default; -extern BMAllocTemplate bm_mesh_chunksize_default; +extern const BMAllocTemplate bm_mesh_allocsize_default; +extern const BMAllocTemplate bm_mesh_chunksize_default; + +enum { + BM_MESH_CREATE_USE_TOOLFLAGS = (1 << 0) +}; #endif /* __BMESH_MESH_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 62abf43829b..388d148377a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -206,7 +206,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { - v = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL); + v = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(v, i); /* set_ok */ vt[i] = v; @@ -220,11 +220,11 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) normal_short_to_float_v3(v->no, mvert->no); - BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f); - - /* Copy Custom Dat */ + /* Copy Custom Data */ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data); + BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f); + /* set shapekey data */ if (me->key) { /* set shape key original index */ @@ -254,7 +254,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) medge = me->medge; for (i = 0; i < me->totedge; i++, medge++) { - e = BM_edge_create(bm, vt[medge->v1], vt[medge->v2], NULL, FALSE); + e = BM_edge_create(bm, vt[medge->v1], vt[medge->v2], NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(e, i); /* set_ok */ et[i] = e; @@ -312,7 +312,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) } #endif - f = BM_face_create(bm, verts, fedges, mpoly->totloop, FALSE); + f = BM_face_create(bm, verts, fedges, mpoly->totloop, BM_CREATE_SKIP_CD); if (UNLIKELY(f == NULL)) { printf("%s: Warning! Bad face in mesh" @@ -338,7 +338,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) j = 0; BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, j) { /* Save index of correspsonding MLoop */ - BM_elem_index_set(l, mpoly->loopstart + j); /* set_loop */ + CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart + j, &l->head.data); } /* Copy Custom Data */ @@ -347,23 +347,6 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) bm->elem_index_dirty &= ~BM_FACE; /* added in order, clear dirty flag */ - { - BMIter fiter; - BMIter liter; - - /* Copy over loop CustomData. Doing this in a separate loop isn't necessary - * but is an optimization, to avoid copying a bunch of interpolated customdata - * for each BMLoop (from previous BMLoops using the same edge), always followed - * by freeing the interpolated data and overwriting it with data from the Mesh. */ - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - int li = BM_elem_index_get(l); - CustomData_to_bmesh_block(&me->ldata, &bm->ldata, li, &l->head.data); - BM_elem_index_set(l, 0); /* set_loop */ - } - } - } - if (me->mselect && me->totselect != 0) { BMVert **vert_array = MEM_callocN(sizeof(BMVert *) * bm->totvert, diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 62374d8b7bb..89516061f91 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -118,7 +118,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) e = v->e; do { e = bmesh_disk_edge_next(e, v); - if (!(BM_edge_share_face_count(e, v->e))) { + if (!(BM_edge_share_face_check(e, v->e))) { keepedge = e; baseedge = v->e; break; @@ -142,9 +142,10 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) return FALSE; } #else - BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE); - - if (!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE)) { + if (UNLIKELY(!BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE))) { + return FALSE; + } + else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE))) { return FALSE; } #endif diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 31698f0abc1..58c6e051e48 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -47,9 +47,9 @@ * "in" (e.g. edgefacein). for three-type slots, use geom. * * for output slots, for single-type geometry slots, use the type name plus "out", - * (e.g. vertout), for double-type slots, use the two type names plus "out", - * (e.g. vertfaceout), for three-type slots, use geom. note that you can also - * use more esohteric names (e.g. skirtout) so long as the comment next to the + * (e.g. verts.out), for double-type slots, use the two type names plus "out", + * (e.g. vertfaces.out), for three-type slots, use geom. note that you can also + * use more esohteric names (e.g. geom_skirt.out) so long as the comment next to the * slot definition tells you what types of elements are in it. * */ @@ -59,8 +59,10 @@ #include "bmesh.h" #include "intern/bmesh_private.h" -/* ok, I'm going to write a little docgen script. so all - * bmop comments must conform to the following template/rules: +/* The formatting of these bmesh operators is parsed by + * 'doc/python_api/rst_from_bmesh_opdefines.py' + * for use in python docs, so reStructuredText may be used + * rather then doxygen syntax. * * template (py quotes used because nested comments don't work * on all C compilers): @@ -79,250 +81,291 @@ * so the first line is the "title" of the bmop. * subsequent line blocks separated by blank lines * are paragraphs. individual descriptions of slots - * would be extracted from comments - * next to them, e.g. + * are extracted from comments next to them. * - * {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, //output slot, boundary region + * eg: + * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, """ output slot, boundary region """ * - * the doc generator would automatically detect the presence of "output slot" - * and flag the slot as an output. the same happens for "input slot". also - * note that "edges", "faces", "verts", "loops", and "geometry" are valid - * substitutions for "slot". + * ... or: * - * note that slots default to being input slots. + * """ output slot, boundary region """ + * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + * + * Both are acceptable. + * note that '//' comments are ignored. */ /* - * Vertex Smooth + * Vertex Smooth. * * Smooths vertices by using a basic vertex averaging scheme. */ static BMOpDefine bmo_smooth_vert_def = { "smooth_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, /* set vertices close to the x axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, /* set vertices close to the y axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, /* set vertices close to the z axis before the operation to 0 */ - {BMO_OP_SLOT_FLT, "clipdist"}, /* clipping threshod for the above three slots */ - {BMO_OP_SLOT_BOOL, "use_axis_x"}, /* smooth vertices along X axis */ - {BMO_OP_SLOT_BOOL, "use_axis_y"}, /* smooth vertices along Y axis */ - {BMO_OP_SLOT_BOOL, "use_axis_z"}, /* smooth vertices along Z axis */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */ + {"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */ + {"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */ + {"clip_dist", BMO_OP_SLOT_FLT}, /* clipping threshold for the above three slots */ + {"use_axis_x", BMO_OP_SLOT_BOOL}, /* smooth vertices along X axis */ + {"use_axis_y", BMO_OP_SLOT_BOOL}, /* smooth vertices along Y axis */ + {"use_axis_z", BMO_OP_SLOT_BOOL}, /* smooth vertices along Z axis */ + {{'\0'}}, }, + {{{'\0'}}}, /* no output */ bmo_smooth_vert_exec, 0 }; /* - * Vertext Smooth Laplacian + * Vertext Smooth Laplacian. + * * Smooths vertices by using Laplacian smoothing propose by. - * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow -*/ + * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow. + */ static BMOpDefine bmo_smooth_laplacian_vert_def = { "smooth_laplacian_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices - {BMO_OP_SLOT_FLT, "lambda"}, //lambda param - {BMO_OP_SLOT_FLT, "lambda_border"}, //lambda param in border - {BMO_OP_SLOT_BOOL, "use_x"}, //Smooth object along X axis - {BMO_OP_SLOT_BOOL, "use_y"}, //Smooth object along Y axis - {BMO_OP_SLOT_BOOL, "use_z"}, //Smooth object along Z axis - {BMO_OP_SLOT_BOOL, "volume_preservation"}, //Apply volume preservation after smooth - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"lambda", BMO_OP_SLOT_FLT}, /* lambda param */ + {"lambda_border", BMO_OP_SLOT_FLT}, /* lambda param in border */ + {"use_x", BMO_OP_SLOT_BOOL}, /* Smooth object along X axis */ + {"use_y", BMO_OP_SLOT_BOOL}, /* Smooth object along Y axis */ + {"use_z", BMO_OP_SLOT_BOOL}, /* Smooth object along Z axis */ + {"preserve_volume", BMO_OP_SLOT_BOOL}, /* Apply volume preservation after smooth */ + {{'\0'}}, }, + {{{'\0'}}}, /* no output */ bmo_smooth_laplacian_vert_exec, 0 }; /* - * Right-Hand Faces + * Right-Hand Faces. * * Computes an "outside" normal for the specified input faces. */ - static BMOpDefine bmo_recalc_face_normals_def = { "recalc_face_normals", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "do_flip"}, /* internal flag, used by bmesh_rationalize_normals */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_flip", BMO_OP_SLOT_BOOL}, /* Reverse the result */ + {{'\0'}}, }, + {{{'\0'}}}, /* no output */ bmo_recalc_face_normals_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Region Extend + * Region Extend. * * used to implement the select more/less tools. * this puts some geometry surrounding regions of - * geometry in geom into geomout. + * geometry in geom into geom.out. * - * if usefaces is 0 then geomout spits out verts and edges, + * if use_faces is 0 then geom.out spits out verts and edges, * otherwise it spits out faces. */ static BMOpDefine bmo_region_extend_def = { "region_extend", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output slot, computed boundary geometry. */ - {BMO_OP_SLOT_BOOL, "constrict"}, /* find boundary inside the regions, not outside. */ - {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"use_constrict", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */ + {"use_faces", BMO_OP_SLOT_BOOL}, /* extend from faces instead of edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */ + {{'\0'}}, }, bmo_region_extend_exec, 0 }; /* - * Edge Rotate + * Edge Rotate. * * Rotates edges topologically. Also known as "spin edge" to some people. - * Simple example: [/] becomes [|] then [\]. + * Simple example: ``[/] becomes [|] then [\]``. */ static BMOpDefine bmo_rotate_edges_def = { "rotate_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly spun edges */ - {BMO_OP_SLOT_BOOL, "ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate edge counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly spun edges */ + {{'\0'}}, }, bmo_rotate_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Reverse Faces + * Reverse Faces. * - * Reverses the winding (vertex order) of faces. This has the effect of - * flipping the normal. + * Reverses the winding (vertex order) of faces. + * This has the effect of flipping the normal. */ static BMOpDefine bmo_reverse_faces_def = { "reverse_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, + {{{'\0'}}}, /* no output */ bmo_reverse_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Edge Bisect + * Edge Bisect. * * Splits input edges (but doesn't do anything else). * This creates a 2-valence vert. */ static BMOpDefine bmo_bisect_edges_def = { "bisect_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_INT, "numcuts"}, /* number of cuts */ - {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, /* newly created vertices and edges */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* newly created vertices and edges */ + {{'\0'}}, }, bmo_bisect_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Mirror + * Mirror. * * Mirrors geometry along an axis. The resulting geometry is welded on using - * mergedist. Pairs of original/mirrored vertices are welded using the mergedist + * merge_dist. Pairs of original/mirrored vertices are welded using the merge_dist * parameter (which defines the minimum distance for welding to happen). */ - static BMOpDefine bmo_mirror_def = { "mirror", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */ - {BMO_OP_SLOT_FLT, "mergedist"}, /* maximum distance for merging. does no merging if 0. */ - {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, /* output geometry, mirrored */ - {BMO_OP_SLOT_INT, "axis"}, /* the axis to use, 0, 1, or 2 for x, y, z */ - {BMO_OP_SLOT_BOOL, "mirror_u"}, /* mirror UVs across the u axis */ - {BMO_OP_SLOT_BOOL, "mirror_v"}, /* mirror UVs across the v axis */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining the mirror transformation */ + {"merge_dist", BMO_OP_SLOT_FLT}, /* maximum distance for merging. does no merging if 0. */ + {"axis", BMO_OP_SLOT_INT}, /* the axis to use, 0, 1, or 2 for x, y, z */ + {"mirror_u", BMO_OP_SLOT_BOOL}, /* mirror UVs across the u axis */ + {"mirror_v", BMO_OP_SLOT_BOOL}, /* mirror UVs across the v axis */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry, mirrored */ + {{'\0'}}, + }, bmo_mirror_exec, 0, }; /* - * Find Doubles + * Find Doubles. * - * Takes input verts and find vertices they should weld to. Outputs a - * mapping slot suitable for use with the weld verts bmop. + * Takes input verts and find vertices they should weld to. + * Outputs a mapping slot suitable for use with the weld verts bmop. * * If keep_verts is used, vertices outside that set can only be merged * with vertices in that set. */ static BMOpDefine bmo_find_doubles_def = { "find_doubles", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "keep_verts"}, /* list of verts to keep */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {BMO_OP_SLOT_MAPPING, "targetmapout"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"keep_verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* list of verts to keep */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + /* slots_out */ + {{"targetmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, bmo_find_doubles_exec, 0, }; /* - * Remove Doubles + * Remove Doubles. * * Finds groups of vertices closer then dist and merges them together, * using the weld verts bmop. */ static BMOpDefine bmo_remove_doubles_def = { "remove_doubles", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_remove_doubles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Auto Merge + * Auto Merge. * - * Finds groups of vertices closer then dist and merges them together, + * Finds groups of vertices closer then **dist** and merges them together, * using the weld verts bmop. The merges must go from a vert not in - * verts to one in verts. + * **verts** to one in **verts**. */ static BMOpDefine bmo_automerge_def = { "automerge", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_automerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Collapse Connected + * Collapse Connected. * * Collapses connected vertices */ static BMOpDefine bmo_collapse_def = { "collapse", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_collapse_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; - /* - * Facedata point Merge + * Face-Data Point Merge. * * Merge uv/vcols at a specific vertex. */ static BMOpDefine bmo_pointmerge_facedata_def = { "pointmerge_facedata", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap verte */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_pointmerge_facedata_exec, 0, }; /* - * Average Vertices Facevert Data + * Average Vertices Facevert Data. * * Merge uv/vcols associated with the input vertices at * the bounding box center. (I know, it's not averaging but @@ -330,145 +373,189 @@ static BMOpDefine bmo_pointmerge_facedata_def = { */ static BMOpDefine bmo_average_vert_facedata_def = { "average_vert_facedata", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_average_vert_facedata_exec, 0, }; /* - * Point Merge + * Point Merge. * * Merge verts together at a point. */ static BMOpDefine bmo_pointmerge_def = { "pointmerge", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {BMO_OP_SLOT_VEC, "merge_co"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {"merge_co", BMO_OP_SLOT_VEC}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_pointmerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Collapse Connected UVs + * Collapse Connected UV's. * * Collapses connected UV vertices. */ static BMOpDefine bmo_collapse_uvs_def = { "collapse_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_collapse_uvs_exec, 0, }; /* - * Weld Verts + * Weld Verts. * - * Welds verts together (kindof like remove doubles, merge, etc, all of which + * Welds verts together (kind-of like remove doubles, merge, etc, all of which * use or will use this bmop). You pass in mappings from vertices to the vertices * they weld with. */ static BMOpDefine bmo_weld_verts_def = { "weld_verts", - {{BMO_OP_SLOT_MAPPING, "targetmap"}, /* maps welded vertices to verts they should weld to */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + /* maps welded vertices to verts they should weld to */ + {{"targetmap", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_weld_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Make Vertex + * Make Vertex. * * Creates a single vertex; this bmop was necessary * for click-create-vertex. */ static BMOpDefine bmo_create_vert_def = { "create_vert", - {{BMO_OP_SLOT_VEC, "co"}, /* the coordinate of the new vert */ - {BMO_OP_SLOT_ELEMENT_BUF, "newvertout"}, /* the new vert */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"co", BMO_OP_SLOT_VEC}, /* the coordinate of the new vert */ + {{'\0'}}, + }, + /* slots_out */ + {{"vert.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* the new vert */ + {{'\0'}}, + }, bmo_create_vert_exec, 0, }; /* - * Join Triangles + * Join Triangles. * * Tries to intelligently join triangles according * to various settings and stuff. */ static BMOpDefine bmo_join_triangles_def = { "join_triangles", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input geometry. */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* joined faces */ - {BMO_OP_SLOT_BOOL, "cmp_sharp"}, - {BMO_OP_SLOT_BOOL, "cmp_uvs"}, - {BMO_OP_SLOT_BOOL, "cmp_vcols"}, - {BMO_OP_SLOT_BOOL, "cmp_materials"}, - {BMO_OP_SLOT_FLT, "limit"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */ + {"cmp_sharp", BMO_OP_SLOT_BOOL}, + {"cmp_uvs", BMO_OP_SLOT_BOOL}, + {"cmp_vcols", BMO_OP_SLOT_BOOL}, + {"cmp_materials", BMO_OP_SLOT_BOOL}, + {"limit", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* joined faces */ + {{'\0'}}, + }, bmo_join_triangles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Contextual Create + * Contextual Create. * - * This is basically fkey, it creates + * This is basically F-key, it creates * new faces from vertices, makes stuff from edge nets, - * makes wire edges, etc. It also dissolves - * faces. + * makes wire edges, etc. It also dissolves faces. * * Three verts become a triangle, four become a quad. Two * become a wire edge. */ static BMOpDefine bmo_contextual_create_def = { "contextual_create", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* newly-made face(s) */ + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry. */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth to use */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */ /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly-made edge(s) */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0, /* null-terminating sentinel */}}, + {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */ + {{'\0'}}, + }, bmo_contextual_create_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Bridge edge loops with faces + * Bridge edge loops with faces. */ static BMOpDefine bmo_bridge_loops_def = { "bridge_loops", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */ - {BMO_OP_SLOT_BOOL, "use_merge"}, - {BMO_OP_SLOT_FLT, "merge_factor"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {"use_merge", BMO_OP_SLOT_BOOL}, + {"merge_factor", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {{'\0'}}, + }, bmo_bridge_loops_exec, 0, }; +/* + * Edge Net Fill. + * + * Create faces defined by enclosed edges. + */ static BMOpDefine bmo_edgenet_fill_def = { "edgenet_fill", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_MAPPING, "restrict"}, /* restricts edges to groups. maps edges to integer */ - {BMO_OP_SLOT_BOOL, "use_restrict"}, - {BMO_OP_SLOT_BOOL, "use_fill_check"}, - {BMO_OP_SLOT_ELEMENT_BUF, "excludefaces"}, /* list of faces to ignore for manifold check */ - {BMO_OP_SLOT_MAPPING, "faceout_groupmap"}, /* maps new faces to the group numbers they came fro */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + /* restricts edges to groups. maps edges to integer */ + {"restrict", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_BOOL}}, + {"use_restrict", BMO_OP_SLOT_BOOL}, + {"use_fill_check", BMO_OP_SLOT_BOOL}, + {"exclude_faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* list of faces to ignore for manifold check */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* material to use */ + {{'\0'}}, + }, + /* slots_out */ + /* maps new faces to the group numbers they came from */ + {{"face_groupmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new face */ + {{'\0'}}, + }, bmo_edgenet_fill_exec, 0, }; /* - * Edgenet Prepare + * Edgenet Prepare. * * Identifies several useful edge loop cases and modifies them so * they'll become a face when edgenet_fill is called. The cases covered are: @@ -479,708 +566,992 @@ static BMOpDefine bmo_edgenet_fill_def = { */ static BMOpDefine bmo_edgenet_prepare_def = { "edgenet_prepare", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* new edges */ - {0, /* null-terminating sentinel */}}, - bmo_edgenet_prepare, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ + {{'\0'}}, + }, + bmo_edgenet_prepare_exec, 0, }; /* - * Rotate + * Rotate. * - * Rotate vertices around a center, using a 3x3 rotation - * matrix. Equivalent of the old rotateflag function. + * Rotate vertices around a center, using a 3x3 rotation matrix. */ static BMOpDefine bmo_rotate_def = { "rotate", - {{BMO_OP_SLOT_VEC, "cent"}, /* center of rotation */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining rotation */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"cent", BMO_OP_SLOT_VEC}, /* center of rotation */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining rotation */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_rotate_exec, 0, }; /* - * Translate + * Translate. * - * Translate vertices by an offset. Equivalent of the - * old translateflag function. + * Translate vertices by an offset. */ static BMOpDefine bmo_translate_def = { "translate", - {{BMO_OP_SLOT_VEC, "vec"}, /* translation offset */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"vec", BMO_OP_SLOT_VEC}, /* translation offset */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_translate_exec, 0, }; /* - * Scale + * Scale. * * Scales vertices by an offset. */ static BMOpDefine bmo_scale_def = { "scale", - {{BMO_OP_SLOT_VEC, "vec"}, /* scale factor */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"vec", BMO_OP_SLOT_VEC}, /* scale factor */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_scale_exec, 0, }; /* - * Transform + * Transform. * * Transforms a set of vertices by a matrix. Multiplies * the vertex coordinates with the matrix. */ static BMOpDefine bmo_transform_def = { "transform", - {{BMO_OP_SLOT_MAT, "mat"}, /* transform matrix */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"matrix", BMO_OP_SLOT_MAT}, /* transform matrix */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_transform_exec, 0, }; /* - * Object Load BMesh + * Object Load BMesh. * * Loads a bmesh into an object/mesh. This is a "private" * bmop. */ static BMOpDefine bmo_object_load_bmesh_def = { "object_load_bmesh", - {{BMO_OP_SLOT_PTR, "scene"}, - {BMO_OP_SLOT_PTR, "object"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"scene", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_SCENE}}, + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_object_load_bmesh_exec, 0, }; /* - * BMesh to Mesh + * BMesh to Mesh. * * Converts a bmesh to a Mesh. This is reserved for exiting editmode. */ static BMOpDefine bmo_bmesh_to_mesh_def = { "bmesh_to_mesh", - {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a mesh structure to fill in */ - {BMO_OP_SLOT_PTR, "object"}, /* pointer to an object structure */ - {BMO_OP_SLOT_BOOL, "notessellation"}, /* don't calculate mfaces */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + { + /* pointer to a mesh structure to fill in */ + {"mesh", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, + /* pointer to an object structure */ + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"skip_tessface", BMO_OP_SLOT_BOOL}, /* don't calculate mfaces */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_bmesh_to_mesh_exec, 0, }; /* - * Mesh to BMesh + * Mesh to BMesh. * * Load the contents of a mesh into the bmesh. this bmop is private, it's * reserved exclusively for entering editmode. */ static BMOpDefine bmo_mesh_to_bmesh_def = { "mesh_to_bmesh", - {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a Mesh structure */ - {BMO_OP_SLOT_PTR, "object"}, /* pointer to an Object structure */ - {BMO_OP_SLOT_BOOL, "set_shapekey"}, /* load active shapekey coordinates into verts */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + { + /* pointer to a Mesh structure */ + {"mesh", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, + /* pointer to an Object structure */ + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_mesh_to_bmesh_exec, 0 }; /* - * Individual Face Extrude + * Individual Face Extrude. * * Extrudes faces individually. */ static BMOpDefine bmo_extrude_discrete_faces_def = { "extrude_discrete_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "skirtout"}, /* output skirt geometry, faces and edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, bmo_extrude_discrete_faces_exec, 0 }; /* - * Extrude Only Edges + * Extrude Only Edges. * * Extrudes Edges into faces, note that this is very simple, there's no fancy * winged extrusion. */ static BMOpDefine bmo_extrude_edge_only_def = { "extrude_edge_only", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output geometry */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry */ + {{'\0'}}, + }, bmo_extrude_edge_only_exec, 0 }; /* - * Individual Vertex Extrude + * Individual Vertex Extrude. * * Extrudes wire edges from vertices. */ static BMOpDefine bmo_extrude_vert_indiv_def = { "extrude_vert_indiv", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output wire edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output wire edges */ + {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, + }, bmo_extrude_vert_indiv_exec, 0 }; +/* + * Connect Verts. + * + * Split faces by adding edges that connect **verts**. + */ static BMOpDefine bmo_connect_verts_def = { "connect_verts", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, bmo_connect_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Extrude Faces. + * + * Extrude operator (does not transform) + */ static BMOpDefine bmo_extrude_face_region_def = { "extrude_face_region", - {{BMO_OP_SLOT_ELEMENT_BUF, "edgefacein"}, - {BMO_OP_SLOT_MAPPING, "exclude"}, - {BMO_OP_SLOT_BOOL, "alwayskeeporig"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */ + {"edges_exclude", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, + {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, bmo_extrude_face_region_exec, 0 }; +/* + * Dissolve Verts. + */ static BMOpDefine bmo_dissolve_verts_def = { "dissolve_verts", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_dissolve_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Edges. + */ static BMOpDefine bmo_dissolve_edges_def = { "dissolve_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, - {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, bmo_dissolve_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Edge Loop. + */ static BMOpDefine bmo_dissolve_edge_loop_def = { "dissolve_edge_loop", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, bmo_dissolve_edgeloop_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Faces. + */ static BMOpDefine bmo_dissolve_faces_def = { "dissolve_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, - {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, bmo_dissolve_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Limited Dissolve. + * + * Dissolve planar faces and co-linear edges. + */ static BMOpDefine bmo_dissolve_limit_def = { "dissolve_limit", - {{BMO_OP_SLOT_FLT, "angle_limit"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_BOOL, "use_dissolve_boundaries"}, - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL}, + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_dissolve_limit_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Triangulate. + */ static BMOpDefine bmo_triangulate_def = { "triangulate", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, - {BMO_OP_SLOT_MAPPING, "facemap"}, - {BMO_OP_SLOT_BOOL, "use_beauty"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_beauty", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, bmo_triangulate_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Un-Subdivide. + * + * Reduce detail in geometry containing grids. + */ static BMOpDefine bmo_unsubdivide_def = { "unsubdivide", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_INT, "iterations"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"iterations", BMO_OP_SLOT_INT}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_unsubdivide_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Subdivide Edges. + * + * Advanced operator for subdividing edges + * with options for face patterns, smoothing and randomization. + */ static BMOpDefine bmo_subdivide_edges_def = { "subdivide_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_FLT, "smooth"}, - {BMO_OP_SLOT_FLT, "fractal"}, - {BMO_OP_SLOT_FLT, "along_normal"}, - {BMO_OP_SLOT_INT, "numcuts"}, - {BMO_OP_SLOT_INT, "seed"}, - {BMO_OP_SLOT_MAPPING, "custompatterns"}, - {BMO_OP_SLOT_MAPPING, "edgepercents"}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"smooth", BMO_OP_SLOT_FLT}, + {"fractal", BMO_OP_SLOT_FLT}, + {"along_normal", BMO_OP_SLOT_FLT}, + {"cuts", BMO_OP_SLOT_INT}, + {"seed", BMO_OP_SLOT_INT}, + {"custom_patterns", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */ + {"edge_percents", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_FLT}}, - /* these next three can have multiple types of elements in them */ - {BMO_OP_SLOT_ELEMENT_BUF, "outinner"}, - {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* contains all output geometr */ - - {BMO_OP_SLOT_INT, "quadcornertype"}, /* quad corner type, see bmesh_operators.h */ - {BMO_OP_SLOT_BOOL, "use_gridfill"}, /* fill in fully-selected faces with a grid */ - {BMO_OP_SLOT_BOOL, "use_singleedge"}, /* tessellate the case of one edge selected in a quad or triangle */ - {BMO_OP_SLOT_BOOL, "use_sphere"}, /* for making new primitives only */ - - {0} /* null-terminating sentinel */, + {"quad_corner_type", BMO_OP_SLOT_INT}, /* quad corner type, see bmesh_operators.h */ + {"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */ + {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */ + {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */ + {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */ + {{'\0'}}, + }, + /* slots_out */ + {/* these next three can have multiple types of elements in them */ + {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometr */ + {{'\0'}}, }, bmo_subdivide_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Delete Geometry. + * + * Utility operator to delete geometry. + */ static BMOpDefine bmo_delete_def = { "delete", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_INT, "context"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"context", BMO_OP_SLOT_INT}, /* enum DEL_VERTS ... */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_delete_exec, 0 }; +/* + * Duplicate Geometry. + * + * Utility operator to duplicate geometry, + * optionally into a destination mesh. + */ static BMOpDefine bmo_duplicate_def = { "duplicate", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "origout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* destination bmesh, if NULL will use current on */ + {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* facemap maps from source faces to dupe * faces, and from dupe faces to source faces */ - {BMO_OP_SLOT_MAPPING, "facemap"}, - {BMO_OP_SLOT_MAPPING, "boundarymap"}, - {BMO_OP_SLOT_MAPPING, "isovertmap"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {0} /* null-terminating sentinel */}, + {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, bmo_duplicate_exec, 0 }; +/* + * Split Off Geometry. + * + * Disconnect geometry from adjacent edges and faces, + * optionally into a destination mesh. + */ static BMOpDefine bmo_split_def = { "split", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {BMO_OP_SLOT_MAPPING, "boundarymap"}, - {BMO_OP_SLOT_MAPPING, "isovertmap"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* destination bmesh, if NULL will use current one */ + {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, bmo_split_exec, 0 }; /* - * Spin + * Spin. * * Extrude or duplicate geometry a number of times, * rotating and possibly translating after each step */ static BMOpDefine bmo_spin_def = { "spin", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "lastout"}, /* result of last step */ - {BMO_OP_SLOT_VEC, "cent"}, /* rotation center */ - {BMO_OP_SLOT_VEC, "axis"}, /* rotation axis */ - {BMO_OP_SLOT_VEC, "dvec"}, /* translation delta per step */ - {BMO_OP_SLOT_FLT, "ang"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_INT, "steps"}, /* number of steps */ - {BMO_OP_SLOT_BOOL, "do_dupli"}, /* duplicate or extrude? */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"cent", BMO_OP_SLOT_VEC}, /* rotation center */ + {"axis", BMO_OP_SLOT_VEC}, /* rotation axis */ + {"dvec", BMO_OP_SLOT_VEC}, /* translation delta per step */ + {"angle", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"steps", BMO_OP_SLOT_INT}, /* number of steps */ + {"use_duplicate", BMO_OP_SLOT_BOOL}, /* duplicate or extrude? */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */ + {{'\0'}}, + }, bmo_spin_exec, 0 }; /* - * Similar faces search + * Similar Faces Search. * * Find similar faces (area/material/perimeter, ...). */ static BMOpDefine bmo_similar_faces_def = { "similar_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, bmo_similar_faces_exec, 0 }; /* - * Similar edges search + * Similar Edges Search. * * Find similar edges (length, direction, edge, seam, ...). */ static BMOpDefine bmo_similar_edges_def = { "similar_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */ + {{'\0'}}, + }, bmo_similar_edges_exec, 0 }; /* - * Similar vertices search + * Similar Verts Search. * * Find similar vertices (normal, face, vertex group, ...). */ static BMOpDefine bmo_similar_verts_def = { "similar_verts", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, + }, bmo_similar_verts_exec, 0 }; /* - * uv rotation - * cycle the uvs + * UV Rotation. + * + * Cycle the loop UV's */ static BMOpDefine bmo_rotate_uvs_def = { "rotate_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "dir"}, /* direction */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + /* slots_out */ + {{{'\0'}}}, /* no output */ bmo_rotate_uvs_exec, 0 }; /* - * uv reverse - * reverse the uvs + * UV Reverse. + * + * Reverse the UV's */ static BMOpDefine bmo_reverse_uvs_def = { "reverse_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_reverse_uvs_exec, 0 }; /* - * color rotation - * cycle the colors + * Color Rotation. + * + * Cycle the loop colors */ static BMOpDefine bmo_rotate_colors_def = { "rotate_colors", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "dir"}, /* direction */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_rotate_colors_exec, 0 }; /* - * color reverse - * reverse the colors + * Color Reverse + * + * Reverse the loop colors. */ static BMOpDefine bmo_reverse_colors_def = { "reverse_colors", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_reverse_colors_exec, 0 }; /* - * Similar vertices search + * Shortest Path. * - * Find similar vertices (normal, face, vertex group, ...). + * Select the shortest path between 2 verts. */ static BMOpDefine bmo_shortest_path_def = { "shortest_path", - {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"vert_start", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* start vertex */ + {"vert_end", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* end vertex */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, + }, bmo_shortest_path_exec, 0 }; /* - * Edge Split + * Edge Split. * * Disconnects faces along input edges. */ static BMOpDefine bmo_split_edges_def = { "split_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* old output disconnected edges */ + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* optional tag verts, use to have greater control of splits */ - {BMO_OP_SLOT_BOOL, "use_verts"}, /* use 'verts' for splitting, else just find verts to split from edges */ - {0} /* null-terminating sentinel */}, + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* optional tag verts, use to have greater control of splits */ + {"use_verts", BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */ + {{'\0'}}, + }, bmo_split_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Create Grid + * Create Grid. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_grid_def = { "create_grid", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "xsegments"}, /* number of x segments */ - {BMO_OP_SLOT_INT, "ysegments"}, /* number of y segments */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the grid */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"x_segments", BMO_OP_SLOT_INT}, /* number of x segments */ + {"y_segments", BMO_OP_SLOT_INT}, /* number of y segments */ + {"size", BMO_OP_SLOT_FLT}, /* size of the grid */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_grid_exec, 0, }; /* - * Create UV Sphere + * Create UV Sphere. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_uvsphere_def = { "create_uvsphere", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "segments"}, /* number of u segments */ - {BMO_OP_SLOT_INT, "revolutions"}, /* number of v segment */ - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"u_segments", BMO_OP_SLOT_INT}, /* number of u segments */ + {"v_segments", BMO_OP_SLOT_INT}, /* number of v segment */ + {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_uvsphere_exec, 0, }; /* - * Create Ico Sphere + * Create Ico-Sphere. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_icosphere_def = { "create_icosphere", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "subdivisions"}, /* how many times to recursively subdivide the sphere */ - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"subdivisions", BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */ + {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_icosphere_exec, 0, }; /* - * Create Suzanne + * Create Suzanne. * - * Creates a monkey. Be wary. + * Creates a monkey (standard blender primitive). */ static BMOpDefine bmo_create_monkey_def = { "create_monkey", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_monkey_exec, 0, }; /* - * Create Cone + * Create Cone. * * Creates a cone with variable depth at both ends */ static BMOpDefine bmo_create_cone_def = { "create_cone", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ - {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter1"}, /* diameter of one end */ - {BMO_OP_SLOT_FLT, "diameter2"}, /* diameter of the opposite */ - {BMO_OP_SLOT_FLT, "depth"}, /* distance between ends */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ + {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ + {"segments", BMO_OP_SLOT_INT}, + {"diameter1", BMO_OP_SLOT_FLT}, /* diameter of one end */ + {"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */ + {"depth", BMO_OP_SLOT_FLT}, /* distance between ends */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_cone_exec, 0, }; /* - * Creates a circle + * Creates a Circle. */ static BMOpDefine bmo_create_circle_def = { "create_circle", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ - {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter of one end */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ + {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ + {"segments", BMO_OP_SLOT_INT}, + {"diameter", BMO_OP_SLOT_FLT}, /* diameter of one end */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_circle_exec, 0, }; /* - * Create Cone + * Create Cube * - * Creates a cone with variable depth at both ends + * Creates a cube. */ static BMOpDefine bmo_create_cube_def = { "create_cube", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the cube */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"size", BMO_OP_SLOT_FLT}, /* size of the cube */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_cube_exec, 0, }; /* - * Bevel + * Bevel. * * Bevels edges and vertices */ static BMOpDefine bmo_bevel_def = { "bevel", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */ - {BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */ - {BMO_OP_SLOT_BOOL, "use_lengths"}, /* grab edge lengths from a PROP_FLT customdata layer */ - {BMO_OP_SLOT_BOOL, "use_even"}, /* corner vert placement: use shell/angle calculations */ - {BMO_OP_SLOT_BOOL, "use_dist"}, /* corner vert placement: evaluate percent as a distance, - * modifier uses this. We could do this as another float setting */ - {BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */ - {BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand beveled edge */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ + {"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ + {"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, +/* old bevel*/ +// {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ +// {"face_spans", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new geometry */ +// {"face_holes", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new geometry */ +// {"use_lengths", BMO_OP_SLOT_BOOL}, /* grab edge lengths from a PROP_FLT customdata layer */ +// {"use_even", BMO_OP_SLOT_BOOL}, /* corner vert placement: use shell/angle calculations */ +// {"use_dist", BMO_OP_SLOT_BOOL}, /* corner vert placement: evaluate percent as a distance, +// * modifier uses this. We could do this as another float setting */ +// {"lengthlayer", BMO_OP_SLOT_INT}, /* which PROP_FLT layer to us */ +// {"percent", BMO_OP_SLOT_FLT}, /* percentage to expand beveled edge */ +// {{'\0'}}, +// }, + bmo_bevel_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Beautify Fill + * Beautify Fill. * - * Makes triangle a bit nicer + * Rotate edges to create more evenly spaced triangles. */ static BMOpDefine bmo_beautify_fill_def = { "beautify_fill", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "constrain_edges"}, /* edges that can't be flipped */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new flipped faces and edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"constrain_edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can't be flipped */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */ + {{'\0'}}, + }, bmo_beautify_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Triangle Fill + * Triangle Fill. * * Fill edges with triangles */ static BMOpDefine bmo_triangle_fill_def = { "triangle_fill", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new faces and edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */ + {{'\0'}}, + }, bmo_triangle_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Solidify + * Solidify. * * Turns a mesh into a shell with thickness */ static BMOpDefine bmo_solidify_def = { "solidify", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {0}}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"thickness", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, bmo_solidify_face_region_exec, 0 }; /* - * Face Inset + * Face Inset. * - * Extrudes faces individually. + * Inset or outset faces. */ static BMOpDefine bmo_inset_def = { "inset", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_BOOL, "use_boundary"}, - {BMO_OP_SLOT_BOOL, "use_even_offset"}, - {BMO_OP_SLOT_BOOL, "use_relative_offset"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_FLT, "depth"}, - {BMO_OP_SLOT_BOOL, "use_outset"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_boundary", BMO_OP_SLOT_BOOL}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"thickness", BMO_OP_SLOT_FLT}, + {"depth", BMO_OP_SLOT_FLT}, + {"use_outset", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, bmo_inset_exec, 0 }; /* - * Wire Frame + * Wire Frame. * - * Makes a wire copy of faces. + * Makes a wire-frame copy of faces. */ static BMOpDefine bmo_wireframe_def = { "wireframe", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_BOOL, "use_boundary"}, - {BMO_OP_SLOT_BOOL, "use_even_offset"}, - {BMO_OP_SLOT_BOOL, "use_crease"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_BOOL, "use_relative_offset"}, - {BMO_OP_SLOT_FLT, "depth"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_boundary", BMO_OP_SLOT_BOOL}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_crease", BMO_OP_SLOT_BOOL}, + {"thickness", BMO_OP_SLOT_FLT}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"depth", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, bmo_wireframe_exec, 0 }; /* - * Vertex Slide + * Vertex Slide. * - * Translates vertes along an edge + * Translates verts along an edge */ static BMOpDefine bmo_slide_vert_def = { "slide_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "vert"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edge"}, - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, - {BMO_OP_SLOT_FLT, "distance_t"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"vert", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"factor", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, + }, bmo_slide_vert_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -1194,7 +1565,7 @@ static BMOpDefine bmo_slide_vert_def = { * If 'use_existing_faces' is true, the hull will not output triangles * that are covered by a pre-existing face. * - * All hull vertices, faces, and edges are added to 'geomout'. Any + * All hull vertices, faces, and edges are added to 'geom.out'. Any * input elements that end up inside the hull (i.e. are not used by an * output face) are added to the 'interior_geom' slot. The * 'unused_geom' slot will contain all interior geometry that is @@ -1203,44 +1574,49 @@ static BMOpDefine bmo_slide_vert_def = { */ static BMOpDefine bmo_convex_hull_def = { "convex_hull", - {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, - {BMO_OP_SLOT_BOOL, "use_existing_faces"}, - - /* Outputs */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "interior_geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "unused_geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "holes_geom"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"use_existing_faces", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, bmo_convex_hull_exec, 0 }; #endif /* - * Symmetrize + * Symmetrize. * - * Mekes the mesh elements in the "input" slot symmetrical. Unlike + * Makes the mesh elements in the "input" slot symmetrical. Unlike * normal mirroring, it only copies in one direction, as specified by * the "direction" slot. The edges and faces that cross the plane of * symmetry are split as needed to enforce symmetry. * - * All new vertices, edges, and faces are added to the "geomout" slot. + * All new vertices, edges, and faces are added to the "geom.out" slot. */ static BMOpDefine bmo_symmetrize_def = { "symmetrize", - {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, - {BMO_OP_SLOT_INT, "direction"}, - - /* Outputs */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"direction", BMO_OP_SLOT_INT}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, bmo_symmetrize_exec, 0 }; -BMOpDefine *opdefines[] = { +const BMOpDefine *bmo_opdefines[] = { &bmo_automerge_def, &bmo_average_vert_facedata_def, &bmo_beautify_fill_def, @@ -1315,7 +1691,6 @@ BMOpDefine *opdefines[] = { &bmo_unsubdivide_def, &bmo_weld_verts_def, &bmo_wireframe_def, - }; -int bmesh_total_ops = (sizeof(opdefines) / sizeof(void *)); +const int bmo_opdefines_total = (sizeof(bmo_opdefines) / sizeof(void *)); diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 671cfbbc55e..7df9c94a2f1 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -91,15 +91,15 @@ BLI_INLINE void _bmo_elem_flag_toggle( BMesh *bm, BMFlagLayer *oflags, const /* slot type arrays are terminated by the last member * having a slot type of 0 */ -enum { - BMO_OP_SLOT_SENTINEL = 0, +typedef enum eBMOpSlotType { + /* BMO_OP_SLOT_SENTINEL = 0, */ BMO_OP_SLOT_BOOL = 1, BMO_OP_SLOT_INT = 2, BMO_OP_SLOT_FLT = 3, /* normally store pointers to object, scene, * _never_ store arrays corresponding to mesh elements with this */ - BMO_OP_SLOT_PTR = 4, + BMO_OP_SLOT_PTR = 4, /* requres subtype BMO_OP_SLOT_SUBTYPE_PTR_xxx */ BMO_OP_SLOT_MAT = 5, BMO_OP_SLOT_VEC = 8, @@ -108,38 +108,84 @@ enum { * * it's very important this remain a power of two */ BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */ - BMO_OP_SLOT_MAPPING = 10 /* simple hash map */ -}; + BMO_OP_SLOT_MAPPING = 10 /* simple hash map, requres subtype BMO_OP_SLOT_SUBTYPE_MAP_xxx */ +} eBMOpSlotType; #define BMO_OP_SLOT_TOTAL_TYPES 11 +/* don't overlap values to avoid confusion */ +typedef enum eBMOpSlotSubType_Elem { + /* use as flags */ + BMO_OP_SLOT_SUBTYPE_ELEM_VERT = BM_VERT, + BMO_OP_SLOT_SUBTYPE_ELEM_EDGE = BM_EDGE, + BMO_OP_SLOT_SUBTYPE_ELEM_FACE = BM_FACE, + BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE = (BM_FACE << 1), +} eBMOpSlotSubType_Elem; +typedef enum eBMOpSlotSubType_Map { + BMO_OP_SLOT_SUBTYPE_MAP_EMPTY = 64, /* use as a set(), unused value */ + BMO_OP_SLOT_SUBTYPE_MAP_ELEM = 65, + BMO_OP_SLOT_SUBTYPE_MAP_FLT = 66, + BMO_OP_SLOT_SUBTYPE_MAP_INT = 67, + BMO_OP_SLOT_SUBTYPE_MAP_BOOL = 68, + BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL = 69, /* python can't convert these */ +} eBMOpSlotSubType_Map; +typedef enum eBMOpSlotSubType_Ptr { + BMO_OP_SLOT_SUBTYPE_PTR_BMESH = 100, + BMO_OP_SLOT_SUBTYPE_PTR_SCENE = 101, + BMO_OP_SLOT_SUBTYPE_PTR_OBJECT = 102, + BMO_OP_SLOT_SUBTYPE_PTR_MESH = 103, +} eBMOpSlotSubType_Ptr; + +typedef union eBMOpSlotSubType_Union { + eBMOpSlotSubType_Elem elem; + eBMOpSlotSubType_Ptr ptr; + eBMOpSlotSubType_Map map; +} eBMOpSlotSubType_Union; + /* please ignore all these structures, don't touch them in tool code, except * for when your defining an operator with BMOpDefine.*/ typedef struct BMOpSlot { - int slot_type; + const char *slot_name; /* pointer to BMOpDefine.slot_args */ + eBMOpSlotType slot_type; + eBMOpSlotSubType_Union slot_subtype; + int len; - int flag; - int index; /* index within slot array */ +// int flag; /* UNUSED */ +// int index; /* index within slot array */ /* UNUSED */ union { int i; float f; void *p; float vec[3]; - void *buf; + void **buf; GHash *ghash; } data; } BMOpSlot; -#define BMO_OP_MAX_SLOTS 16 /* way more than probably needed */ +/* mainly for use outside bmesh internal code */ +#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i) +#define BMO_SLOT_AS_INT(slot) ((slot)->data.i) +#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f) +#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec) +#define BMO_SLOT_AS_MATRIX(slot ) ((float (*)[4])((slot)->data.p)) +#define BMO_SLOT_AS_BUFFER(slot ) ((slot)->data.buf) +#define BMO_SLOT_AS_GHASH(slot ) ((slot)->data.ghash) + +#define BMO_ASSERT_SLOT_IN_OP(slot, op) \ + BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \ + ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS]))) + +/* way more than probably needed, compiler complains if limit hit */ +#define BMO_OP_MAX_SLOTS 16 typedef struct BMOperator { - int type; - int slot_type; - int type_flag; - int flag; /* runtime options */ - struct BMOpSlot slot_args[BMO_OP_MAX_SLOTS]; + struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]; + struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]; void (*exec)(BMesh *bm, struct BMOperator *op); struct MemArena *arena; + int type; + int type_flag; + int flag; /* runtime options */ } BMOperator; enum { @@ -151,13 +197,15 @@ enum { #define MAX_SLOTNAME 32 typedef struct BMOSlotType { - int type; char name[MAX_SLOTNAME]; + eBMOpSlotType type; + eBMOpSlotSubType_Union subtype; } BMOSlotType; typedef struct BMOpDefine { - const char *name; - BMOSlotType slot_types[BMO_OP_MAX_SLOTS]; + const char *opname; + BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS]; + BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS]; void (*exec)(BMesh *bm, BMOperator *op); int type_flag; } BMOpDefine; @@ -192,43 +240,6 @@ int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag); int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag); /*---------formatted operator initialization/execution-----------*/ -/* - * this system is used to execute or initialize an operator, - * using a formatted-string system. - * - * for example, BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES); - * . . .will execute the delete operator, feeding in selected faces, deleting them. - * - * the basic format for the format string is: - * [operatorname] [slot_name]=%[code] [slot_name]=%[code] - * - * as in printf, you pass in one additional argument to the function - * for every code. - * - * the formatting codes are: - * %d - put int in slot - * %f - put float in slot - * %p - put pointer in slot - * %h[f/e/v] - put elements with a header flag in slot. - * the letters after %h define which element types to use, - * so e.g. %hf will do faces, %hfe will do faces and edges, - * %hv will do verts, etc. must pass in at least one - * element type letter. - * %H[f/e/v] - same as %h, but tests if the flag is disabled - * %f[f/e/v] - same as %h, except it deals with tool flags instead of - * header flags. - * %F[f/e/v] - same as %f, but tests if the flag is disabled - * %a[f/e/v] - pass all elements (of types specified by f/e/v) to the - * slot. - * %e - pass in a single element. - * %v - pointer to a float vector of length 3. - * %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the - * corresponding argument must be a pointer to - * a float matrix. - * %s - copy a slot from another op, instead of mapping to one - * argument, it maps to two, a pointer to an operator and - * a slot name. - */ void BMO_push(BMesh *bm, BMOperator *op); void BMO_pop(BMesh *bm); @@ -245,15 +256,22 @@ int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ... int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist); /* test whether a named slot exists */ -int BMO_slot_exists(BMOperator *op, const char *slot_name); +int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); /* get a pointer to a slot. this may be removed layer on from the public API. */ -BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name); +BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); /* copies the data of a slot from one operator to another. src and dst are the * source/destination slot codes, respectively. */ -void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, - const char *src, const char *dst); +#define BMO_slot_copy(op_src, slots_src, slot_name_src, \ + op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_copy((op_src)->slots_src, slot_name_src, \ + (op_dst)->slots_dst, slot_name_dst, \ + (op_dst)->arena) + +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst); /* del "context" slot values, used for operator too */ enum { @@ -279,13 +297,13 @@ typedef enum { void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag); -void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f); -float BMO_slot_float_get(BMOperator *op, const char *slot_name); -void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i); -int BMO_slot_int_get(BMOperator *op, const char *slot_name); -void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i); -int BMO_slot_bool_get(BMOperator *op, const char *slot_name); -void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f); +float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); +int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len); /* don't pass in arrays that are supposed to map to elements this way. @@ -293,69 +311,85 @@ void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); * so, e.g. passing in list of floats per element in another slot is bad. * passing in, e.g. pointer to an editmesh for the conversion operator is fine * though. */ -void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p); -void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name); -void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]); -void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]); +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p); +void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]); +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]); /* only supports square mats */ /* size must be 3 or 4; this api is meant only for transformation matrices. * note that internally the matrix is stored in 4x4 form, and it's safe to * call whichever BMO_Get_MatXXX function you want. */ -void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size); -void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]); -void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]); +void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size); +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]); +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]); void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); /* copies the values from another slot to the end of the output slot */ -void BMO_slot_buffer_append(BMOperator *output_op, const char *output_op_slot, - BMOperator *other_op, const char *other_op_slot); +#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ + op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \ + (op_dst)->slots_dst, slot_name_dst, \ + (op_dst)->arena) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst); /* puts every element of type 'type' (which is a bitmask) with tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* puts every element of type 'type' (which is a bitmask) without tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush); /* puts every element of type 'type' (which is a bitmask) with header * flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, - const char *slot_name, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); /* puts every element of type 'type' (which is a bitmask) without * header flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, - const char *slot_name, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); -/* counts number of elements inside a slot array. */ -int BMO_slot_buffer_count(BMesh *bm, BMOperator *op, const char *slot_name); -int BMO_slot_map_count(BMesh *bm, BMOperator *op, const char *slot_name); +void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele); +void *BMO_slot_buffer_get_single(BMOpSlot *slot); -void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element, void *data, int len); + +/* counts number of elements inside a slot array. */ +int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); + +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, + const void *element, const void *data, const int len); /* Counts the number of edges with tool flag toolflag around */ @@ -363,23 +397,27 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag); /* flags all elements in a mapping. note that the mapping must only have * bmesh elements in it.*/ -void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, - const char hflag, const short oflag); +void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char hflag, const short oflag); -void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len); +void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const int len); -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, - const char htype); +void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype); -/* this part of the API is used to iterate over element buffer or +/** + * This part of the API is used to iterate over element buffer or * mapping slots. * * for example, iterating over the faces in a slot is: * + * \code{.c} + * * BMOIter oiter; * BMFace *f; * - * f = BMO_iter_new(&oiter, bm, some_operator, "slot_name", BM_FACE); + * f = BMO_iter_new(&oiter, some_operator, "slot_name", BM_FACE); * for (; f; f = BMO_iter_step(&oiter)) { * /do something with the face * } @@ -400,6 +438,7 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, * // *((void**)BMO_iter_map_value(&oiter)); * //or something like that. * } + * \endcode */ /* contents of this structure are private, @@ -412,10 +451,11 @@ typedef struct BMOIter { char restrictmask; /* bitwise '&' with BMHeader.htype */ } BMOIter; -void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name); +void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void *BMO_iter_new(BMOIter *iter, BMesh *bm, BMOperator *op, - const char *slot_name, const char restrictmask); +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask); void *BMO_iter_step(BMOIter *iter); /* returns a pointer to the key value when iterating over mappings. @@ -428,8 +468,8 @@ void *BMO_iter_map_value_p(BMOIter *iter); /* use this for float mappings */ float BMO_iter_map_value_f(BMOIter *iter); -#define BMO_ITER(ele, iter, bm, op, slot_name, restrict) \ - for (ele = BMO_iter_new(iter, bm, op, slot_name, restrict); ele; ele = BMO_iter_step(iter)) +#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \ + for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter)) /******************* Inlined Functions********************/ typedef void (*opexec)(BMesh *bm, BMOperator *op); @@ -441,6 +481,9 @@ typedef struct BMOElemMapping { int len; } BMOElemMapping; +/* pointer after BMOElemMapping */ +#define BMO_OP_SLOT_MAPPING_DATA(var) (void *)(((BMOElemMapping *)var) + 1) + extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]; #ifdef __cplusplus diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 16c2b8b0505..ad116011421 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -69,16 +69,26 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor oflags[bm->stackdepth - 1].f ^= oflag; } -BLI_INLINE void BMO_slot_map_int_insert(BMesh *bm, BMOperator *op, const char *slot_name, - void *element, int val) +BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, + void *element, const int val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(int)); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); } -BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char *slot_name, - void *element, float val) +BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, + void *element, const int val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(float)); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + BLI_assert(val == FALSE || val == TRUE); + BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); +} + +BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, + void *element, const float val) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + BMO_slot_map_insert(op, slot, element, &val, sizeof(float)); } @@ -87,62 +97,107 @@ BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char * do NOT use these for non-operator-api-allocated memory! instead * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */ -BLI_INLINE void BMO_slot_map_ptr_insert(BMesh *bm, BMOperator *op, const char *slot_name, - void *element, void *val) +BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(void *)); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); + BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); } -BLI_INLINE int BMO_slot_map_contains(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, void *element) +BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *val) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); + BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); +} + + +/* no values */ +BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, + const void *element) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY); + BMO_slot_map_insert(op, slot, element, NULL, 0); +} + +BLI_INLINE int BMO_slot_map_contains(BMOpSlot *slot, const void *element) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ - if (!slot->data.ghash) return 0; + if (UNLIKELY(slot->data.ghash == NULL)) { + return 0; + } return BLI_ghash_haskey(slot->data.ghash, element); } -BLI_INLINE void *BMO_slot_map_data_get(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element) { BMOElemMapping *mapping; - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ - if (!slot->data.ghash) return NULL; + if (UNLIKELY(slot->data.ghash == NULL)) { + return NULL; + } mapping = (BMOElemMapping *)BLI_ghash_lookup(slot->data.ghash, element); - if (!mapping) return NULL; + if (!mapping) { + return NULL; + } return mapping + 1; } -BLI_INLINE float BMO_slot_map_float_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { - float *val = (float *) BMO_slot_map_data_get(bm, op, slot_name, element); + float *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + + val = (float *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0.0f; } -BLI_INLINE int BMO_slot_map_int_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { - int *val = (int *) BMO_slot_map_data_get(bm, op, slot_name, element); + int *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + + val = (int *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0; } -BLI_INLINE void *BMO_slot_map_ptr_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE int BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) { - void **val = (void **) BMO_slot_map_data_get(bm, op, slot_name, element); + int *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + + val = (int *) BMO_slot_map_data_get(slot, element); + BLI_assert(val == NULL || *val == FALSE || *val == TRUE); + if (val) return *val; + + return 0; +} + +BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) +{ + void **val = (void **) BMO_slot_map_data_get(slot, element); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); + if (val) return *val; + + return NULL; +} + +BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element) +{ + void **val = (void **) BMO_slot_map_data_get(slot, element); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); if (val) return *val; return NULL; diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 4cc946a3a40..5e51f5a5ada 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -45,8 +45,8 @@ static void bmo_flag_layer_alloc(BMesh *bm); static void bmo_flag_layer_free(BMesh *bm); static void bmo_flag_layer_clear(BMesh *bm); -static int bmo_name_to_slotcode(BMOpDefine *def, const char *name); -static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name); +static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); static int bmo_opname_to_opcode(const char *opname); static const char *bmo_error_messages[] = { @@ -80,7 +80,7 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = { }; /* Dummy slot so there is something to return when slot name lookup fails */ -static BMOpSlot BMOpEmptySlot = {0}; +// static BMOpSlot BMOpEmptySlot = {0}; void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag) { @@ -101,6 +101,8 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op)) { bm->stackdepth++; + BLI_assert(bm->totflags > 0); + /* add flag layer, if appropriate */ if (bm->stackdepth > 1) bmo_flag_layer_alloc(bm); @@ -123,6 +125,19 @@ void BMO_pop(BMesh *bm) bm->stackdepth--; } + +/* use for both slot_types_in and slot_types_out */ +static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot_args[i].slot_name = slot_types[i].name; + slot_args[i].slot_type = slot_types[i].type; + slot_args[i].slot_subtype = slot_types[i].subtype; + // slot_args[i].index = i; // UNUSED + } +} + /** * \brief BMESH OPSTACK INIT OP * @@ -130,7 +145,7 @@ void BMO_pop(BMesh *bm) */ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) { - int i, opcode = bmo_opname_to_opcode(opname); + int opcode = bmo_opname_to_opcode(opname); #ifdef DEBUG BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname); @@ -144,17 +159,15 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) memset(op, 0, sizeof(BMOperator)); op->type = opcode; - op->type_flag = opdefines[opcode]->type_flag; + op->type_flag = bmo_opdefines[opcode]->type_flag; op->flag = flag; /* initialize the operator slot types */ - for (i = 0; opdefines[opcode]->slot_types[i].type; i++) { - op->slot_args[i].slot_type = opdefines[opcode]->slot_types[i].type; - op->slot_args[i].index = i; - } + bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in); + bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out); /* callback */ - op->exec = opdefines[opcode]->exec; + op->exec = bmo_opdefines[opcode]->exec; /* memarena, used for operator's slot buffers */ op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); @@ -172,7 +185,9 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) */ void BMO_op_exec(BMesh *bm, BMOperator *op) { - + /* allocate tool flags on demand */ + BM_mesh_elem_toolflags_ensure(bm); + BMO_push(bm, op); if (bm->stackdepth == 2) @@ -185,6 +200,20 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) BMO_pop(bm); } +static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + BMOpSlot *slot; + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot = &slot_args[i]; + if (slot->slot_type == BMO_OP_SLOT_MAPPING) { + if (slot->data.ghash) { + BLI_ghash_free(slot->data.ghash, NULL, NULL); + } + } + } +} + /** * \brief BMESH OPSTACK FINISH OP * @@ -192,21 +221,13 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) */ void BMO_op_finish(BMesh *bm, BMOperator *op) { - BMOpSlot *slot; - int i; - - for (i = 0; opdefines[op->type]->slot_types[i].type; i++) { - slot = &op->slot_args[i]; - if (slot->slot_type == BMO_OP_SLOT_MAPPING) { - if (slot->data.ghash) - BLI_ghash_free(slot->data.ghash, NULL, NULL); - } - } + bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_in, op->slots_in); + bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_out, op->slots_out); BLI_memarena_free(op->arena); #ifdef DEBUG - BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->name); + BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname); #else (void)bm; #endif @@ -217,9 +238,9 @@ void BMO_op_finish(BMesh *bm, BMOperator *op) * * \return Success if the slot if found. */ -int BMO_slot_exists(BMOperator *op, const char *slot_name) +int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode(opdefines[op->type], slot_name); + int slot_code = bmo_name_to_slotcode(slot_args, identifier); return (slot_code >= 0); } @@ -228,73 +249,118 @@ int BMO_slot_exists(BMOperator *op, const char *slot_name) * * Returns a pointer to the slot of type 'slot_code' */ -BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name) +BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode_check(opdefines[op->type], slot_name); + int slot_code = bmo_name_to_slotcode_check(slot_args, identifier); - if (slot_code < 0) { - return &BMOpEmptySlot; + if (UNLIKELY(slot_code < 0)) { + //return &BMOpEmptySlot; + BLI_assert(0); + return NULL; /* better crash */ } - return &(op->slot_args[slot_code]); + return &slot_args[slot_code]; } /** * \brief BMESH OPSTACK COPY SLOT * + * define used. * Copies data from one slot to another. */ -void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst) +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst) { - BMOpSlot *source_slot = BMO_slot_get(source_op, src); - BMOpSlot *dest_slot = BMO_slot_get(dest_op, dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); - if (source_slot == dest_slot) + if (slot_src == slot_dst) return; - if (source_slot->slot_type != dest_slot->slot_type) { - /* possibly assert here? */ + BLI_assert(slot_src->slot_type == slot_dst->slot_type); + if (slot_src->slot_type != slot_dst->slot_type) { return; } - if (dest_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { /* do buffer copy */ - dest_slot->data.buf = NULL; - dest_slot->len = source_slot->len; - if (dest_slot->len) { - const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[dest_slot->slot_type] * dest_slot->len; - dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, slot_alloc_size); - memcpy(dest_slot->data.buf, source_slot->data.buf, slot_alloc_size); + slot_dst->data.buf = NULL; + slot_dst->len = slot_src->len; + if (slot_dst->len) { + /* check dest has all flags enabled that the source has */ + const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP); + const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP); + + if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) { + /* pass */ + } + else { + /* check types */ + const unsigned int tot = slot_src->len; + unsigned int i; + unsigned int out = 0; + BMElem **ele_src = (BMElem **)slot_src->data.buf; + for (i = 0; i < tot; i++, ele_src++) { + if ((*ele_src)->head.htype & dst_elem_flag) { + out++; + } + } + if (out != tot) { + slot_dst->len = out; + } + } + + if (slot_dst->len) { + const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len; + slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size); + if (slot_src->len == slot_dst->len) { + memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); + } + else { + /* only copy compatible elements */ + const unsigned int tot = slot_src->len; + unsigned int i; + BMElem **ele_src = (BMElem **)slot_src->data.buf; + BMElem **ele_dst = (BMElem **)slot_dst->data.buf; + for (i = 0; i < tot; i++, ele_src++) { + if ((*ele_src)->head.htype & dst_elem_flag) { + *ele_dst = *ele_src; + ele_dst++; + } + } + } + } } } - else if (dest_slot->slot_type == BMO_OP_SLOT_MAPPING) { + else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { GHashIterator it; BMOElemMapping *srcmap, *dstmap; /* sanity check */ - if (!source_slot->data.ghash) { + if (!slot_src->data.ghash) { return; } - if (!dest_slot->data.ghash) { - dest_slot->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); + if (!slot_dst->data.ghash) { + slot_dst->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); } - BLI_ghashIterator_init(&it, source_slot->data.ghash); - for ( ; (srcmap = BLI_ghashIterator_getValue(&it)); - BLI_ghashIterator_step(&it)) + for (BLI_ghashIterator_init(&it, slot_src->data.ghash); + (srcmap = BLI_ghashIterator_getValue(&it)); + BLI_ghashIterator_step(&it)) { - dstmap = BLI_memarena_alloc(dest_op->arena, sizeof(*dstmap) + srcmap->len); + dstmap = BLI_memarena_alloc(arena_dst, sizeof(*dstmap) + srcmap->len); dstmap->element = srcmap->element; dstmap->len = srcmap->len; - memcpy(dstmap + 1, srcmap + 1, srcmap->len); + memcpy(BMO_OP_SLOT_MAPPING_DATA(dstmap), BMO_OP_SLOT_MAPPING_DATA(srcmap), srcmap->len); - BLI_ghash_insert(dest_slot->data.ghash, dstmap->element, dstmap); + BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap); } } else { - dest_slot->data = source_slot->data; + slot_dst->data = slot_src->data; } } @@ -304,9 +370,9 @@ void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, * Sets the value of a slot depending on it's type */ -void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f) +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) return; @@ -314,9 +380,9 @@ void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f) slot->data.f = f; } -void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i) +void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) return; @@ -324,9 +390,9 @@ void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i) slot->data.i = i; } -void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i) +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) return; @@ -335,9 +401,9 @@ void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i) } /* only supports square mats */ -void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size) +void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; @@ -354,33 +420,43 @@ void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, i else { fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size); - memset(slot->data.p, 0, sizeof(float) * 4 * 4); + zero_m4(slot->data.p); } } -void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]) +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; - copy_m4_m4(r_mat, (float (*)[4])slot->data.p); + if (slot->data.p) { + copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); + } + else { + unit_m4(r_mat); + } } -void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]) +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; - copy_m3_m4(r_mat, slot->data.p); + if (slot->data.p) { + copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); + } + else { + unit_m3(r_mat); + } } -void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); if (!(slot->slot_type == BMO_OP_SLOT_PTR)) return; @@ -388,9 +464,9 @@ void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) slot->data.p = p; } -void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]) +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); if (!(slot->slot_type == BMO_OP_SLOT_VEC)) return; @@ -399,9 +475,9 @@ void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]) } -float BMO_slot_float_get(BMOperator *op, const char *slot_name) +float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) return 0.0f; @@ -409,9 +485,9 @@ float BMO_slot_float_get(BMOperator *op, const char *slot_name) return slot->data.f; } -int BMO_slot_int_get(BMOperator *op, const char *slot_name) +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) return 0; @@ -419,9 +495,9 @@ int BMO_slot_int_get(BMOperator *op, const char *slot_name) return slot->data.i; } -int BMO_slot_bool_get(BMOperator *op, const char *slot_name) +int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) return 0; @@ -430,23 +506,23 @@ int BMO_slot_bool_get(BMOperator *op, const char *slot_name) } /* if you want a copy of the elem buffer */ -void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len) +void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); void *ret; /* could add support for mapping type */ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - ret = MEM_mallocN(sizeof(void *) * slot->len, __func__); - memcpy(ret, slot->data.buf, sizeof(void *) * slot->len); + ret = MEM_mallocN(sizeof(void **) * slot->len, __func__); + memcpy(ret, slot->data.buf, sizeof(void **) * slot->len); *len = slot->len; return ret; } -void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) +void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); if (!(slot->slot_type == BMO_OP_SLOT_PTR)) return NULL; @@ -454,9 +530,9 @@ void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) return slot->data.p; } -void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]) +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); if (!(slot->slot_type == BMO_OP_SLOT_VEC)) return; @@ -532,9 +608,9 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty } } -int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) +int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); /* check if its actually a buffer */ @@ -544,9 +620,9 @@ int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_na return slot->len; } -int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) +int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* check if its actually a buffer */ @@ -559,24 +635,27 @@ int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) /* inserts a key/value mapping into a mapping slot. note that it copies the * value, it doesn't store a reference to it. */ -void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element, void *data, int len) +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, + const void *element, const void *data, const int len) { BMOElemMapping *mapping; - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); + BMO_ASSERT_SLOT_IN_OP(slot, op); mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len); mapping->element = (BMHeader *) element; mapping->len = len; - memcpy(mapping + 1, data, len); + memcpy(BMO_OP_SLOT_MAPPING_DATA(mapping), data, len); if (!slot->data.ghash) { slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); } + else { + BLI_assert(slot->data.ghash); + } - BLI_ghash_insert(slot->data.ghash, element, mapping); + BLI_ghash_insert(slot->data.ghash, (void *)element, mapping); } #if 0 @@ -596,7 +675,7 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) if (slot->len >= slot->size) { slot->size = (slot->size + 1 + totadd) * 2; - allocsize = BMO_OPSLOT_TYPEINFO[opdefines[op->type]->slot_types[slot_code].type] * slot->size; + allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->size; tmp = slot->data.buf; slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); @@ -611,7 +690,7 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) slot->len += totadd; slot->size = slot->len + 2; - allocsize = BMO_OPSLOT_TYPEINFO[opdefines[op->type]->slot_types[slot_code].type] * slot->len; + allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->len; tmp = slot->data.buf; slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); @@ -622,11 +701,11 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) } #endif -void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { GHashIterator it; - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElemF *ele_f; BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -642,18 +721,22 @@ void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, } } -void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len) +void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int len) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); /* check if its actually a buffer */ if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) return NULL; slot->len = len; - if (len) + if (len) { slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len); + } + else { + slot->data.buf = NULL; + } + return slot->data.buf; } @@ -662,9 +745,10 @@ void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len * * Copies all elements of a certain type into an operator slot. */ -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, const char htype) +void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype) { - BMOpSlot *output = BMO_slot_get(op, slot_name); + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; if (htype & BM_VERT) totelement += bm->totvert; @@ -675,27 +759,27 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, BMIter iter; BMHeader *ele; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); /* TODO - collapse these loops into one */ if (htype & BM_VERT) { BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } if (htype & BM_EDGE) { BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } if (htype & BM_FACE) { BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -708,11 +792,11 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, * Copies elements of a certain type, which have a certain header flag * enabled/disabled into a slot for an operator. */ -static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const short test_for_enabled) { - BMOpSlot *output = BMO_slot_get(op, slot_name); + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0; @@ -727,7 +811,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl BMIter iter; BMElem *ele; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); /* TODO - collapse these loops into one */ @@ -736,7 +820,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -747,7 +831,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -758,7 +842,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -769,46 +853,74 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl } } -void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag) { - bmo_slot_buffer_from_hflag(bm, op, slot_name, htype, hflag, TRUE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, TRUE); } -void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag) { - bmo_slot_buffer_from_hflag(bm, op, slot_name, htype, hflag, FALSE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, FALSE); +} + +void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele) +{ + BMO_ASSERT_SLOT_IN_OP(slot, op); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); + BLI_assert(slot->len == 0 || slot->len == 1); + + BLI_assert(slot->slot_subtype.elem & ele->htype); + + slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */ + slot->len = 1; + *slot->data.buf = ele; +} + +void *BMO_slot_buffer_get_single(BMOpSlot *slot) +{ + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); + BLI_assert(slot->len == 0 || slot->len == 1); + + return slot->len ? (BMHeader *)slot->data.buf[0] : NULL; } /** * Copies the values from another slot to the end of the output slot. */ -void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name, - BMOperator *other_op, const char *other_slot_name) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst) { - BMOpSlot *output_slot = BMO_slot_get(output_op, output_slot_name); - BMOpSlot *other_slot = BMO_slot_get(other_op, other_slot_name); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); - BLI_assert(output_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF && - other_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF && + slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - if (output_slot->len == 0) { + if (slot_dst->len == 0) { /* output slot is empty, copy rather than append */ - BMO_slot_copy(other_op, output_op, other_slot_name, output_slot_name); + _bmo_slot_copy(slot_args_src, slot_name_src, + slot_args_dst, slot_name_dst, + arena_dst); } - else if (other_slot->len != 0) { - int elem_size = BMO_OPSLOT_TYPEINFO[output_slot->slot_type]; - int alloc_size = elem_size * (output_slot->len + other_slot->len); + else if (slot_src->len != 0) { + int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type]; + int alloc_size = elem_size * (slot_dst->len + slot_src->len); /* allocate new buffer */ - void *buf = BLI_memarena_alloc(output_op->arena, alloc_size); + void *buf = BLI_memarena_alloc(arena_dst, alloc_size); /* copy slot data */ - memcpy(buf, output_slot->data.buf, elem_size * output_slot->len); - memcpy(((char *)buf) + elem_size * output_slot->len, other_slot->data.buf, elem_size * other_slot->len); + memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len); + memcpy(((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len); - output_slot->data.buf = buf; - output_slot->len += other_slot->len; + slot_dst->data.buf = buf; + slot_dst->len += slot_src->len; } } @@ -818,13 +930,15 @@ void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name, * Copies elements of a certain type, which have a certain flag set * into an output slot for an operator. */ -static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slot_name, +static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag, const short test_for_enabled) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); int totelement, i = 0; + BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args); BLI_assert(ELEM(TRUE, FALSE, test_for_enabled)); if (test_for_enabled) @@ -833,15 +947,16 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); if (totelement) { BMIter iter; BMHeader *ele; BMHeader **ele_array; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - ele_array = (BMHeader **)slot->data.p; + ele_array = (BMHeader **)slot->data.buf; /* TODO - collapse these loops into one */ @@ -877,16 +992,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo } } -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - bmo_slot_buffer_from_flag(bm, op, slot_name, htype, oflag, TRUE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, TRUE); } -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - bmo_slot_buffer_from_flag(bm, op, slot_name, htype, oflag, FALSE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, FALSE); } /** @@ -895,16 +1012,18 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *s * Header Flags elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMElem **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElem **data = (BMElem **)slot->data.buf; int i; const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++, data++) { if (!(htype & (*data)->head.htype)) @@ -928,16 +1047,18 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_na * Removes flags from elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMElem **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElem **data = (BMElem **)slot->data.buf; int i; const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++, data++) { if (!(htype & (*data)->head.htype)) @@ -979,14 +1100,16 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag) * * Flags elements in a slots buffer */ -void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMHeader **data = slot->data.p; int i; BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++) { if (!(htype & data[i]->htype)) @@ -1001,14 +1124,16 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_nam * * Removes flags from elements in a slots buffer */ -void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMHeader **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMHeader **data = (BMHeader **)slot->data.buf; int i; BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++) { if (!(htype & data[i]->htype)) @@ -1046,7 +1171,9 @@ static void bmo_flag_layer_alloc(BMesh *bm) /* store memcpy size for reuse */ const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer)); - + + BLI_assert(oldpool != NULL); + bm->totflags++; /* allocate new flag poo */ @@ -1058,18 +1185,21 @@ static void bmo_flag_layer_alloc(BMesh *bm) ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1095,7 +1225,7 @@ static void bmo_flag_layer_free(BMesh *bm) /* de-increment the totflags first.. */ bm->totflags--; /* allocate new flag poo */ - bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, BLI_MEMPOOL_SYSMALLOC); + bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, 0); /* now go through and memcpy all the flag */ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { @@ -1103,18 +1233,21 @@ static void bmo_flag_layer_free(BMesh *bm) ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1149,14 +1282,14 @@ static void bmo_flag_layer_clear(BMesh *bm) bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } -void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name) +void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) return NULL; - return slot->data.buf ? *(void **)slot->data.buf : NULL; + return slot->data.buf ? *slot->data.buf : NULL; } /** @@ -1165,10 +1298,11 @@ void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name) * \param restrictmask restricts the iteration to certain element types * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating * over an element buffer (not a mapping). */ -void *BMO_iter_new(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op, - const char *slot_name, const char restrictmask) +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); memset(iter, 0, sizeof(BMOIter)); @@ -1190,35 +1324,42 @@ void *BMO_iter_new(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op, void *BMO_iter_step(BMOIter *iter) { - if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { - BMHeader *h; + BMOpSlot *slot = iter->slot; + if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + BMHeader *ele; - if (iter->cur >= iter->slot->len) { + if (iter->cur >= slot->len) { return NULL; } - h = ((void **)iter->slot->data.buf)[iter->cur++]; - while (!(iter->restrictmask & h->htype)) { - if (iter->cur >= iter->slot->len) { + ele = slot->data.buf[iter->cur++]; + while (!(iter->restrictmask & ele->htype)) { + if (iter->cur >= slot->len) { return NULL; } - h = ((void **)iter->slot->data.buf)[iter->cur++]; + ele = slot->data.buf[iter->cur++]; + BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); } - return h; + BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); + + return ele; } - else if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) { + else if (slot->slot_type == BMO_OP_SLOT_MAPPING) { BMOElemMapping *map; void *ret = BLI_ghashIterator_getKey(&iter->giter); map = BLI_ghashIterator_getValue(&iter->giter); - iter->val = map + 1; + iter->val = BMO_OP_SLOT_MAPPING_DATA(map); BLI_ghashIterator_step(&iter->giter); return ret; } + else { + BLI_assert(0); + } return NULL; } @@ -1302,24 +1443,26 @@ int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op) #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0) -static int bmo_name_to_slotcode(BMOpDefine *def, const char *name) +static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i; + int i = 0; - for (i = 0; def->slot_types[i].type; i++) { - if (!strncmp(name, def->slot_types[i].name, MAX_SLOTNAME)) { + while (slot_args->slot_name) { + if (strncmp(identifier, slot_args->slot_name, MAX_SLOTNAME) == 0) { return i; } + slot_args++; + i++; } return -1; } -static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name) +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i = bmo_name_to_slotcode(def, name); + int i = bmo_name_to_slotcode(slot_args, identifier); if (i < 0) { - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name); + fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, identifier); } return i; @@ -1329,36 +1472,78 @@ static int bmo_opname_to_opcode(const char *opname) { int i; - for (i = 0; i < bmesh_total_ops; i++) { - if (!strcmp(opname, opdefines[i]->name)) { + for (i = 0; i < bmo_opdefines_total; i++) { + if (!strcmp(opname, bmo_opdefines[i]->opname)) { return i; } } - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); + fprintf(stderr, "%s: could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); return -1; } -/* Example: - * BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete %i %hv", DEL_ONLYFACES, BM_ELEM_SELECT); +/** + * \brief Format Strings for #BMOperator Initialization. * - * i - int - * b - boolean (same as int but 1/0 only) - * f - float - * hv - header flagged verts (hflag) - * he - header flagged edges (hflag) - * hf - header flagged faces (hflag) - * fv - flagged verts (oflag) - * fe - flagged edges (oflag) - * ff - flagged faces (oflag) + * This system is used to execute or initialize an operator, + * using a formatted-string system. * - * capitals - H, F to use the flag flipped (when the flag is off) - * Hv, He, Hf, Fv, Fe, Ff, + * The basic format for the format string is: + * `[operatorname] [slot_name]=%[code] [slot_name]=%[code]` + * + * Example: + * + * \code{.c} + * BMO_op_callf(bm, BMO_FLAG_DEFAULTS, + * "delete context=%i geom=%hv", + * DEL_ONLYFACES, BM_ELEM_SELECT); + * \endcode + * + * + * **Primitive Types** + * - `b` - boolean (same as int but 1/0 only). #BMO_OP_SLOT_BOOL + * - `i` - int. #BMO_OP_SLOT_INT + * - `f` - float. #BMO_OP_SLOT_FLT + * - `p` - pointer (normally to a Scene/Mesh/Object/BMesh). #BMO_OP_SLOT_PTR + * - `m3` - 3x3 matrix of floats. #BMO_OP_SLOT_MAT + * - `m4` - 4x4 matrix of floats. #BMO_OP_SLOT_MAT + * - `v` - 3D vector of floats. #BMO_OP_SLOT_VEC + * + * + * **Utility** + * + * Pass an existing slot which is copied to either an input or output slot. + * Taking the operator and slot-name pair of args. + * - `s` - slot_in (lower case) + * - `S` - slot_out (upper case) + * + * + * **Element Buffer** (#BMO_OP_SLOT_ELEMENT_BUF) + * - `e` - single element vert/edge/face (use with #BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE). + * - `av` - all verts + * - `ae` - all edges + * - `af` - all faces + * - `hv` - header flagged verts (hflag) + * - `he` - header flagged edges (hflag) + * - `hf` - header flagged faces (hflag) + * - `Hv` - header flagged verts (hflag off) + * - `He` - header flagged edges (hflag off) + * - `Hf` - header flagged faces (hflag off) + * - `fv` - flagged verts (oflag) + * - `fe` - flagged edges (oflag) + * - `ff` - flagged faces (oflag) + * - `Fv` - flagged verts (oflag off) + * - `Fe` - flagged edges (oflag off) + * - `Ff` - flagged faces (oflag off) + * + * \note The common v/e/f suffix can be mixed, + * so `avef` is can be used for all verts, edges and faces. + * Order is not important so `Hfev` is also valid (all unflagged verts, edges and faces). */ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist) { - BMOpDefine *def; +// BMOpDefine *def; char *opname, *ofmt, *fmt; char slot_name[64] = {0}; int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state; @@ -1397,7 +1582,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } BMO_op_init(bm, op, flag, opname); - def = opdefines[i]; +// def = bmo_opdefines[i]; i = 0; state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */ @@ -1420,7 +1605,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v fmt[i] = 0; - if (bmo_name_to_slotcode_check(def, fmt) < 0) { + if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) { GOTO_ERROR("name to slot code check failed"); } @@ -1446,47 +1631,55 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v else if (c == '4') size = 4; else GOTO_ERROR("matrix size was not 3 or 4"); - BMO_slot_mat_set(op, slot_name, va_arg(vlist, void *), size); + BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size); state = 1; break; } case 'v': { - BMO_slot_vec_set(op, slot_name, va_arg(vlist, float *)); + BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *)); state = 1; break; } - case 'e': + case 'e': /* single vert/edge/face */ { BMHeader *ele = va_arg(vlist, void *); - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); - slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); - slot->len = 1; - *((void **)slot->data.buf) = ele; + BMO_slot_buffer_from_single(op, slot, ele); state = 1; break; } case 's': + case 'S': { - BMOperator *op2 = va_arg(vlist, void *); - const char *slot_name2 = va_arg(vlist, char *); + BMOperator *op_other = va_arg(vlist, void *); + const char *slot_name_other = va_arg(vlist, char *); - BMO_slot_copy(op2, op, slot_name2, slot_name); + if (*fmt == 's') { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_in, slot_name_other, + op, slots_in, slot_name); + } + else { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_out, slot_name_other, + op, slots_in, slot_name); + } state = 1; break; } case 'i': - BMO_slot_int_set(op, slot_name, va_arg(vlist, int)); + BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int)); state = 1; break; case 'b': - BMO_slot_bool_set(op, slot_name, va_arg(vlist, int)); + BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int)); state = 1; break; case 'p': - BMO_slot_ptr_set(op, slot_name, va_arg(vlist, void *)); + BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *)); state = 1; break; case 'f': @@ -1497,7 +1690,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v type = *fmt; if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') { - BMO_slot_float_set(op, slot_name, va_arg(vlist, double)); + BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double)); } else { htype = 0; @@ -1519,19 +1712,19 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } if (type == 'h') { - BMO_slot_buffer_from_enabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'H') { - BMO_slot_buffer_from_disabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'a') { - BMO_slot_buffer_from_all(bm, op, slot_name, htype); + BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype); } else if (type == 'f') { - BMO_slot_buffer_from_enabled_flag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'F') { - BMO_slot_buffer_from_disabled_flag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_disabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } } diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 14da93302b9..d02b0dce728 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -83,34 +83,22 @@ enum { SIMVERT_EDGE }; -enum { - OPUVC_AXIS_X = 1, - OPUVC_AXIS_Y -}; - -enum { - DIRECTION_CW = 1, - DIRECTION_CCW -}; - /* vertex path selection values */ enum { VPATH_SELECT_EDGE_LENGTH = 0, VPATH_SELECT_TOPOLOGICAL }; -extern BMOpDefine *opdefines[]; -extern int bmesh_total_ops; +extern const BMOpDefine *bmo_opdefines[]; +extern const int bmo_opdefines_total; /*------specific operator helper functions-------*/ - -struct Object; - void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, float smooth, float fractal, float along_normal, int numcuts, int seltype, int cornertype, - const short use_singleedge, const short use_gridfill, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, int seed); #include "intern/bmesh_operator_api_inline.h" diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index 65c9cf0c421..9175af1c822 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -61,7 +61,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op); void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op); void bmo_duplicate_exec(BMesh *bm, BMOperator *op); void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op); -void bmo_edgenet_prepare(BMesh *bm, BMOperator *op); +void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op); void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op); void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op); void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 98edceb30a2..2e0471863d4 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -162,7 +162,7 @@ float BM_face_calc_area(BMFace *f) float area; int i; - BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) { copy_v3_v3(verts[i], l->v->co); @@ -677,6 +677,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa BMLoop *l_first; const float cos_threshold = 0.9f; + const float bias = 1.0f + 1e-6f; if (f->len == 4) { BMLoop *larr[4]; @@ -691,7 +692,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa /* pick 0/1 based on best lenth */ /* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */ i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) > - len_squared_v3v3(larr[1]->v->co, larr[3]->v->co))) != use_beauty); + len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty); i4 = (i + 3) % 4; /* Check produced tris aren’t too flat/narrow... * Probably not the best test, but is quite efficient and should at least avoid null-area faces! */ @@ -965,8 +966,8 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f; int i, j, a = 0, clen; - BLI_array_fixedstack_declare(projverts, BM_NGON_STACK_SIZE, f->len, "projvertsb"); - BLI_array_fixedstack_declare(edgeverts, BM_NGON_STACK_SIZE * 2, len * 2, "edgevertsb"); + BLI_array_fixedstack_declare(projverts, BM_DEFAULT_NGON_STACK_SIZE, f->len, "projvertsb"); + BLI_array_fixedstack_declare(edgeverts, BM_DEFAULT_NGON_STACK_SIZE * 2, len * 2, "edgevertsb"); i = 0; l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, f); diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index b3fe3676ab8..850e81ba3ac 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -56,15 +56,21 @@ int bmesh_elem_check(void *element, const char htype); int bmesh_radial_length(BMLoop *l); int bmesh_disk_count(BMVert *v); -/* NOTE: ensure different parts of the API do not conflict +/** + * Internal BMHeader.api_flag + * \note Ensure different parts of the API do not conflict * on using these internal flags!*/ -#define _FLAG_JF 1 /* join faces */ -#define _FLAG_MF 2 /* make face */ -#define _FLAG_MV 2 /* make face, vertex */ +enum { + _FLAG_JF = (1 << 0), /* join faces */ + _FLAG_MF = (1 << 1), /* make face */ + _FLAG_MV = (1 << 1), /* make face, vertex */ + _FLAG_OVERLAP = (1 << 2) /* general overlap flag */ +}; -#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->oflags[0].pflag |= (f)) -#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->oflags[0].pflag &= ~(f)) -#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->oflags[0].pflag & (f)) +#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->head.api_flag |= (f)) +#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->head.api_flag &= ~(f)) +#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f)) +#define BM_ELEM_API_FLAG_CLEAR(element) ((element)->head.api_flag = 0) void calc_poly_plane(float (*verts)[3], const int nverts); void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 4b07dd74eef..195c60c5a9c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -39,8 +39,6 @@ #include "bmesh.h" #include "intern/bmesh_private.h" -#define BM_OVERLAP (1 << 13) - /** * Returns whether or not a given vertex is * is part of a given edge. @@ -240,7 +238,7 @@ int BM_vert_in_face(BMFace *f, BMVert *v) * Compares the number of vertices in an array * that appear in a given face */ -int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) +int BM_verts_in_face(BMFace *f, BMVert **varr, int len) { BMLoop *l_iter, *l_first; @@ -251,7 +249,7 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) int i, count = 0; for (i = 0; i < len; i++) { - BMO_elem_flag_enable(bm, varr[i], BM_OVERLAP); + BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); } #ifdef USE_BMESH_HOLES @@ -266,14 +264,16 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) #endif do { - if (BMO_elem_flag_test(bm, l_iter->v, BM_OVERLAP)) { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { count++; } } while ((l_iter = l_iter->next) != l_first); } - for (i = 0; i < len; i++) BMO_elem_flag_disable(bm, varr[i], BM_OVERLAP); + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } return count; } @@ -401,6 +401,7 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) } else { BLI_assert(0); + return NULL; } if (BM_edge_is_manifold(e_next)) { @@ -723,6 +724,47 @@ int BM_edge_is_boundary(BMEdge *e) } #endif +/** + * Returns the number of faces that are adjacent to both f1 and f2, + * \note Could be sped up a bit by not using iterators and by tagging + * faces on either side, then count the tags rather then searching. + */ +int BM_face_share_face_count(BMFace *f1, BMFace *f2) +{ + BMIter iter1, iter2; + BMEdge *e; + BMFace *f; + int count = 0; + + BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { + if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) + count++; + } + } + + return count; +} + +/** + * same as #BM_face_share_face_count but returns a bool + */ +int BM_face_share_face_check(BMFace *f1, BMFace *f2) +{ + BMIter iter1, iter2; + BMEdge *e; + BMFace *f; + + BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { + if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) + return TRUE; + } + } + + return FALSE; +} + /** * Counts the number of edges two faces share (if any) */ @@ -742,10 +784,28 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2) return count; } +/** + * Returns TRUE if the faces share an edge + */ +int BM_face_share_edge_check(BMFace *f1, BMFace *f2) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f1); + do { + if (bmesh_radial_face_find(l_iter->e, f2)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + + return FALSE; +} + /** * Test if e1 shares any faces with e2 */ -int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2) +int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) { BMLoop *l; BMFace *f; @@ -763,10 +823,33 @@ int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2) return FALSE; } +/** + * Test if e1 shares any quad faces with e2 + */ +int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) +{ + BMLoop *l; + BMFace *f; + + if (e1->l && e2->l) { + l = e1->l; + do { + f = l->f; + if (f->len == 4) { + if (bmesh_radial_face_find(e2, f)) { + return TRUE; + } + } + l = l->radial_next; + } while (l != e1->l); + } + return FALSE; +} + /** * Tests to see if e1 shares a vertex with e2 */ -int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2) +int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) { return (e1->v1 == e2->v1 || e1->v1 == e2->v2 || @@ -1023,7 +1106,12 @@ float BM_vert_calc_shell_factor(BMVert *v) accum_angle += face_angle; } - return accum_shell / accum_angle; + if (accum_angle != 0.0f) { + return accum_shell / accum_angle; + } + else { + return 1.0f; + } } /** @@ -1044,7 +1132,12 @@ float BM_vert_calc_mean_tagged_edge_length(BMVert *v) } } - return length / (float)tot; + if (tot) { + return length / (float)tot; + } + else { + return 0.0f; + } } @@ -1147,7 +1240,7 @@ BMEdge *BM_edge_find_double(BMEdge *e) * \returns TRUE for overlap * */ -int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlapface) +int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_overlapface) { BMIter viter; BMFace *f; @@ -1155,7 +1248,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(bm, f, varr, len); + amount = BM_verts_in_face(f, varr, len); if (amount >= len) { if (r_overlapface) { *r_overlapface = f; @@ -1177,7 +1270,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap * there is a face with exactly those vertices * (and only those vertices). */ -int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface) +int BM_face_exists(BMVert **varr, int len, BMFace **r_existface) { BMIter viter; BMFace *f; @@ -1185,7 +1278,7 @@ int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface) for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(bm, f, varr, len); + amount = BM_verts_in_face(f, varr, len); if (amount == len && amount == f->len) { if (r_existface) { *r_existface = f; @@ -1323,7 +1416,7 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) int BM_face_exists_multi_edge(BMEdge **earr, int len) { BMVert **varr; - BLI_array_fixedstack_declare(varr, BM_NGON_STACK_SIZE, len, __func__); + BLI_array_fixedstack_declare(varr, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); int ok; int i, i_next; @@ -1349,3 +1442,38 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len) return ok; } + +/* convenience functions for checking flags */ +int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag) +{ + return (BM_elem_flag_test(e->v1, hflag) || + BM_elem_flag_test(e->v2, hflag)); +} + +int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} + +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->e, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 34d0747676c..7a18f69371e 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -28,7 +28,7 @@ */ int BM_vert_in_face(BMFace *f, BMVert *v); -int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len); +int BM_verts_in_face(BMFace *f, BMVert **varr, int len); int BM_edge_in_face(BMFace *f, BMEdge *e); int BM_edge_in_loop(BMEdge *e, BMLoop *l); @@ -77,16 +77,21 @@ BMLoop *BM_face_find_longest_loop(BMFace *f); BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2); BMEdge *BM_edge_find_double(BMEdge *e); -int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); +int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_existface); -int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); +int BM_face_exists(BMVert **varr, int len, BMFace **r_existface); int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len); int BM_face_exists_multi_edge(BMEdge **earr, int len); +int BM_face_share_face_count(BMFace *f1, BMFace *f2); int BM_face_share_edge_count(BMFace *f1, BMFace *f2); -int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2); -int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2); + +int BM_face_share_face_check(BMFace *f1, BMFace *f2); +int BM_face_share_edge_check(BMFace *f1, BMFace *f2); +int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2); +int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2); +int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2); BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2); BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v); @@ -96,4 +101,8 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2); void BM_edge_ordered_verts_ex(BMEdge *edge, BMVert **r_v1, BMVert **r_v2, BMLoop *edge_loop); +int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag); +int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag); +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); + #endif /* __BMESH_QUERIES_H__ */ diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index c5120571755..126d0f46119 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -15,7 +15,7 @@ * 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): Joseph Eagar. + * Contributor(s): * * ***** END GPL LICENSE BLOCK ***** */ @@ -24,865 +24,38 @@ * \ingroup bmesh */ -#include "MEM_guardedalloc.h" - -#include "BLI_array.h" -#include "BLI_math.h" -#include "BLI_smallhash.h" - -#include "BKE_customdata.h" +#include "BLI_utildefines.h" #include "bmesh.h" #include "intern/bmesh_operators_private.h" /* own include */ -#define BEVEL_FLAG 1 -#define BEVEL_DEL 2 -#define FACE_NEW 4 -#define EDGE_OLD 8 -#define FACE_OLD 16 -#define VERT_OLD 32 -#define FACE_SPAN 64 -#define FACE_HOLE 128 - -typedef struct LoopTag { - BMVert *newv; -} LoopTag; - -typedef struct EdgeTag { - BMVert *newv1, *newv2; -} EdgeTag; - -static void calc_corner_co(BMLoop *l, const float fac, float r_co[3], - const short do_dist, const short do_even) -{ - float no[3], l_vec_prev[3], l_vec_next[3], l_co_prev[3], l_co[3], l_co_next[3], co_ofs[3]; - int is_concave; - - /* first get the prev/next verts */ - if (l->f->len > 2) { - copy_v3_v3(l_co_prev, l->prev->v->co); - copy_v3_v3(l_co, l->v->co); - copy_v3_v3(l_co_next, l->next->v->co); - - /* calculate normal */ - sub_v3_v3v3(l_vec_prev, l_co_prev, l_co); - sub_v3_v3v3(l_vec_next, l_co_next, l_co); - - cross_v3_v3v3(no, l_vec_prev, l_vec_next); - is_concave = dot_v3v3(no, l->f->no) > 0.0f; - } - else { - BMIter iter; - BMLoop *l2; - float up[3] = {0.0f, 0.0f, 1.0f}; - - copy_v3_v3(l_co_prev, l->prev->v->co); - copy_v3_v3(l_co, l->v->co); - - BM_ITER_ELEM (l2, &iter, l->v, BM_LOOPS_OF_VERT) { - if (l2->f != l->f) { - copy_v3_v3(l_co_next, BM_edge_other_vert(l2->e, l2->next->v)->co); - break; - } - } - - sub_v3_v3v3(l_vec_prev, l_co_prev, l_co); - sub_v3_v3v3(l_vec_next, l_co_next, l_co); - - cross_v3_v3v3(no, l_vec_prev, l_vec_next); - if (dot_v3v3(no, no) == 0.0f) { - no[0] = no[1] = 0.0f; no[2] = -1.0f; - } - - is_concave = dot_v3v3(no, up) < 0.0f; - } - - - /* now calculate the new location */ - if (do_dist) { /* treat 'fac' as distance */ - - normalize_v3(l_vec_prev); - normalize_v3(l_vec_next); - - add_v3_v3v3(co_ofs, l_vec_prev, l_vec_next); - if (UNLIKELY(normalize_v3(co_ofs) == 0.0f)) { /* edges form a straight line */ - cross_v3_v3v3(co_ofs, l_vec_prev, l->f->no); - } - - if (do_even) { - negate_v3(l_vec_next); - mul_v3_fl(co_ofs, fac * shell_angle_to_dist(0.5f * angle_normalized_v3v3(l_vec_prev, l_vec_next))); - /* negate_v3(l_vec_next); */ /* no need unless we use again */ - } - else { - mul_v3_fl(co_ofs, fac); - } - } - else { /* treat as 'fac' as a factor (0 - 1) */ - - /* not strictly necessary, balance vectors - * so the longer edge doesn't skew the result, - * gives nicer, move even output. - * - * Use the minimum rather then the middle value so skinny faces don't flip along the short axis */ - float min_fac = min_ff(normalize_v3(l_vec_prev), normalize_v3(l_vec_next)); - float angle; - - if (do_even) { - negate_v3(l_vec_next); - angle = angle_normalized_v3v3(l_vec_prev, l_vec_next); - negate_v3(l_vec_next); /* no need unless we use again */ - } - else { - angle = 0.0f; - } - - mul_v3_fl(l_vec_prev, min_fac); - mul_v3_fl(l_vec_next, min_fac); - - add_v3_v3v3(co_ofs, l_vec_prev, l_vec_next); - - if (UNLIKELY(is_zero_v3(co_ofs))) { - cross_v3_v3v3(co_ofs, l_vec_prev, l->f->no); - normalize_v3(co_ofs); - mul_v3_fl(co_ofs, min_fac); - } - - /* done */ - if (do_even) { - mul_v3_fl(co_ofs, (fac * 0.5f) * shell_angle_to_dist(0.5f * angle)); - } - else { - mul_v3_fl(co_ofs, fac * 0.5f); - } - } - - /* apply delta vec */ - if (is_concave) - negate_v3(co_ofs); - - add_v3_v3v3(r_co, co_ofs, l->v->co); -} - - -#define ETAG_SET(e, v, nv) ( \ - (v) == (e)->v1 ? \ - (etags[BM_elem_index_get((e))].newv1 = (nv)) : \ - (etags[BM_elem_index_get((e))].newv2 = (nv)) \ - ) - -#define ETAG_GET(e, v) ( \ - (v) == (e)->v1 ? \ - (etags[BM_elem_index_get((e))].newv1) : \ - (etags[BM_elem_index_get((e))].newv2) \ - ) - void bmo_bevel_exec(BMesh *bm, BMOperator *op) { - BMOIter siter; - BMIter iter; - BMEdge *e; - BMVert *v; - BMFace **faces = NULL, *f; - LoopTag *tags = NULL, *tag; - EdgeTag *etags = NULL; - BMVert **verts = NULL; - BMEdge **edges = NULL; - BLI_array_declare(faces); - BLI_array_declare(tags); - BLI_array_declare(etags); - BLI_array_declare(verts); - BLI_array_declare(edges); - SmallHash hash; - float fac = BMO_slot_float_get(op, "percent"); - const short do_even = BMO_slot_bool_get(op, "use_even"); - const short do_dist = BMO_slot_bool_get(op, "use_dist"); - int i, li, has_elens, HasMDisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); - - has_elens = CustomData_has_layer(&bm->edata, CD_PROP_FLT) && BMO_slot_bool_get(op, "use_lengths"); - if (has_elens) { - li = BMO_slot_int_get(op, "lengthlayer"); + const float offset = BMO_slot_float_get(op->slots_in, "offset"); + const int seg = BMO_slot_int_get(op->slots_in, "segments"); + + if (offset > 0) { + BMOIter siter; + BMEdge *e; + BMVert *v; + + /* first flush 'geom' into flags, this makes it possible to check connected data, + * BM_FACE is cleared so we can put newly created faces into a bmesh slot. */ + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, FALSE); + + BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + } + + BMO_ITER (e, &siter, op->slots_in, "geom", BM_EDGE) { + if (BM_edge_is_manifold(e)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + } + + BM_mesh_bevel(bm, offset, seg); + + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } - - BLI_smallhash_init(&hash); - - BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) { - BMO_elem_flag_enable(bm, e, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v1, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v2, BEVEL_FLAG | BEVEL_DEL); - - if (BM_edge_face_count(e) < 2) { - BMO_elem_flag_disable(bm, e, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v1, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v2, BEVEL_DEL); - } -#if 0 - if (BM_edge_face_count(e) == 0) { - BMVert *verts[2] = {e->v1, e->v2}; - BMEdge *edges[2] = {e, BM_edge_create(bm, e->v1, e->v2, e, 0)}; - - BMO_elem_flag_enable(bm, edges[1], BEVEL_FLAG); - BM_face_create(bm, verts, edges, 2, FALSE); - } -#endif - } - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMO_elem_flag_enable(bm, v, VERT_OLD); - } - -#if 0 - /* a bit of cleaner code that, alas, doens't work. */ - /* build edge tag */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(bm, e->v1, BEVEL_FLAG) || BMO_elem_flag_test(bm, e->v2, BEVEL_FLAG)) { - BMIter liter; - BMLoop *l; - - if (!BMO_elem_flag_test(bm, e, EDGE_OLD)) { - BM_elem_index_set(e, BLI_array_count(etags)); /* set_dirty! */ - BLI_array_grow_one(etags); - - BMO_elem_flag_enable(bm, e, EDGE_OLD); - } - - BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - BMLoop *l2; - BMIter liter2; - - if (BMO_elem_flag_test(bm, l->f, BEVEL_FLAG)) - continue; - - BM_ITER_ELEM (l2, &liter2, l->f, BM_LOOPS_OF_FACE) { - BM_elem_index_set(l2, BLI_array_count(tags)); /* set_loop */ - BLI_array_grow_one(tags); - - if (!BMO_elem_flag_test(bm, l2->e, EDGE_OLD)) { - BM_elem_index_set(l2->e, BLI_array_count(etags)); /* set_dirty! */ - BLI_array_grow_one(etags); - - BMO_elem_flag_enable(bm, l2->e, EDGE_OLD); - } - } - - BMO_elem_flag_enable(bm, l->f, BEVEL_FLAG); - BLI_array_append(faces, l->f); - } - } - else { - BM_elem_index_set(e, -1); /* set_dirty! */ - } - } -#endif - - /* create and assign looptag structure */ - BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) { - BMLoop *l; - BMIter liter; - - BMO_elem_flag_enable(bm, e->v1, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v2, BEVEL_FLAG | BEVEL_DEL); - - if (BM_edge_face_count(e) < 2) { - BMO_elem_flag_disable(bm, e, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v1, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v2, BEVEL_DEL); - } - - if (!BLI_smallhash_haskey(&hash, (intptr_t)e)) { - BLI_array_grow_one(etags); - BM_elem_index_set(e, BLI_array_count(etags) - 1); /* set_dirty! */ - BLI_smallhash_insert(&hash, (intptr_t)e, NULL); - BMO_elem_flag_enable(bm, e, EDGE_OLD); - } - - /* find all faces surrounding e->v1 and, e->v2 */ - for (i = 0; i < 2; i++) { - BM_ITER_ELEM (l, &liter, i ? e->v2:e->v1, BM_LOOPS_OF_VERT) { - BMLoop *l2; - BMIter liter2; - - /* see if we've already processed this loop's fac */ - if (BLI_smallhash_haskey(&hash, (intptr_t)l->f)) - continue; - - /* create tags for all loops in l-> */ - BM_ITER_ELEM (l2, &liter2, l->f, BM_LOOPS_OF_FACE) { - BLI_array_grow_one(tags); - BM_elem_index_set(l2, BLI_array_count(tags) - 1); /* set_loop */ - - if (!BLI_smallhash_haskey(&hash, (intptr_t)l2->e)) { - BLI_array_grow_one(etags); - BM_elem_index_set(l2->e, BLI_array_count(etags) - 1); /* set_dirty! */ - BLI_smallhash_insert(&hash, (intptr_t)l2->e, NULL); - BMO_elem_flag_enable(bm, l2->e, EDGE_OLD); - } - } - - BLI_smallhash_insert(&hash, (intptr_t)l->f, NULL); - BMO_elem_flag_enable(bm, l->f, BEVEL_FLAG); - BLI_array_append(faces, l->f); - } - } - } - - bm->elem_index_dirty |= BM_EDGE; - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMIter eiter; - - if (!BMO_elem_flag_test(bm, v, BEVEL_FLAG)) - continue; - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BMO_elem_flag_test(bm, e, BEVEL_FLAG) && !ETAG_GET(e, v)) { - BMVert *v2; - float co[3]; - - v2 = BM_edge_other_vert(e, v); - sub_v3_v3v3(co, v2->co, v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, e->head.data, CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, v->co); - - v2 = BM_vert_create(bm, co, v); - ETAG_SET(e, v, v2); - } - } - } - - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - - BMO_elem_flag_enable(bm, faces[i], FACE_OLD); - - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - float co[3]; - - if (BMO_elem_flag_test(bm, l->e, BEVEL_FLAG)) { - if (BMO_elem_flag_test(bm, l->prev->e, BEVEL_FLAG)) { - tag = tags + BM_elem_index_get(l); - calc_corner_co(l, fac, co, do_dist, do_even); - tag->newv = BM_vert_create(bm, co, l->v); - } - else { - tag = tags + BM_elem_index_get(l); - tag->newv = ETAG_GET(l->prev->e, l->v); - - if (!tag->newv) { - sub_v3_v3v3(co, l->prev->v->co, l->v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, - CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, l->v->co); - - tag->newv = BM_vert_create(bm, co, l->v); - - ETAG_SET(l->prev->e, l->v, tag->newv); - } - } - } - else if (BMO_elem_flag_test(bm, l->v, BEVEL_FLAG)) { - tag = tags + BM_elem_index_get(l); - tag->newv = ETAG_GET(l->e, l->v); - - if (!tag->newv) { - sub_v3_v3v3(co, l->next->v->co, l->v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, l->e->head.data, CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, l->v->co); - - tag = tags + BM_elem_index_get(l); - tag->newv = BM_vert_create(bm, co, l->v); - - ETAG_SET(l->e, l->v, tag->newv); - } - } - else { - tag = tags + BM_elem_index_get(l); - tag->newv = l->v; - BMO_elem_flag_disable(bm, l->v, BEVEL_DEL); - } - } - } - - /* create new faces inset from original face */ - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - BMFace *f; - BMVert *lastv = NULL, *firstv = NULL; - - BMO_elem_flag_enable(bm, faces[i], BEVEL_DEL); - - BLI_array_empty(verts); - BLI_array_empty(edges); - - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - BMVert *v2; - - tag = tags + BM_elem_index_get(l); - BLI_array_append(verts, tag->newv); - - if (!firstv) - firstv = tag->newv; - - if (lastv) { - e = BM_edge_create(bm, lastv, tag->newv, l->e, TRUE); - BM_elem_attrs_copy(bm, bm, l->prev->e, e); - BLI_array_append(edges, e); - } - lastv = tag->newv; - - v2 = ETAG_GET(l->e, l->next->v); - - tag = &tags[BM_elem_index_get(l->next)]; - if (!BMO_elem_flag_test(bm, l->e, BEVEL_FLAG) && v2 && v2 != tag->newv) { - BLI_array_append(verts, v2); - - e = BM_edge_create(bm, lastv, v2, l->e, TRUE); - BM_elem_attrs_copy(bm, bm, l->e, e); - - BLI_array_append(edges, e); - lastv = v2; - } - } - - e = BM_edge_create(bm, firstv, lastv, BM_FACE_FIRST_LOOP(faces[i])->e, TRUE); - if (BM_FACE_FIRST_LOOP(faces[i])->prev->e != e) { - BM_elem_attrs_copy(bm, bm, BM_FACE_FIRST_LOOP(faces[i])->prev->e, e); - } - BLI_array_append(edges, e); - - f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), FALSE); - if (UNLIKELY(f == NULL)) { - printf("%s: could not make face!\n", __func__); - continue; - } - - BMO_elem_flag_enable(bm, f, FACE_NEW); - } - - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - int j; - - /* create quad spans between split edge */ - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - BMVert *v1 = NULL, *v2 = NULL, *v3 = NULL, *v4 = NULL; - - if (!BMO_elem_flag_test(bm, l->e, BEVEL_FLAG)) - continue; - - v1 = tags[BM_elem_index_get(l)].newv; - v2 = tags[BM_elem_index_get(l->next)].newv; - if (l->radial_next != l) { - v3 = tags[BM_elem_index_get(l->radial_next)].newv; - if (l->radial_next->next->v == l->next->v) { - v4 = v3; - v3 = tags[BM_elem_index_get(l->radial_next->next)].newv; - } - else { - v4 = tags[BM_elem_index_get(l->radial_next->next)].newv; - } - } - else { - /* the loop is on a boundar */ - v3 = l->next->v; - v4 = l->v; - - for (j = 0; j < 2; j++) { - BMIter eiter; - BMVert *v = j ? v4 : v3; - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_vert_in_edge(e, v3) || !BM_vert_in_edge(e, v4)) - continue; - - if (!BMO_elem_flag_test(bm, e, BEVEL_FLAG) && BMO_elem_flag_test(bm, e, EDGE_OLD)) { - BMVert *vv; - - vv = ETAG_GET(e, v); - if (!vv || BMO_elem_flag_test(bm, vv, BEVEL_FLAG)) - continue; - - if (j) { - v1 = vv; - } - else { - v2 = vv; - } - break; - } - } - } - - BMO_elem_flag_disable(bm, v3, BEVEL_DEL); - BMO_elem_flag_disable(bm, v4, BEVEL_DEL); - } - - if (v1 != v2 && v2 != v3 && v3 != v4) { - BMIter liter2; - BMLoop *l2, *l3; - BMEdge *e1, *e2; - float d1, d2, *d3; - - f = BM_face_create_quad_tri(bm, v4, v3, v2, v1, l->f, TRUE); - - e1 = BM_edge_exists(v4, v3); - e2 = BM_edge_exists(v2, v1); - BM_elem_attrs_copy(bm, bm, l->e, e1); - BM_elem_attrs_copy(bm, bm, l->e, e2); - - /* set edge lengths of cross edges as the average of the cross edges they're based o */ - if (has_elens) { - /* angle happens not to be used. why? - not sure it just isn't - campbell. - * leave this in in case we need to use it later */ -#if 0 - float ang; -#endif - e1 = BM_edge_exists(v1, v4); - e2 = BM_edge_exists(v2, v3); - - if (l->radial_next->v == l->v) { - l2 = l->radial_next->prev; - l3 = l->radial_next->next; - } - else { - l2 = l->radial_next->next; - l3 = l->radial_next->prev; - } - - d3 = CustomData_bmesh_get_n(&bm->edata, e1->head.data, CD_PROP_FLT, li); - d1 = *(float *)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, CD_PROP_FLT, li); - d2 = *(float *)CustomData_bmesh_get_n(&bm->edata, l2->e->head.data, CD_PROP_FLT, li); -#if 0 - ang = angle_v3v3v3(l->prev->v->co, l->v->co, BM_edge_other_vert(l2->e, l->v)->co); -#endif - *d3 = (d1 + d2) * 0.5f; - - d3 = CustomData_bmesh_get_n(&bm->edata, e2->head.data, CD_PROP_FLT, li); - d1 = *(float *)CustomData_bmesh_get_n(&bm->edata, l->next->e->head.data, CD_PROP_FLT, li); - d2 = *(float *)CustomData_bmesh_get_n(&bm->edata, l3->e->head.data, CD_PROP_FLT, li); -#if 0 - ang = angle_v3v3v3(BM_edge_other_vert(l->next->e, l->next->v)->co, l->next->v->co, - BM_edge_other_vert(l3->e, l->next->v)->co); -#endif - *d3 = (d1 + d2) * 0.5f; - } - - if (UNLIKELY(f == NULL)) { - fprintf(stderr, "%s: face index out of range! (bmesh internal error)\n", __func__); - continue; - } - - BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_SPAN); - - /* un-tag edges in f for deletio */ - BM_ITER_ELEM (l2, &liter2, f, BM_LOOPS_OF_FACE) { - BMO_elem_flag_disable(bm, l2->e, BEVEL_DEL); - } - } - else { - f = NULL; - } - } - } - - /* fill in holes at vertices */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMIter eiter; - BMVert *vv, *vstart = NULL, *lastv = NULL; - SmallHash tmphash; - int rad, insorig = 0, err = 0; - - BLI_smallhash_init(&tmphash); - - if (!BMO_elem_flag_test(bm, v, BEVEL_FLAG)) - continue; - - BLI_array_empty(verts); - BLI_array_empty(edges); - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - BMIter liter; - BMVert *v1 = NULL, *v2 = NULL; - BMLoop *l; - - if (BM_edge_face_count(e) < 2) - insorig = 1; - - if (BM_elem_index_get(e) == -1) - continue; - - rad = 0; - BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - if (!BMO_elem_flag_test(bm, l->f, FACE_OLD)) - continue; - - rad++; - - tag = tags + BM_elem_index_get((l->v == v) ? l : l->next); - - if (!v1) - v1 = tag->newv; - else if (!v2) - v2 = tag->newv; - } - - if (rad < 2) - insorig = 1; - - if (!v1) - v1 = ETAG_GET(e, v); - if (!v2 || v1 == v2) - v2 = ETAG_GET(e, v); - - if (v1) { - if (!BLI_smallhash_haskey(&tmphash, (intptr_t)v1)) { - BLI_array_append(verts, v1); - BLI_smallhash_insert(&tmphash, (intptr_t)v1, NULL); - } - - if (v2 && v1 != v2 && !BLI_smallhash_haskey(&tmphash, (intptr_t)v2)) { - BLI_array_append(verts, v2); - BLI_smallhash_insert(&tmphash, (intptr_t)v2, NULL); - } - } - } - - if (!BLI_array_count(verts)) - continue; - - if (insorig) { - BLI_array_append(verts, v); - BLI_smallhash_insert(&tmphash, (intptr_t)v, NULL); - } - - /* find edges that exist between vertices in verts. this is basically - * a topological walk of the edges connecting them */ - vstart = vstart ? vstart : verts[0]; - vv = vstart; - do { - BM_ITER_ELEM (e, &eiter, vv, BM_EDGES_OF_VERT) { - BMVert *vv2 = BM_edge_other_vert(e, vv); - - if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) { - /* if we've go over the same vert twice, break out of outer loop */ - if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) { - e = NULL; - err = 1; - break; - } - - /* use self pointer as ta */ - BLI_smallhash_remove(&tmphash, (intptr_t)vv2); - BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2); - - lastv = vv; - BLI_array_append(edges, e); - vv = vv2; - break; - } - } - - if (e == NULL) { - break; - } - } while (vv != vstart); - - if (err) { - continue; - } - - /* there may not be a complete loop of edges, so start again and make - * final edge afterwards. in this case, the previous loop worked to - * find one of the two edges at the extremes. */ - if (vv != vstart) { - /* undo previous taggin */ - for (i = 0; i < BLI_array_count(verts); i++) { - BLI_smallhash_remove(&tmphash, (intptr_t)verts[i]); - BLI_smallhash_insert(&tmphash, (intptr_t)verts[i], NULL); - } - - vstart = vv; - lastv = NULL; - BLI_array_empty(edges); - do { - BM_ITER_ELEM (e, &eiter, vv, BM_EDGES_OF_VERT) { - BMVert *vv2 = BM_edge_other_vert(e, vv); - - if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) { - /* if we've go over the same vert twice, break out of outer loo */ - if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) { - e = NULL; - err = 1; - break; - } - - /* use self pointer as ta */ - BLI_smallhash_remove(&tmphash, (intptr_t)vv2); - BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2); - - lastv = vv; - BLI_array_append(edges, e); - vv = vv2; - break; - } - } - if (e == NULL) - break; - } while (vv != vstart); - - if (!err) { - e = BM_edge_create(bm, vv, vstart, NULL, TRUE); - BLI_array_append(edges, e); - } - } - - if (err) - continue; - - if (BLI_array_count(edges) >= 3) { - BMFace *f; - - if (BM_face_exists(bm, verts, BLI_array_count(verts), &f)) - continue; - - f = BM_face_create_ngon(bm, lastv, vstart, edges, BLI_array_count(edges), FALSE); - if (UNLIKELY(f == NULL)) { - fprintf(stderr, "%s: in bevel vert fill! (bmesh internal error)\n", __func__); - } - else { - BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_HOLE); - } - } - BLI_smallhash_release(&tmphash); - } - - /* copy over customdat */ - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - BMFace *f = faces[i]; - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - BMLoop *l2; - BMIter liter2; - - tag = tags + BM_elem_index_get(l); - if (!tag->newv) - continue; - - BM_ITER_ELEM (l2, &liter2, tag->newv, BM_LOOPS_OF_VERT) { - if (!BMO_elem_flag_test(bm, l2->f, FACE_NEW) || (l2->v != tag->newv && l2->v != l->v)) - continue; - - if (tag->newv != l->v || HasMDisps) { - BM_elem_attrs_copy(bm, bm, l->f, l2->f); - BM_loop_interp_from_face(bm, l2, l->f, TRUE, TRUE); - } - else { - BM_elem_attrs_copy(bm, bm, l->f, l2->f); - BM_elem_attrs_copy(bm, bm, l, l2); - } - - if (HasMDisps) { - BMLoop *l3; - BMIter liter3; - - BM_ITER_ELEM (l3, &liter3, l2->f, BM_LOOPS_OF_FACE) { - BM_loop_interp_multires(bm, l3, l->f); - } - } - } - } - } - - /* handle vertices along boundary edge */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_elem_flag_test(bm, v, VERT_OLD) && - BMO_elem_flag_test(bm, v, BEVEL_FLAG) && - !BMO_elem_flag_test(bm, v, BEVEL_DEL)) - { - BMLoop *l; - BMLoop *lorig = NULL; - BMIter liter; - - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - // BMIter liter2; - // BMLoop *l2 = l->v == v ? l : l->next, *l3; - - if (BMO_elem_flag_test(bm, l->f, FACE_OLD)) { - lorig = l; - break; - } - } - - if (!lorig) - continue; - - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - BMLoop *l2 = l->v == v ? l : l->next; - - BM_elem_attrs_copy(bm, bm, lorig->f, l2->f); - BM_elem_attrs_copy(bm, bm, lorig, l2); - } - } - } -#if 0 - /* clean up any remaining 2-edged face */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (f->len == 2) { - BMFace *faces[2] = {f, BM_FACE_FIRST_LOOP(f)->radial_next->f}; - - if (faces[0] == faces[1]) - BM_face_kill(bm, f); - else - BM_faces_join(bm, faces, 2); - } - } -#endif - - BMO_op_callf(bm, op->flag, "delete geom=%fv context=%i", BEVEL_DEL, DEL_VERTS); - - /* clean up any edges that might not get properly delete */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(bm, e, EDGE_OLD) && !e->l) - BMO_elem_flag_enable(bm, e, BEVEL_DEL); - } - - BMO_op_callf(bm, op->flag, "delete geom=%fe context=%i", BEVEL_DEL, DEL_EDGES); - BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", BEVEL_DEL, DEL_FACES); - - BLI_smallhash_release(&hash); - BLI_array_free(tags); - BLI_array_free(etags); - BLI_array_free(verts); - BLI_array_free(edges); - BLI_array_free(faces); - - BMO_slot_buffer_from_enabled_flag(bm, op, "face_spans", BM_FACE, FACE_SPAN); - BMO_slot_buffer_from_enabled_flag(bm, op, "face_holes", BM_FACE, FACE_HOLE); } diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index ebd848ff8b2..c7cd1e742d8 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -52,8 +52,10 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) BLI_array_declare(verts_pair); int i; - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_INPUT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_INPUT); + /* BMESH_TODO, loop over vert faces: + * faster then looping over all faces, then searching each for flagged verts*/ for (f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL); f; f = BM_iter_step(&iter)) { BLI_array_empty(loops_split); BLI_array_empty(verts_pair); @@ -117,7 +119,7 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); BLI_array_free(loops_split); BLI_array_free(verts_pair); @@ -219,12 +221,12 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) int c = 0, cl1 = 0, cl2 = 0; /* merge-bridge support */ - const int use_merge = BMO_slot_bool_get(op, "use_merge"); - const float merge_factor = BMO_slot_float_get(op, "merge_factor"); + const int use_merge = BMO_slot_bool_get(op->slots_in, "use_merge"); + const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (!BMO_elem_flag_test(bm, e, EDGE_DONE)) { BMVert *v, *ov; /* BMEdge *e2, *e3, *oe = e; */ /* UNUSED */ @@ -380,18 +382,19 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) /* compute summed length between vertices in forward direction */ len = 0.0f; - for (j = 0; j < lenv2; j++) { + for (j = 0; (j < lenv2) && (len < min); j++) { len += len_v3v3(vv1[clamp_index(i + j, lenv1)]->co, vv2[j]->co); } if (len < min) { min = len; starti = i; + dir1 = 1; } /* compute summed length between vertices in backward direction */ len = 0.0f; - for (j = 0; j < lenv2; j++) { + for (j = 0; (j < lenv2) && (len < min); j++) { len += len_v3v3(vv1[clamp_index(i - j, lenv1)]->co, vv2[j]->co); } @@ -523,7 +526,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT); cleanup: BLI_array_free(ee1); diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index bd1c0f809bd..aa69806fb37 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -168,7 +168,7 @@ static void rotsys_reverse(BMEdge *UNUSED(e), BMVert *v, EdgeData *edata, VertDa BMEdge **edges = NULL; BMEdge *e_first; BMEdge *e; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); int i, totedge; e = e_first = vdata[BM_elem_index_get(v)].e; @@ -274,7 +274,7 @@ static int UNUSED_FUNCTION(rotsys_fill_faces)(BMesh *bm, EdgeData *edata, VertDa if (!ok || BLI_array_count(edges) < 3) continue; - f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), TRUE); + f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), BM_CREATE_NO_DOUBLE); if (UNLIKELY(f == NULL)) { continue; } @@ -359,10 +359,10 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata) BMIter iter; BMEdge *e; BMEdge **edges = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); BMVert *v; /* BMVert **verts = NULL; */ - /* BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); */ /* UNUSE */ + /* BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); */ /* UNUSE */ int i; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -611,11 +611,11 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata) v2 = BM_vert_create(bm, co, NULL); BM_elem_index_set(v2, -1); /* set_dirty! */ - //BM_edge_create(bm, cv, v2, NULL, FALSE); + //BM_edge_create(bm, cv, v2, NULL, 0); BM_vert_select_set(bm, v2, TRUE); if (lastv) { - e2 = BM_edge_create(bm, lastv, v2, NULL, FALSE); + e2 = BM_edge_create(bm, lastv, v2, NULL, 0); BM_edge_select_set(bm, e2, TRUE); } @@ -741,7 +741,10 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E BMVert *startv; BMVert *endv; EPathNode *node; - int i, use_restrict = BMO_slot_bool_get(op, "use_restrict"); + int i; + const int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); + BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict"); + startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1; endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2; @@ -769,7 +772,7 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E verts[i] = node->v; } - if (BM_face_exists(bm, verts, i, &f)) { + if (BM_face_exists(verts, i, &f)) { if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) { BLI_ghash_remove(gh, endv, NULL, NULL); continue; @@ -806,12 +809,13 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E continue; } - if (use_restrict && BMO_slot_map_contains(bm, op, "restrict", e)) { - int group = BMO_slot_map_int_get(bm, op, "restrict", e); - - if (!(group & path->group)) { - v2 = NULL; - continue; + if (use_restrict) { + int *group = (int *)BMO_slot_map_data_get(slot_restrict, e); + if (group) { + if (!(*group & path->group)) { + v2 = NULL; + continue; + } } } @@ -895,12 +899,14 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) BMEdge **edges = NULL; PathBase *pathbase; BLI_array_declare(edges); - int use_restrict = BMO_slot_bool_get(op, "use_restrict"); - int use_fill_check = BMO_slot_bool_get(op, "use_fill_check"); - const short mat_nr = BMO_slot_int_get(op, "mat_nr"); - const short use_smooth = BMO_slot_bool_get(op, "use_smooth"); + int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); + int use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check"); + const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); + const short use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); int i, j, group = 0; unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */ + BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict"); + BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out"); if (!bm->totvert || !bm->totedge) return; @@ -910,8 +916,8 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData"); vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); - BMO_slot_buffer_flag_enable(bm, op, "excludefaces", BM_FACE, FACE_IGNORE); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "exclude_faces", BM_FACE, FACE_IGNORE); BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -932,14 +938,14 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) bm->elem_index_dirty &= ~BM_EDGE; init_rotsys(bm, edata, vdata); - + while (1) { edge = NULL; group = 0; - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /* if restrict is on, only start on faces in the restrict map */ - if (use_restrict && !BMO_slot_map_contains(bm, op, "restrict", e)) + if (use_restrict && !BMO_slot_map_contains(slot_restrict, e)) continue; if (edata[BM_elem_index_get(e)].tag < 2) { @@ -948,7 +954,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) if (use_restrict) { int i = 0, j = 0, gi = 0; - group = BMO_slot_map_int_get(bm, op, "restrict", e); + group = BMO_slot_map_int_get(slot_restrict, e); for (i = 0; i < 30; i++) { if (group & (1 << i)) { @@ -1045,7 +1051,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) /* fairly expensive check - see if there are already faces filling this area */ (BM_face_exists_multi_edge(edges, i) == FALSE)) { - f = BM_face_create_ngon(bm, v1, v2, edges, i, TRUE); + f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE); if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) { BMO_elem_flag_enable(bm, f, FACE_NEW); f->mat_nr = mat_nr; @@ -1055,7 +1061,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) } if (use_restrict) { - BMO_slot_map_int_insert(bm, op, "faceout_groupmap", f, path->group); + BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group); } } } @@ -1063,7 +1069,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) edge_free_path(pathbase, path); } - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW); BLI_array_free(edges); BLI_array_free(verts); @@ -1092,7 +1098,7 @@ static BMEdge *edge_next(BMesh *bm, BMEdge *e) return NULL; } -void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) +void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e; @@ -1103,11 +1109,11 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) int ok = 1; int i, count; - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); /* validate that each edge has at most one other tagged edge in the * disk cycle around each of it's vertices */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { for (i = 0; i < 2; i++) { count = BMO_vert_edge_flags_count(bm, i ? e->v2 : e->v1, EDGE_MARK); if (count > 2) { @@ -1129,7 +1135,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) /* find connected loops within the input edge */ count = 0; while (1) { - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (!BMO_elem_flag_test(bm, e, EDGE_VIS)) { if (BMO_vert_edge_flags_count(bm, e->v1, EDGE_MARK) == 1 || BMO_vert_edge_flags_count(bm, e->v2, EDGE_MARK) == 1) @@ -1177,10 +1183,10 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) } if (edges1 && BLI_array_count(edges1) > 2 && - BM_edge_share_vert_count(edges1[0], edges1[BLI_array_count(edges1) - 1])) + BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1])) { if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1])) + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) { BLI_array_free(edges1); BLI_array_free(edges2); @@ -1193,7 +1199,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) } if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1])) + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) { edges2 = NULL; } @@ -1243,9 +1249,9 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) SWAP(BMVert *, v3, v4); } - e = BM_edge_create(bm, v1, v3, NULL, TRUE); + e = BM_edge_create(bm, v1, v3, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); - e = BM_edge_create(bm, v2, v4, NULL, TRUE); + e = BM_edge_create(bm, v2, v4, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); } else if (edges1) { @@ -1255,12 +1261,12 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1; i = BLI_array_count(edges1) - 1; v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1; - e = BM_edge_create(bm, v1, v2, NULL, TRUE); + e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW); BLI_array_free(edges1); BLI_array_free(edges2); @@ -1280,11 +1286,11 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMEdge *e; BMFace *f; int totv = 0, tote = 0, totf = 0, amount; - const short mat_nr = BMO_slot_int_get(op, "mat_nr"); - const short use_smooth = BMO_slot_bool_get(op, "use_smooth"); + const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); + const short use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); /* count number of each element type we were passe */ - BMO_ITER (h, &oiter, bm, op, "geom", BM_VERT | BM_EDGE | BM_FACE) { + BMO_ITER (h, &oiter, op->slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE) { switch (h->htype) { case BM_VERT: totv++; break; case BM_EDGE: tote++; break; @@ -1318,7 +1324,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) int ok = TRUE; - BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) { /* count how many flagged edges this vertex uses */ int tot_edges = 0; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { @@ -1353,10 +1359,10 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) } if (ok == TRUE && v_free && v_a && v_b) { - e = BM_edge_create(bm, v_free, v_a, NULL, TRUE); + e = BM_edge_create(bm, v_free, v_a, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); - e = BM_edge_create(bm, v_free, v_b, NULL, TRUE); + e = BM_edge_create(bm, v_free, v_b, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); } } @@ -1366,7 +1372,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) /* call edgenet prepare op so additional face creation cases wore */ BMO_op_initf(bm, &op2, op->flag, "edgenet_prepare edges=%fe", ELE_NEW); BMO_op_exec(bm, &op2); - BMO_slot_buffer_flag_enable(bm, &op2, "edgeout", BM_EDGE, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, op2.slots_out, "edges.out", BM_EDGE, ELE_NEW); BMO_op_finish(bm, &op2); BMO_op_initf(bm, &op2, op->flag, @@ -1376,8 +1382,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op2); /* return if edge net create did something */ - if (BMO_slot_buffer_count(bm, &op2, "faceout")) { - BMO_slot_copy(&op2, op, "faceout", "faceout"); + if (BMO_slot_buffer_count(op2.slots_out, "faces.out")) { + BMO_slot_copy(&op2, slots_out, "faces.out", + op, slots_out, "faces.out"); BMO_op_finish(bm, &op2); return; } @@ -1389,8 +1396,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op2); /* if we dissolved anything, then return */ - if (BMO_slot_buffer_count(bm, &op2, "regionout")) { - BMO_slot_copy(&op2, op, "regionout", "faceout"); + if (BMO_slot_buffer_count(op2.slots_out, "region.out")) { + BMO_slot_copy(&op2, slots_out, "region.out", + op, slots_out, "faces.out"); BMO_op_finish(bm, &op2); return; } @@ -1412,9 +1420,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) if (amount == 2) { /* create edge */ - e = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE); + e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_OUT); - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); } else if (0) { /* nice feature but perhaps it should be a different tool? */ @@ -1453,14 +1461,14 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) if (ese->htype == BM_VERT) { v = (BMVert *)ese->ele; if (v_prev) { - e = BM_edge_create(bm, v, v_prev, NULL, TRUE); + e = BM_edge_create(bm, v, v_prev, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_OUT); } v_prev = v; } } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); /* done creating edges */ } else if (amount > 2) { @@ -1470,12 +1478,12 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMVert **vert_arr = MEM_mallocN(sizeof(BMVert **) * totv, __func__); int i = 0; - BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) { vert_arr[i] = v; i++; } - f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, TRUE); + f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, BM_CREATE_NO_DOUBLE); if (f) { BMO_elem_flag_enable(bm, f, ELE_OUT); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 9addb1b1657..7c3bcd60daa 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -85,7 +85,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) BMWalker regwalker; int i; - int use_verts = BMO_slot_bool_get(op, "use_verts"); + int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); if (use_verts) { /* tag verts that start out with only 2 edges, @@ -98,10 +98,10 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_flag_enable(bm, op, "faces", BM_FACE, FACE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_MARK); /* collect region */ - BMO_ITER (f, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, f, FACE_MARK)) { continue; @@ -184,7 +184,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) goto cleanup; } - BMO_slot_buffer_from_enabled_flag(bm, op, "regionout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW); cleanup: /* free/cleanup */ @@ -208,7 +208,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) int i; - BMO_ITER (e, &oiter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) { if (BM_edge_face_pair(e, &fa, &fb)) { BMO_elem_flag_enable(bm, e->v1, VERT_MARK); BMO_elem_flag_enable(bm, e->v2, VERT_MARK); @@ -237,7 +237,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) //BMO_op_initf(bm, &fop, "dissolve_faces faces=%ff", FACE_MARK); //BMO_op_exec(bm, &fop); - //BMO_slot_copy(op, &fop, "regionout", "regionout"); + //BMO_slot_copy(op, &fop, "region.out", "region.out"); //BMO_op_finish(bm, &fop); } @@ -254,7 +254,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) BMIter viter; BMVert *v; - int use_verts = BMO_slot_bool_get(op, "use_verts"); + int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); if (use_verts) { BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { @@ -262,7 +262,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &eiter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) { BMFace *fa, *fb; if (BM_edge_face_pair(e, &fa, &fb)) { @@ -338,7 +338,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) BMFace *f; /* int i; */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_MARK); for (v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v = BM_iter_step(&iter)) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { @@ -479,13 +479,13 @@ void dummy_exec(BMesh *bm, BMOperator *op) /* Limited Dissolve */ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op) { - BMOpSlot *einput = BMO_slot_get(op, "edges"); - BMOpSlot *vinput = BMO_slot_get(op, "verts"); + BMOpSlot *einput = BMO_slot_get(op->slots_in, "edges"); + BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts"); const float angle_max = (float)M_PI / 2.0f; - const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op, "angle_limit")); - const int do_dissolve_boundaries = BMO_slot_bool_get(op, "use_dissolve_boundaries"); + const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit")); + const int do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries"); BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, - vinput->data.p, vinput->len, - einput->data.p, einput->len); + (BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len, + (BMEdge **)BMO_SLOT_AS_BUFFER(einput), einput->len); } diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 32270007a0b..9a58d7acfb9 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -49,7 +49,7 @@ static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *tar BMVert *target_vertex = NULL; /* Create a new vertex */ - target_vertex = BM_vert_create(target_mesh, source_vertex->co, NULL); + target_vertex = BM_vert_create(target_mesh, source_vertex->co, NULL, BM_CREATE_SKIP_CD); /* Insert new vertex into the vert hash */ BLI_ghash_insert(vhash, source_vertex, target_vertex); @@ -68,7 +68,9 @@ static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *tar * * Copy an existing edge from one bmesh to another. */ -static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, +static BMEdge *copy_edge(BMOperator *op, + BMOpSlot *slot_boundarymap_out, + BMesh *source_mesh, BMEdge *source_edge, BMesh *target_mesh, GHash *vhash, GHash *ehash) { @@ -96,14 +98,13 @@ static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2); /* Create a new edge */ - target_edge = BM_edge_create(target_mesh, target_vert1, target_vert2, NULL, FALSE); + target_edge = BM_edge_create(target_mesh, target_vert1, target_vert2, NULL, BM_CREATE_SKIP_CD); /* add to new/old edge map if necassary */ if (rlen < 2) { /* not sure what non-manifold cases of greater then three * radial should do. */ - BMO_slot_map_ptr_insert(source_mesh, op, "boundarymap", - source_edge, target_edge); + BMO_slot_map_elem_insert(op, slot_boundarymap_out, source_edge, target_edge); } /* Insert new edge into the edge hash */ @@ -124,7 +125,9 @@ static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, * Copy an existing face from one bmesh to another. */ -static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, +static BMFace *copy_face(BMOperator *op, + BMOpSlot *slot_facemap_out, + BMesh *source_mesh, BMFace *source_face, BMesh *target_mesh, BMVert **vtar, BMEdge **edar, GHash *vhash, GHash *ehash) { @@ -151,11 +154,11 @@ static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, vtar[i] = BLI_ghash_lookup(vhash, source_loop->v); edar[i] = BLI_ghash_lookup(ehash, source_loop->e); } - + /* create new face */ - target_face = BM_face_create(target_mesh, vtar, edar, source_face->len, FALSE); - BMO_slot_map_ptr_insert(source_mesh, op, "facemap", source_face, target_face); - BMO_slot_map_ptr_insert(source_mesh, op, "facemap", target_face, source_face); + target_face = BM_face_create(target_mesh, vtar, edar, source_face->len, BM_CREATE_SKIP_CD); + BMO_slot_map_elem_insert(op, slot_facemap_out, source_face, target_face); + BMO_slot_map_elem_insert(op, slot_facemap_out, target_face, source_face); BM_elem_attrs_copy(source_mesh, target_mesh, source_face, target_face); @@ -181,7 +184,7 @@ static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, * Internal Copy function. */ -static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) +static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) { BMVert *v = NULL, *v2; @@ -196,22 +199,26 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) BMIter viter, eiter, fiter; GHash *vhash, *ehash; + BMOpSlot *slot_boundary_map_out = BMO_slot_get(op->slots_out, "boundary_map.out"); + BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out"); + BMOpSlot *slot_isovert_map_out = BMO_slot_get(op->slots_out, "isovert_map.out"); + /* initialize pointer hashes */ vhash = BLI_ghash_ptr_new("bmesh dupeops v"); ehash = BLI_ghash_ptr_new("bmesh dupeops e"); /* duplicate flagged vertices */ - BM_ITER_MESH (v, &viter, source, BM_VERTS_OF_MESH) { - if (BMO_elem_flag_test(source, v, DUPE_INPUT) && - !BMO_elem_flag_test(source, v, DUPE_DONE)) + BM_ITER_MESH (v, &viter, bm_src, BM_VERTS_OF_MESH) { + if (BMO_elem_flag_test(bm_src, v, DUPE_INPUT) && + !BMO_elem_flag_test(bm_src, v, DUPE_DONE)) { BMIter iter; int isolated = 1; - v2 = copy_vertex(source, v, target, vhash); + v2 = copy_vertex(bm_src, v, bm_dst, vhash); BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { - if (BMO_elem_flag_test(source, f, DUPE_INPUT)) { + if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) { isolated = 0; break; } @@ -219,7 +226,7 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) if (isolated) { BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - if (BMO_elem_flag_test(source, e, DUPE_INPUT)) { + if (BMO_elem_flag_test(bm_src, e, DUPE_INPUT)) { isolated = 0; break; } @@ -227,49 +234,49 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) } if (isolated) { - BMO_slot_map_ptr_insert(source, op, "isovertmap", v, v2); + BMO_slot_map_elem_insert(op, slot_isovert_map_out, v, v2); } - BMO_elem_flag_enable(source, v, DUPE_DONE); + BMO_elem_flag_enable(bm_src, v, DUPE_DONE); } } /* now we dupe all the edges */ - BM_ITER_MESH (e, &eiter, source, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(source, e, DUPE_INPUT) && - !BMO_elem_flag_test(source, e, DUPE_DONE)) + BM_ITER_MESH (e, &eiter, bm_src, BM_EDGES_OF_MESH) { + if (BMO_elem_flag_test(bm_src, e, DUPE_INPUT) && + !BMO_elem_flag_test(bm_src, e, DUPE_DONE)) { /* make sure that verts are copied */ - if (!BMO_elem_flag_test(source, e->v1, DUPE_DONE)) { - copy_vertex(source, e->v1, target, vhash); - BMO_elem_flag_enable(source, e->v1, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e->v1, DUPE_DONE)) { + copy_vertex(bm_src, e->v1, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, e->v1, DUPE_DONE); } - if (!BMO_elem_flag_test(source, e->v2, DUPE_DONE)) { - copy_vertex(source, e->v2, target, vhash); - BMO_elem_flag_enable(source, e->v2, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e->v2, DUPE_DONE)) { + copy_vertex(bm_src, e->v2, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, e->v2, DUPE_DONE); } /* now copy the actual edge */ - copy_edge(op, source, e, target, vhash, ehash); - BMO_elem_flag_enable(source, e, DUPE_DONE); + copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash); + BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } /* first we dupe all flagged faces and their elements from source */ - BM_ITER_MESH (f, &fiter, source, BM_FACES_OF_MESH) { - if (BMO_elem_flag_test(source, f, DUPE_INPUT)) { + BM_ITER_MESH (f, &fiter, bm_src, BM_FACES_OF_MESH) { + if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) { /* vertex pass */ BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { - if (!BMO_elem_flag_test(source, v, DUPE_DONE)) { - copy_vertex(source, v, target, vhash); - BMO_elem_flag_enable(source, v, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, v, DUPE_DONE)) { + copy_vertex(bm_src, v, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, v, DUPE_DONE); } } /* edge pass */ BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) { - if (!BMO_elem_flag_test(source, e, DUPE_DONE)) { - copy_edge(op, source, e, target, vhash, ehash); - BMO_elem_flag_enable(source, e, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e, DUPE_DONE)) { + copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash); + BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } @@ -280,8 +287,8 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) BLI_array_grow_items(vtar, f->len); BLI_array_grow_items(edar, f->len); - copy_face(op, source, f, target, vtar, edar, vhash, ehash); - BMO_elem_flag_enable(source, f, DUPE_DONE); + copy_face(op, slot_face_map_out, bm_src, f, bm_dst, vtar, edar, vhash, ehash); + BMO_elem_flag_enable(bm_src, f, DUPE_DONE); } } @@ -317,23 +324,24 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) void bmo_duplicate_exec(BMesh *bm, BMOperator *op) { BMOperator *dupeop = op; - BMesh *bm2 = BMO_slot_ptr_get(op, "dest"); + BMesh *bm2 = BMO_slot_ptr_get(op->slots_in, "dest"); if (!bm2) bm2 = bm; /* flag input */ - BMO_slot_buffer_flag_enable(bm, dupeop, "geom", BM_ALL, DUPE_INPUT); + BMO_slot_buffer_flag_enable(bm, dupeop->slots_in, "geom", BM_ALL_NOLOOP, DUPE_INPUT); /* use the internal copy function */ - BKE_mesh_copy(dupeop, bm, bm2); + bmo_mesh_copy(dupeop, bm, bm2); /* Output */ /* First copy the input buffers to output buffers - original data */ - BMO_slot_copy(dupeop, dupeop, "geom", "origout"); + BMO_slot_copy(dupeop, slots_in, "geom", + dupeop, slots_out, "geom_orig.out"); /* Now alloc the new output buffers */ - BMO_slot_buffer_from_enabled_flag(bm, dupeop, "newout", BM_ALL, DUPE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, dupeop, dupeop->slots_out, "geom.out", BM_ALL_NOLOOP, DUPE_NEW); } #if 0 /* UNUSED */ @@ -378,16 +386,17 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) BMOperator *splitop = op; BMOperator dupeop; BMOperator delop; - const short use_only_faces = BMO_slot_bool_get(op, "use_only_faces"); + const short use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces"); /* initialize our sub-operator */ BMO_op_init(bm, &dupeop, op->flag, "duplicate"); BMO_op_init(bm, &delop, op->flag, "delete"); - BMO_slot_copy(splitop, &dupeop, "geom", "geom"); + BMO_slot_copy(splitop, slots_in, "geom", + &dupeop, slots_in, "geom"); BMO_op_exec(bm, &dupeop); - BMO_slot_buffer_flag_enable(bm, splitop, "geom", BM_ALL, SPLIT_INPUT); + BMO_slot_buffer_flag_enable(bm, splitop->slots_in, "geom", BM_ALL_NOLOOP, SPLIT_INPUT); if (use_only_faces) { BMVert *v; @@ -427,16 +436,22 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) } /* connect outputs of dupe to delete, exluding keep geometry */ - BMO_slot_int_set(&delop, "context", DEL_FACES); - BMO_slot_buffer_from_enabled_flag(bm, &delop, "geom", BM_ALL, SPLIT_INPUT); + BMO_slot_int_set(delop.slots_in, "context", DEL_FACES); + BMO_slot_buffer_from_enabled_flag(bm, &delop, delop.slots_in, "geom", BM_ALL_NOLOOP, SPLIT_INPUT); BMO_op_exec(bm, &delop); /* now we make our outputs by copying the dupe output */ - BMO_slot_copy(&dupeop, splitop, "newout", "geomout"); - BMO_slot_copy(&dupeop, splitop, "boundarymap", "boundarymap"); - BMO_slot_copy(&dupeop, splitop, "isovertmap", "isovertmap"); - + BMO_slot_copy(&dupeop, slots_out, "geom.out", + splitop, slots_out, "geom.out"); + + BMO_slot_copy(&dupeop, slots_out, "boundary_map.out", + splitop, slots_out, "boundary_map.out"); + + BMO_slot_copy(&dupeop, slots_out, "isovert_map.out", + splitop, slots_out, "isovert_map.out"); + + /* cleanup */ BMO_op_finish(bm, &delop); BMO_op_finish(bm, &dupeop); @@ -450,9 +465,9 @@ void bmo_delete_exec(BMesh *bm, BMOperator *op) BMOperator *delop = op; /* Mark Buffer */ - BMO_slot_buffer_flag_enable(bm, delop, "geom", BM_ALL, DEL_INPUT); + BMO_slot_buffer_flag_enable(bm, delop->slots_in, "geom", BM_ALL_NOLOOP, DEL_INPUT); - BMO_remove_tagged_context(bm, DEL_INPUT, BMO_slot_int_get(op, "context")); + BMO_remove_tagged_context(bm, DEL_INPUT, BMO_slot_int_get(op->slots_in, "context")); #undef DEL_INPUT } @@ -473,44 +488,47 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op) float phi; int steps, do_dupli, a, usedvec; - BMO_slot_vec_get(op, "cent", cent); - BMO_slot_vec_get(op, "axis", axis); + BMO_slot_vec_get(op->slots_in, "cent", cent); + BMO_slot_vec_get(op->slots_in, "axis", axis); normalize_v3(axis); - BMO_slot_vec_get(op, "dvec", dvec); + BMO_slot_vec_get(op->slots_in, "dvec", dvec); usedvec = !is_zero_v3(dvec); - steps = BMO_slot_int_get(op, "steps"); - phi = BMO_slot_float_get(op, "ang") * DEG2RADF(1.0f) / steps; - do_dupli = BMO_slot_bool_get(op, "do_dupli"); + steps = BMO_slot_int_get(op->slots_in, "steps"); + phi = BMO_slot_float_get(op->slots_in, "angle") / steps; + do_dupli = BMO_slot_bool_get(op->slots_in, "use_duplicate"); axis_angle_to_mat3(rmat, axis, phi); - BMO_slot_copy(op, op, "geom", "lastout"); + BMO_slot_copy(op, slots_in, "geom", + op, slots_out, "geom_last.out"); for (a = 0; a < steps; a++) { if (do_dupli) { - BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%s", op, "lastout"); + BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%S", op, "geom_last.out"); BMO_op_exec(bm, &dupop); BMO_op_callf(bm, op->flag, - "rotate cent=%v mat=%m3 verts=%s", - cent, rmat, &dupop, "newout"); - BMO_slot_copy(&dupop, op, "newout", "lastout"); + "rotate cent=%v matrix=%m3 verts=%S", + cent, rmat, &dupop, "geom.out"); + BMO_slot_copy(&dupop, slots_out, "geom.out", + op, slots_out, "geom_last.out"); BMO_op_finish(bm, &dupop); } else { - BMO_op_initf(bm, &extop, op->flag, "extrude_face_region edgefacein=%s", - op, "lastout"); + BMO_op_initf(bm, &extop, op->flag, "extrude_face_region geom=%S", + op, "geom_last.out"); BMO_op_exec(bm, &extop); BMO_op_callf(bm, op->flag, - "rotate cent=%v mat=%m3 verts=%s", - cent, rmat, &extop, "geomout"); - BMO_slot_copy(&extop, op, "geomout", "lastout"); + "rotate cent=%v matrix=%m3 verts=%S", + cent, rmat, &extop, "geom.out"); + BMO_slot_copy(&extop, slots_out, "geom.out", + op, slots_out, "geom_last.out"); BMO_op_finish(bm, &extop); } if (usedvec) { mul_m3_v3(rmat, dvec); BMO_op_callf(bm, op->flag, - "translate vec=%v verts=%s", - dvec, op, "lastout"); + "translate vec=%v verts=%S", + dvec, op, "geom_last.out"); } } } diff --git a/source/blender/bmesh/operators/bmo_edgesplit.c b/source/blender/bmesh/operators/bmo_edgesplit.c index 1f6689ed06c..9e9e4b8c962 100644 --- a/source/blender/bmesh/operators/bmo_edgesplit.c +++ b/source/blender/bmesh/operators/bmo_edgesplit.c @@ -81,14 +81,14 @@ static void bm_edgesplit_validate_seams(BMesh *bm, BMOperator *op) /* single marked edges unconnected to any other marked edges * are illegal, go through and unmark them */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /* lame, but we don't want the count to exceed 255, * so just count to 2, its all we need */ unsigned char *vt; vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; } - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (vtouch[BM_elem_index_get(e->v1)] == 1 && vtouch[BM_elem_index_get(e->v2)] == 1) { @@ -104,13 +104,13 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e; - const int use_verts = BMO_slot_bool_get(op, "use_verts"); + const int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_SEAM); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_SEAM); if (use_verts) { /* this slows down the operation but its ok because the modifier doesn't use */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_SEAM); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_SEAM); /* prevent one edge having both verts unflagged * we could alternately disable these edges, either way its a corner case. @@ -118,7 +118,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) * This is needed so we don't split off the edge but then none of its verts which * would leave a duplicate edge. */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (UNLIKELY((BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE && (BMO_elem_flag_test(bm, e->v2, VERT_SEAM) == FALSE)))) { @@ -130,7 +130,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) bm_edgesplit_validate_seams(bm, op); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) { /* this flag gets copied so we can be sure duplicate edges get it too (important) */ BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); @@ -146,7 +146,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } if (use_verts) { - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); } @@ -156,7 +156,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) { if (BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); @@ -169,5 +169,5 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_hflag(bm, op, "edgeout", BM_EDGE, BM_ELEM_INTERNAL_TAG); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_INTERNAL_TAG); } diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 627351ead11..065a1b57737 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -60,18 +60,18 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) BLI_array_declare(edges); int i; - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BLI_array_empty(edges); BLI_array_grow_items(edges, f->len); i = 0; firstv = lastv = NULL; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - v = BM_vert_create(bm, l->v->co, l->v); + v = BM_vert_create(bm, l->v->co, l->v, 0); /* skip on the first iteration */ if (lastv) { - e = BM_edge_create(bm, lastv, v, l->e, FALSE); + e = BM_edge_create(bm, lastv, v, l->e, 0); edges[i++] = e; } @@ -81,12 +81,12 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) } /* this fits in the array because we skip one in the loop above */ - e = BM_edge_create(bm, v, firstv, laste, FALSE); + e = BM_edge_create(bm, v, firstv, laste, 0); edges[i++] = e; BMO_elem_flag_enable(bm, f, EXT_DEL); - f2 = BM_face_create_ngon(bm, firstv, BM_edge_other_vert(edges[0], firstv), edges, f->len, FALSE); + f2 = BM_face_create_ngon(bm, firstv, BM_edge_other_vert(edges[0], firstv), edges, f->len, 0); if (UNLIKELY(f2 == NULL)) { BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Extrude failed: could not create face"); BLI_array_free(edges); @@ -122,7 +122,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", EXT_DEL, DEL_ONLYFACES); - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, EXT_KEEP); } /** @@ -181,7 +181,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) BMFace *f; BMEdge *e, *e_new; - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, e, EXT_INPUT); BMO_elem_flag_enable(bm, e->v1, EXT_INPUT); BMO_elem_flag_enable(bm, e->v2, EXT_INPUT); @@ -193,12 +193,12 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) /* disable root flag on all new skin nodes */ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { BMVert *v; - BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER(v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { bm_extrude_disable_skin_root(bm, v); } } - for (e = BMO_iter_new(&siter, bm, &dupeop, "boundarymap", 0); e; e = BMO_iter_step(&siter)) { + for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) { BMVert *f_verts[4]; e_new = *(BMEdge **)BMO_iter_map_value(&siter); @@ -230,7 +230,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &dupeop); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, EXT_KEEP); } void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) @@ -240,19 +240,19 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) BMEdge *e; const int has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); - for (v = BMO_iter_new(&siter, bm, op, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { - dupev = BM_vert_create(bm, v->co, v); + for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { + dupev = BM_vert_create(bm, v->co, v, 0); if (has_vskin) bm_extrude_disable_skin_root(bm, v); - e = BM_edge_create(bm, v, dupev, NULL, FALSE); + e = BM_edge_create(bm, v, dupev, NULL, 0); BMO_elem_flag_enable(bm, e, EXT_KEEP); BMO_elem_flag_enable(bm, dupev, EXT_KEEP); } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, EXT_KEEP); - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP); } void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) @@ -264,15 +264,17 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMVert *v, *v2; BMFace *f; int found, fwd, delorig = FALSE; + BMOpSlot *slot_facemap_out; + BMOpSlot *slot_edges_exclude; /* initialize our sub-operators */ BMO_op_init(bm, &dupeop, op->flag, "duplicate"); - BMO_slot_buffer_flag_enable(bm, op, "edgefacein", BM_EDGE | BM_FACE, EXT_INPUT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT); /* if one flagged face is bordered by an un-flagged face, then we delete * original geometry unless caller explicitly asked to keep it. */ - if (!BMO_slot_bool_get(op, "alwayskeeporig")) { + if (!BMO_slot_bool_get(op->slots_in, "use_keep_orig")) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { int edge_face_tot; @@ -339,18 +341,21 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) EXT_DEL, DEL_ONLYTAGGED); } - BMO_slot_copy(op, &dupeop, "edgefacein", "geom"); + BMO_slot_copy(op, slots_in, "geom", + &dupeop, slots_in, "geom"); BMO_op_exec(bm, &dupeop); /* disable root flag on all new skin nodes */ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { - BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER(v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { bm_extrude_disable_skin_root(bm, v); } } - if (bm->act_face && BMO_elem_flag_test(bm, bm->act_face, EXT_INPUT)) - bm->act_face = BMO_slot_map_ptr_get(bm, &dupeop, "facemap", bm->act_face); + slot_facemap_out = BMO_slot_get(dupeop.slots_out, "face_map.out"); + if (bm->act_face && BMO_elem_flag_test(bm, bm->act_face, EXT_INPUT)) { + bm->act_face = BMO_slot_map_elem_get(slot_facemap_out, bm->act_face); + } if (delorig) { BMO_op_exec(bm, &delop); @@ -365,13 +370,15 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_copy(&dupeop, op, "newout", "geomout"); + BMO_slot_copy(&dupeop, slots_out, "geom.out", + op, slots_out, "geom.out"); - for (e = BMO_iter_new(&siter, bm, &dupeop, "boundarymap", 0); e; e = BMO_iter_step(&siter)) { + slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); + for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) { BMVert *f_verts[4]; /* this should always be wire, so this is mainly a speedup to avoid map lookup */ - if (BM_edge_is_wire(e) && BMO_slot_map_contains(bm, op, "exclude", e)) { + if (BM_edge_is_wire(e) && BMO_slot_map_contains(slot_edges_exclude, e)) { BMVert *v1 = e->v1, *v2 = e->v2; /* The original edge was excluded, @@ -421,9 +428,9 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } /* link isolated vert */ - for (v = BMO_iter_new(&siter, bm, &dupeop, "isovertmap", 0); v; v = BMO_iter_step(&siter)) { + for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; v = BMO_iter_step(&siter)) { v2 = *((void **)BMO_iter_map_value(&siter)); - BM_edge_create(bm, v, v2, v->e, TRUE); + BM_edge_create(bm, v, v2, v->e, BM_CREATE_NO_DOUBLE); } /* cleanup */ @@ -595,10 +602,10 @@ static void solidify_add_thickness(BMesh *bm, const float dist) /* array for passing verts to angle_poly_v3 */ float **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); /* array for receiving angles from angle_poly_v3 */ float *face_angles = NULL; - BLI_array_staticdeclare(face_angles, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(face_angles, BM_DEFAULT_NGON_STACK_SIZE); BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -647,25 +654,28 @@ void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op) BMOperator reverseop; float thickness; - thickness = BMO_slot_float_get(op, "thickness"); + thickness = BMO_slot_float_get(op->slots_in, "thickness"); /* Flip original faces (so the shell is extruded inward) */ BMO_op_init(bm, &reverseop, op->flag, "reverse_faces"); - BMO_slot_copy(op, &reverseop, "geom", "faces"); + BMO_slot_copy(op, slots_in, "geom", + &reverseop, slots_in, "faces"); BMO_op_exec(bm, &reverseop); BMO_op_finish(bm, &reverseop); /* Extrude the region */ - BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region alwayskeeporig=%b", TRUE); - BMO_slot_copy(op, &extrudeop, "geom", "edgefacein"); + BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", TRUE); + BMO_slot_copy(op, slots_in, "geom", + &extrudeop, slots_in, "geom"); BMO_op_exec(bm, &extrudeop); /* Push the verts of the extruded faces inward to create thickness */ - BMO_slot_buffer_flag_enable(bm, &extrudeop, "geomout", BM_FACE, FACE_MARK); + BMO_slot_buffer_flag_enable(bm, extrudeop.slots_out, "geom.out", BM_FACE, FACE_MARK); calc_solidify_normals(bm); solidify_add_thickness(bm, thickness); - BMO_slot_copy(&extrudeop, op, "geomout", "geomout"); + BMO_slot_copy(&extrudeop, slots_out, "geom.out", + op, slots_out, "geom.out"); BMO_op_finish(bm, &extrudeop); } diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 013b6183f84..e2da4f4f89c 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -113,13 +113,13 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) if (!t->skip) { BMEdge *edges[3] = { - BM_edge_create(bm, t->v[0], t->v[1], NULL, TRUE), - BM_edge_create(bm, t->v[1], t->v[2], NULL, TRUE), - BM_edge_create(bm, t->v[2], t->v[0], NULL, TRUE) + BM_edge_create(bm, t->v[0], t->v[1], NULL, BM_CREATE_NO_DOUBLE), + BM_edge_create(bm, t->v[1], t->v[2], NULL, BM_CREATE_NO_DOUBLE), + BM_edge_create(bm, t->v[2], t->v[0], NULL, BM_CREATE_NO_DOUBLE) }; BMFace *f, *example = NULL; - if (BM_face_exists(bm, t->v, 3, &f)) { + if (BM_face_exists(t->v, 3, &f)) { /* If the operator is run with "use_existing_faces" * disabled, but an output face in the hull is the * same as a face in the existing mesh, it should not @@ -139,17 +139,17 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) f = BM_face_create_quad_tri_v(bm, t->v, 3, example, TRUE); BM_face_copy_shared(bm, f); } - /* Mark face for 'geomout' slot and select */ + /* Mark face for 'geom.out' slot and select */ BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM); BM_face_select_set(bm, f, TRUE); - /* Mark edges for 'geomout' slot */ + /* Mark edges for 'geom.out' slot */ for (i = 0; i < 3; i++) { BMO_elem_flag_enable(bm, edges[i], HULL_FLAG_OUTPUT_GEOM); } } else { - /* Mark input edges for 'geomout' slot */ + /* Mark input edges for 'geom.out' slot */ for (i = 0; i < 3; i++) { const int next = (i == 2 ? 0 : i + 1); BMEdge *e = BM_edge_exists(t->v[i], t->v[next]); @@ -161,7 +161,7 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) } } - /* Mark verts for 'geomout' slot */ + /* Mark verts for 'geom.out' slot */ for (i = 0; i < 3; i++) { BMO_elem_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM); } @@ -304,14 +304,14 @@ static void hull_mark_interior_elements(BMesh *bm, BMOperator *op, BMOIter oiter; /* Check for interior edges too */ - BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) BMO_elem_flag_enable(bm, e, HULL_FLAG_INTERIOR_ELE); } /* Mark all input faces as interior, some may be unmarked in * hull_remove_overlapping() */ - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { BMO_elem_flag_enable(bm, f, HULL_FLAG_INTERIOR_ELE); } } @@ -328,7 +328,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) * interior (i.e. were already part of the input, but not part of * the hull), but that aren't also used by elements outside the * input set */ - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { if (BMO_elem_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) { int del = TRUE; @@ -351,7 +351,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { if (BMO_elem_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) { int del = TRUE; @@ -367,7 +367,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) } } - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { if (BMO_elem_flag_test(bm, f, HULL_FLAG_INTERIOR_ELE)) BMO_elem_flag_enable(bm, f, HULL_FLAG_DEL); } @@ -382,10 +382,10 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) /* Unmark any hole faces if they are isolated or part of a * border */ - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { if (BMO_elem_flag_test(bm, f, HULL_FLAG_HOLE)) { BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) { - if (BM_edge_face_count(e) == 1) { + if (BM_edge_is_boundary(e)) { BMO_elem_flag_disable(bm, f, HULL_FLAG_HOLE); break; } @@ -395,7 +395,7 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) /* Mark edges too if all adjacent faces are holes and the edge is * not already isolated */ - BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { int hole = TRUE; int any_faces = FALSE; @@ -412,29 +412,29 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) } } -static int hull_input_vert_count(BMesh *bm, BMOperator *op) +static int hull_input_vert_count(BMOperator *op) { BMOIter oiter; BMVert *v; int count = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { count++; } return count; } -static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, - const int num_input_verts) +static BMVert **hull_input_verts_copy(BMOperator *op, + const int num_input_verts) { BMOIter oiter; BMVert *v; BMVert **input_verts = MEM_callocN(sizeof(*input_verts) * - num_input_verts, AT); + num_input_verts, AT); int i = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { input_verts[i++] = v; } @@ -442,7 +442,7 @@ static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, } static float (*hull_verts_for_bullet(BMVert **input_verts, - const int num_input_verts))[3] + const int num_input_verts))[3] { float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, AT); int i; @@ -455,12 +455,12 @@ static float (*hull_verts_for_bullet(BMVert **input_verts, } static BMVert **hull_verts_from_bullet(plConvexHull hull, - BMVert **input_verts, - const int num_input_verts) + BMVert **input_verts, + const int num_input_verts) { const int num_verts = plConvexHullNumVertices(hull); BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) * - num_verts, AT); + num_verts, AT); int i; for (i = 0; i < num_verts; i++) { @@ -479,8 +479,8 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull, } static void hull_from_bullet(BMesh *bm, BMOperator *op, - GHash *hull_triangles, - BLI_mempool *pool) + GHash *hull_triangles, + BLI_mempool *pool) { int *fvi = NULL; BLI_array_declare(fvi); @@ -492,9 +492,9 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, plConvexHull hull; int i, count = 0; - const int num_input_verts = hull_input_vert_count(bm, op); + const int num_input_verts = hull_input_vert_count(op); - input_verts = hull_input_verts_copy(bm, op, num_input_verts); + input_verts = hull_input_verts_copy(op, num_input_verts); coords = hull_verts_for_bullet(input_verts, num_input_verts); hull = plConvexHullCompute(coords, num_input_verts); @@ -523,7 +523,7 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, fv[2] = hull_verts[fvi[j]]; hull_add_triangle(bm, hull_triangles, pool, - fv[0], fv[1], fv[2]); + fv[0], fv[1], fv[2]); } } } @@ -535,13 +535,13 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, } /* Check that there are at least three vertices in the input */ -static int hull_num_input_verts_is_ok(BMesh *bm, BMOperator *op) +static int hull_num_input_verts_is_ok(BMOperator *op) { BMOIter oiter; BMVert *v; int partial_num_verts = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { partial_num_verts++; if (partial_num_verts >= 3) break; @@ -559,14 +559,14 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) GHash *hull_triangles; /* Verify that at least three verts in the input */ - if (!hull_num_input_verts_is_ok(bm, op)) { + if (!hull_num_input_verts_is_ok(op)) { BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED, "Requires at least three vertices"); return; } /* Tag input elements */ - BMO_ITER (ele, &oiter, bm, op, "input", BM_ALL) { + BMO_ITER (ele, &oiter, op->slots_in, "input", BM_ALL) { BMO_elem_flag_enable(bm, ele, HULL_FLAG_INPUT); /* Mark all vertices as interior to begin with */ @@ -584,7 +584,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) hull_mark_interior_elements(bm, op, final_edges); /* Remove hull triangles covered by an existing face */ - if (BMO_slot_bool_get(op, "use_existing_faces")) { + if (BMO_slot_bool_get(op->slots_in, "use_existing_faces")) { hull_remove_overlapping(bm, hull_triangles, final_edges); hull_tag_holes(bm, op); @@ -603,23 +603,23 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) /* Output slot of input elements that ended up inside the hull * rather than part of it */ - BMO_slot_buffer_from_enabled_flag(bm, op, "interior_geom", BM_ALL, - HULL_FLAG_INTERIOR_ELE); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_interior.out", + BM_ALL_NOLOOP, HULL_FLAG_INTERIOR_ELE); /* Output slot of input elements that ended up inside the hull and * are are unused by other geometry. */ - BMO_slot_buffer_from_enabled_flag(bm, op, "unused_geom", BM_ALL, - HULL_FLAG_DEL); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_unused.out", + BM_ALL_NOLOOP, HULL_FLAG_DEL); /* Output slot of faces and edges that were in the input and on * the hull (useful for cases like bridging where you want to * delete some input geometry) */ - BMO_slot_buffer_from_enabled_flag(bm, op, "holes_geom", BM_ALL, - HULL_FLAG_HOLE); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_holes.out", + BM_ALL_NOLOOP, HULL_FLAG_HOLE); /* Output slot of all hull vertices, faces, and edges */ - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, - HULL_FLAG_OUTPUT_GEOM); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", + BM_ALL_NOLOOP, HULL_FLAG_OUTPUT_GEOM); } #endif /* WITH_BULLET */ diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 132d7050b31..cef1181f63b 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -92,13 +92,13 @@ static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l) void bmo_inset_exec(BMesh *bm, BMOperator *op) { - const int use_outset = BMO_slot_bool_get(op, "use_outset"); - const int use_boundary = BMO_slot_bool_get(op, "use_boundary") && (use_outset == FALSE); - const int use_even_offset = BMO_slot_bool_get(op, "use_even_offset"); + const int use_outset = BMO_slot_bool_get(op->slots_in, "use_outset"); + const int use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == FALSE); + const int use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); const int use_even_boundry = use_even_offset; /* could make own option */ - const int use_relative_offset = BMO_slot_bool_get(op, "use_relative_offset"); - const float thickness = BMO_slot_float_get(op, "thickness"); - const float depth = BMO_slot_float_get(op, "depth"); + const int use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); + const float thickness = BMO_slot_float_get(op->slots_in, "thickness"); + const float depth = BMO_slot_float_get(op->slots_in, "depth"); int edge_info_len = 0; @@ -113,11 +113,11 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) if (use_outset == FALSE) { BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_enable(bm, op, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); } else { BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_disable(bm, op, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); } /* first count all inset edges we will split */ @@ -181,7 +181,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) if (es->e_new == es->e_old) { /* happens on boundary edges */ /* take care here, we're creating this double edge which _must_ have its verts replaced later on */ - es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, FALSE); + es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, 0); } /* store index back to original in 'edge_info' */ @@ -205,7 +205,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) v1 = BM_vert_create(bm, tvec, NULL); v2 = BM_vert_create(bm, tvec, NULL); madd_v3_v3fl(v2->co, es->no, 0.1f); - BM_edge_create(bm, v1, v2, NULL, FALSE); + BM_edge_create(bm, v1, v2, NULL, 0); } #endif @@ -477,11 +477,48 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) /* copy for loop data, otherwise UV's and vcols are no good. * tiny speedup here we could be more clever and copy from known adjacent data * also - we could attempt to interpolate the loop data, this would be much slower but more useful too */ +#if 0 + /* don't use this because face boundaries have no adjacent loops and won't be filled in. + * instead copy from the opposite side with the code below */ BM_face_copy_shared(bm, f); +#else + { + /* 2 inner loops on the edge between the new face and the original */ + BMLoop *l_a; + BMLoop *l_b; + BMLoop *l_a_other; + BMLoop *l_b_other; + + l_a = BM_FACE_FIRST_LOOP(f); + l_b = l_a->next; + + /* we know this side has a radial_next because of the order of created verts in the quad */ + l_a_other = BM_edge_other_loop(l_a->e, l_a); + l_b_other = BM_edge_other_loop(l_a->e, l_b); + BM_elem_attrs_copy(bm, bm, l_a_other, l_a); + BM_elem_attrs_copy(bm, bm, l_b_other, l_b); + + /* step around to the opposite side of the quad - warning, this may have no other edges! */ + l_a = l_a->next->next; + l_b = l_a->next; + if (!BM_edge_is_boundary(l_a->e)) { + /* same as above */ + l_a_other = BM_edge_other_loop(l_a->e, l_a); + l_b_other = BM_edge_other_loop(l_a->e, l_b); + BM_elem_attrs_copy(bm, bm, l_a_other, l_a); + BM_elem_attrs_copy(bm, bm, l_b_other, l_b); + } + else { /* boundary edges have no useful data to copy from, use opposite side of face */ + /* swap a<->b intentionally */ + BM_elem_attrs_copy(bm, bm, l_a_other, l_b); + BM_elem_attrs_copy(bm, bm, l_b_other, l_a); + } + } +#endif } /* we could flag new edges/verts too, is it useful? */ - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW); /* cheap feature to add depth to the inset */ if (depth != 0.0f) { @@ -514,7 +551,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE); /* tag face verts */ - BMO_ITER (f, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) { BM_elem_flag_enable(v, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 3dbc0d0a5eb..1e18a83a0a0 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -204,16 +204,16 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMEdge *e; BLI_array_declare(jedges); JoinEdge *jedges = NULL; - int do_sharp = BMO_slot_bool_get(op, "cmp_sharp"); - int do_uv = BMO_slot_bool_get(op, "cmp_uvs"); + int do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp"); + int do_uv = BMO_slot_bool_get(op->slots_in, "cmp_uvs"); int do_tf = do_uv; /* texture face, make make its own option eventually */ - int do_vcol = BMO_slot_bool_get(op, "cmp_vcols"); - int do_mat = BMO_slot_bool_get(op, "cmp_materials"); - float limit = BMO_slot_float_get(op, "limit"); + int do_vcol = BMO_slot_bool_get(op->slots_in, "cmp_vcols"); + int do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials"); + float limit = BMO_slot_float_get(op->slots_in, "limit"); int i, totedge; /* flag all edges of all input face */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BMO_elem_flag_enable(bm, f, FACE_INPUT); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BMO_elem_flag_enable(bm, l->e, EDGE_MARK); diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index c4b988ae82d..4b897a24c8a 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -53,9 +53,9 @@ void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) { - Object *ob = BMO_slot_ptr_get(op, "object"); - Mesh *me = BMO_slot_ptr_get(op, "mesh"); - int set_key = BMO_slot_bool_get(op, "set_shapekey"); + Object *ob = BMO_slot_ptr_get(op->slots_in, "object"); + Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh"); + int set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey"); BM_mesh_bm_from_me(bm, me, set_key, ob->shapenr); @@ -66,20 +66,20 @@ void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) void bmo_object_load_bmesh_exec(BMesh *bm, BMOperator *op) { - Object *ob = BMO_slot_ptr_get(op, "object"); + Object *ob = BMO_slot_ptr_get(op->slots_in, "object"); /* Scene *scene = BMO_slot_ptr_get(op, "scene"); */ Mesh *me = ob->data; BMO_op_callf(bm, op->flag, - "bmesh_to_mesh mesh=%p object=%p notessellation=%b", + "bmesh_to_mesh mesh=%p object=%p skip_tessface=%b", me, ob, TRUE); } void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) { - Mesh *me = BMO_slot_ptr_get(op, "mesh"); + Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh"); /* Object *ob = BMO_slot_ptr_get(op, "object"); */ - int dotess = !BMO_slot_bool_get(op, "notessellation"); + int dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface"); BM_mesh_bm_to_me(bm, me, dotess); } diff --git a/source/blender/bmesh/operators/bmo_mirror.c b/source/blender/bmesh/operators/bmo_mirror.c index c6b228b988e..61b061dd21f 100644 --- a/source/blender/bmesh/operators/bmo_mirror.c +++ b/source/blender/bmesh/operators/bmo_mirror.c @@ -50,27 +50,28 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) float mtx[4][4]; float imtx[4][4]; float scale[3] = {1.0f, 1.0f, 1.0f}; - float dist = BMO_slot_float_get(op, "mergedist"); + float dist = BMO_slot_float_get(op->slots_in, "merge_dist"); int i, ototvert /*, ototedge */; - int axis = BMO_slot_int_get(op, "axis"); - int mirroru = BMO_slot_bool_get(op, "mirror_u"); - int mirrorv = BMO_slot_bool_get(op, "mirror_v"); + int axis = BMO_slot_int_get(op->slots_in, "axis"); + int mirroru = BMO_slot_bool_get(op->slots_in, "mirror_u"); + int mirrorv = BMO_slot_bool_get(op->slots_in, "mirror_v"); + BMOpSlot *slot_targetmap; ototvert = bm->totvert; /* ototedge = bm->totedge; */ /* UNUSED */ - BMO_slot_mat4_get(op, "mat", mtx); + BMO_slot_mat4_get(op->slots_in, "matrix", mtx); invert_m4_m4(imtx, mtx); BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%s", op, "geom"); BMO_op_exec(bm, &dupeop); - BMO_slot_buffer_flag_enable(bm, &dupeop, "newout", BM_ALL, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, dupeop.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW); /* create old -> new mappin */ i = 0; /* v2 = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); */ /* UNUSED */ - BMO_ITER (v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { BLI_array_grow_one(vmap); vmap[i] = v; /* v2 = BM_iter_step(&iter); */ /* UNUSED */ @@ -80,16 +81,18 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) /* feed old data to transform bmo */ scale[axis] = -1.0f; - BMO_op_callf(bm, op->flag, "transform verts=%fv mat=%m4", ELE_NEW, mtx); + BMO_op_callf(bm, op->flag, "transform verts=%fv matrix=%m4", ELE_NEW, mtx); BMO_op_callf(bm, op->flag, "scale verts=%fv vec=%v", ELE_NEW, scale); - BMO_op_callf(bm, op->flag, "transform verts=%fv mat=%m4", ELE_NEW, imtx); + BMO_op_callf(bm, op->flag, "transform verts=%fv matrix=%m4", ELE_NEW, imtx); BMO_op_init(bm, &weldop, op->flag, "weld_verts"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); for (i = 0; i < ototvert; i++) { - if (ABS(v->co[axis]) <= dist) { - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", vmap[i], v); + if (fabsf(v->co[axis]) <= dist) { + BMO_slot_map_elem_insert(&weldop, slot_targetmap, vmap[i], v); } v = BM_iter_step(&iter); } @@ -101,7 +104,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) int totlayer; BMIter liter; - BMO_ITER (f, &siter, bm, &dupeop, "newout", BM_FACE) { + BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV); for (i = 0; i < totlayer; i++) { @@ -120,7 +123,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &weldop); BMO_op_finish(bm, &dupeop); - BMO_slot_buffer_from_enabled_flag(bm, op, "newout", BM_ALL, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW); BLI_array_free(vmap); BLI_array_free(emap); diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index d7b163cb760..c582f710f43 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -227,16 +227,17 @@ static signed char monkeyf[250][4] = { void bmo_create_grid_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "size"); + const int tot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments")); + const int seg = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments")); + BMOperator bmop, prevop; BMVert *eve, *preveve; BMEdge *e; - float vec[3], mat[4][4], phi, phid, dia = BMO_slot_float_get(op, "size"); - int a, tot = BMO_slot_int_get(op, "xsegments"), seg = BMO_slot_int_get(op, "ysegments"); + float vec[3], mat[4][4], phi, phid; + int a; - if (tot < 2) tot = 2; - if (seg < 2) seg = 2; - - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); /* one segment first: the X axis */ phi = 1.0f; @@ -247,11 +248,11 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) vec[2] = 0.0f; mul_m4_v3(mat, vec); - eve = BM_vert_create(bm, vec, NULL); + eve = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, eve, VERT_MARK); if (a != 0) { - e = BM_edge_create(bm, preveve, eve, NULL, TRUE); + e = BM_edge_create(bm, preveve, eve, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, EDGE_ORIG); } @@ -267,39 +268,43 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) for (a = 0; a < seg - 1; a++) { if (a) { - BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%s", &prevop, "geomout"); + BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out"); BMO_op_exec(bm, &bmop); BMO_op_finish(bm, &prevop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); } else { BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%fe", EDGE_ORIG); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); } - BMO_op_callf(bm, op->flag, "translate vec=%v verts=%s", vec, &bmop, "geomout"); + BMO_op_callf(bm, op->flag, "translate vec=%v verts=%S", vec, &bmop, "geom.out"); prevop = bmop; } if (a) BMO_op_finish(bm, &bmop); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "diameter"); + const int seg = BMO_slot_int_get(op->slots_in, "u_segments"); + const int tot = BMO_slot_int_get(op->slots_in, "v_segments"); + BMOperator bmop, prevop; BMVert *eve, *preveve; BMEdge *e; BMIter iter; float vec[3], mat[4][4], cmat[3][3], phi, q[4]; - float phid, dia = BMO_slot_float_get(op, "diameter"); - int a, seg = BMO_slot_int_get(op, "segments"), tot = BMO_slot_int_get(op, "revolutions"); + float phid; + int a; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); phid = 2.0f * (float)M_PI / tot; /* phi = 0.25f * (float)M_PI; */ /* UNUSED */ @@ -312,11 +317,11 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) vec[0] = -dia * sinf(phi); vec[1] = 0.0; vec[2] = dia * cosf(phi); - eve = BM_vert_create(bm, vec, NULL); + eve = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, eve, VERT_MARK); if (a != 0) { - e = BM_edge_create(bm, preveve, eve, NULL, FALSE); + e = BM_edge_create(bm, preveve, eve, NULL, 0); BMO_elem_flag_enable(bm, e, EDGE_ORIG); } @@ -333,7 +338,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) for (a = 0; a < seg; a++) { if (a) { - BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%s", &prevop, "geomout"); + BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out"); BMO_op_exec(bm, &bmop); BMO_op_finish(bm, &prevop); } @@ -342,8 +347,8 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &bmop); } - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); - BMO_op_callf(bm, op->flag, "rotate cent=%v mat=%m3 verts=%s", vec, cmat, &bmop, "geomout"); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); + BMO_op_callf(bm, op->flag, "rotate cent=%v matrix=%m3 verts=%S", vec, cmat, &bmop, "geom.out"); prevop = bmop; } @@ -375,31 +380,34 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "diameter"); + const float dia_div = dia / 200.0f; + const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions"); + BMVert *eva[12]; BMVert *v; BMIter liter; BMIter viter; BMLoop *l; float vec[3], mat[4][4] /* , phi, phid */; - float dia = BMO_slot_float_get(op, "diameter"); - int a, subdiv = BMO_slot_int_get(op, "subdivisions"); + int a; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); /* phid = 2.0f * (float)M_PI / subdiv; */ /* UNUSED */ /* phi = 0.25f * (float)M_PI; */ /* UNUSED */ - dia /= 200.0f; + for (a = 0; a < 12; a++) { - vec[0] = dia * icovert[a][0]; - vec[1] = dia * icovert[a][1]; - vec[2] = dia * icovert[a][2]; - eva[a] = BM_vert_create(bm, vec, NULL); + vec[0] = dia_div * icovert[a][0]; + vec[1] = dia_div * icovert[a][1]; + vec[2] = dia_div * icovert[a][2]; + eva[a] = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, eva[a], VERT_MARK); } @@ -421,22 +429,20 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, eftemp, FACE_MARK); } - dia *= 200.0f; - if (subdiv > 1) { BMOperator bmop; BMO_op_initf(bm, &bmop, op->flag, "subdivide_edges edges=%fe " "smooth=%f " - "numcuts=%i " - "use_gridfill=%b use_sphere=%b", + "cuts=%i " + "use_grid_fill=%b use_sphere=%b", EDGE_MARK, dia, (1 << (subdiv - 1)) - 1, TRUE, TRUE); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_EDGE, EDGE_MARK); BMO_op_finish(bm, &bmop); } @@ -447,7 +453,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) @@ -457,19 +463,19 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) float mat[4][4]; int i; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); for (i = 0; i < monkeynv; i++) { float v[3]; v[0] = (monkeyv[i][0] + 127) / 128.0, v[1] = monkeyv[i][1] / 128.0, v[2] = monkeyv[i][2] / 128.0; - tv[i] = BM_vert_create(bm, v, NULL); + tv[i] = BM_vert_create(bm, v, NULL, 0); BMO_elem_flag_enable(bm, tv[i], VERT_MARK); tv[monkeynv + i] = (fabsf(v[0] = -v[0]) < 0.001f) ? tv[i] : - (eve = BM_vert_create(bm, v, NULL), mul_m4_v3(mat, eve->co), eve); + (eve = BM_vert_create(bm, v, NULL, 0), mul_m4_v3(mat, eve->co), eve); BMO_elem_flag_enable(bm, tv[monkeynv + i], VERT_MARK); @@ -494,24 +500,25 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) MEM_freeN(tv); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_circle_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "diameter"); + const int segs = BMO_slot_int_get(op->slots_in, "segments"); + const int cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); + const int cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); + BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL; float vec[3], mat[4][4], phi, phid; - float dia = BMO_slot_float_get(op, "diameter"); - int segs = BMO_slot_int_get(op, "segments"); - int cap_ends = BMO_slot_bool_get(op, "cap_ends"); - int cap_tris = BMO_slot_bool_get(op, "cap_tris"); int a; if (!segs) return; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); phid = 2.0f * (float)M_PI / segs; phi = 0; @@ -520,7 +527,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) zero_v3(vec); mul_m4_v3(mat, vec); - cent1 = BM_vert_create(bm, vec, NULL); + cent1 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, cent1, VERT_MARK); } @@ -530,12 +537,12 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) vec[1] = dia * cosf(phi); vec[2] = 0.0f; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL); + v1 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v1, VERT_MARK); if (lastv1) - BM_edge_create(bm, v1, lastv1, NULL, FALSE); + BM_edge_create(bm, v1, lastv1, NULL, 0); if (a && cap_ends) { BMFace *f; @@ -553,7 +560,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) if (!a) return; - BM_edge_create(bm, lastv1, firstv1, NULL, FALSE); + BM_edge_create(bm, firstv1, lastv1, NULL, 0); if (cap_ends) { BMFace *f; @@ -566,25 +573,25 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW); } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_cone_exec(BMesh *bm, BMOperator *op) { BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2; float vec[3], mat[4][4], phi, phid; - float dia1 = BMO_slot_float_get(op, "diameter1"); - float dia2 = BMO_slot_float_get(op, "diameter2"); - float depth = BMO_slot_float_get(op, "depth"); - int segs = BMO_slot_int_get(op, "segments"); - int cap_ends = BMO_slot_bool_get(op, "cap_ends"); - int cap_tris = BMO_slot_bool_get(op, "cap_tris"); + float dia1 = BMO_slot_float_get(op->slots_in, "diameter1"); + float dia2 = BMO_slot_float_get(op->slots_in, "diameter2"); + float depth = BMO_slot_float_get(op->slots_in, "depth"); + int segs = BMO_slot_int_get(op->slots_in, "segments"); + int cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); + int cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); int a; if (!segs) return; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); phid = 2.0f * (float)M_PI / segs; phi = 0; @@ -595,13 +602,13 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) vec[2] = -depth; mul_m4_v3(mat, vec); - cent1 = BM_vert_create(bm, vec, NULL); + cent1 = BM_vert_create(bm, vec, NULL, 0); vec[0] = vec[1] = 0.0f; vec[2] = depth; mul_m4_v3(mat, vec); - cent2 = BM_vert_create(bm, vec, NULL); + cent2 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, cent1, VERT_MARK); BMO_elem_flag_enable(bm, cent2, VERT_MARK); @@ -612,13 +619,13 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) vec[1] = dia1 * cosf(phi); vec[2] = -depth; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL); + v1 = BM_vert_create(bm, vec, NULL, 0); vec[0] = dia2 * sinf(phi); vec[1] = dia2 * cosf(phi); vec[2] = depth; mul_m4_v3(mat, vec); - v2 = BM_vert_create(bm, vec, NULL); + v2 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v1, VERT_MARK); BMO_elem_flag_enable(bm, v2, VERT_MARK); @@ -662,15 +669,15 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, FALSE); BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_cube_exec(BMesh *bm, BMOperator *op) { BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8; - float vec[3], mat[4][4], off = BMO_slot_float_get(op, "size") / 2.0f; + float vec[3], mat[4][4], off = BMO_slot_float_get(op->slots_in, "size") / 2.0f; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); if (!off) off = 0.5f; @@ -678,56 +685,56 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) vec[1] = -off; vec[2] = -off; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL); + v1 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v1, VERT_MARK); vec[0] = -off; vec[1] = off; vec[2] = -off; mul_m4_v3(mat, vec); - v2 = BM_vert_create(bm, vec, NULL); + v2 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v2, VERT_MARK); vec[0] = off; vec[1] = off; vec[2] = -off; mul_m4_v3(mat, vec); - v3 = BM_vert_create(bm, vec, NULL); + v3 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v3, VERT_MARK); vec[0] = off; vec[1] = -off; vec[2] = -off; mul_m4_v3(mat, vec); - v4 = BM_vert_create(bm, vec, NULL); + v4 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v4, VERT_MARK); vec[0] = -off; vec[1] = -off; vec[2] = off; mul_m4_v3(mat, vec); - v5 = BM_vert_create(bm, vec, NULL); + v5 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v5, VERT_MARK); vec[0] = -off; vec[1] = off; vec[2] = off; mul_m4_v3(mat, vec); - v6 = BM_vert_create(bm, vec, NULL); + v6 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v6, VERT_MARK); vec[0] = off; vec[1] = off; vec[2] = off; mul_m4_v3(mat, vec); - v7 = BM_vert_create(bm, vec, NULL); + v7 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v7, VERT_MARK); vec[0] = off; vec[1] = -off; vec[2] = off; mul_m4_v3(mat, vec); - v8 = BM_vert_create(bm, vec, NULL); + v8 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v8, VERT_MARK); /* the four sides */ @@ -740,5 +747,5 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, FALSE); BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, FALSE); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index ea6cd747037..87e26f11d4b 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -36,7 +36,7 @@ #include "intern/bmesh_operators_private.h" /* own include */ -static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) +static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot *slot_targetmap) { BMIter liter; BMLoop *l; @@ -44,7 +44,7 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) int split = FALSE; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", l->v); + v2 = BMO_slot_map_elem_get(slot_targetmap, l->v); /* ok: if v2 is NULL (e.g. not in the map) then it's * a target vert, otherwise it's a double */ if ((v2 && BM_vert_in_face(f, v2)) && @@ -61,8 +61,8 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) BMLoop *nl; BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL, FALSE); - remdoubles_splitface(f, bm, op); - remdoubles_splitface(f2, bm, op); + remdoubles_splitface(f, bm, op, slot_targetmap); + remdoubles_splitface(f2, bm, op, slot_targetmap); } } @@ -106,10 +106,11 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) BLI_array_declare(loops); BMFace *f, *f2; int a, b; + BMOpSlot *slot_targetmap = BMO_slot_get(op->slots_in, "targetmap"); /* mark merge verts for deletion */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if ((v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v))) { + if ((v2 = BMO_slot_map_elem_get(slot_targetmap, v))) { BMO_elem_flag_enable(bm, v, ELE_DEL); /* merge the vertex flags, else we get randomly selected/unselected verts */ @@ -120,13 +121,13 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) /* check if any faces are getting their own corners merged * together, split face if so */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - remdoubles_splitface(f, bm, op); + remdoubles_splitface(f, bm, op, slot_targetmap); } BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e->v1, ELE_DEL) || BMO_elem_flag_test(bm, e->v2, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", e->v1); - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", e->v2); + v = BMO_slot_map_elem_get(slot_targetmap, e->v1); + v2 = BMO_slot_map_elem_get(slot_targetmap, e->v2); if (!v) v = e->v1; if (!v2) v2 = e->v2; @@ -135,7 +136,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, e, EDGE_COL); } else if (!BM_edge_exists(v, v2)) { - BM_edge_create(bm, v, v2, e, TRUE); + BM_edge_create(bm, v, v2, e, BM_CREATE_NO_DOUBLE); } BMO_elem_flag_enable(bm, e, ELE_DEL); @@ -174,10 +175,10 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) v = l->v; v2 = l->next->v; if (BMO_elem_flag_test(bm, v, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", v); + v = BMO_slot_map_elem_get(slot_targetmap, v); } if (BMO_elem_flag_test(bm, v2, ELE_DEL)) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v2); + v2 = BMO_slot_map_elem_get(slot_targetmap, v2); } e2 = v != v2 ? BM_edge_exists(v, v2) : NULL; @@ -207,13 +208,13 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) v2 = loops[1]->v; if (BMO_elem_flag_test(bm, v, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", v); + v = BMO_slot_map_elem_get(slot_targetmap, v); } if (BMO_elem_flag_test(bm, v2, ELE_DEL)) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v2); + v2 = BMO_slot_map_elem_get(slot_targetmap, v2); } - f2 = BM_face_create_ngon(bm, v, v2, edges, a, TRUE); + f2 = BM_face_create_ngon(bm, v, v2, edges, a, BM_CREATE_NO_DOUBLE); if (f2 && (f2 != f)) { BM_elem_attrs_copy(bm, bm, f, f2); @@ -257,19 +258,19 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMIter iter; - BMVert *v, *snapv; + BMVert *v, *vert_snap; BMLoop *l, *firstl = NULL; float fac; int i, tot; - snapv = BMO_iter_new(&siter, bm, op, "snapv", BM_VERT); - tot = BM_vert_face_count(snapv); + vert_snap = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_snap")); + tot = BM_vert_face_count(vert_snap); if (!tot) return; fac = 1.0f / tot; - BM_ITER_ELEM (l, &iter, snapv, BM_LOOPS_OF_VERT) { + BM_ITER_ELEM (l, &iter, vert_snap, BM_LOOPS_OF_VERT) { if (!firstl) { firstl = l; } @@ -290,7 +291,7 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { if (l == firstl) { continue; @@ -318,7 +319,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op) type = bm->ldata.layers[i].type; CustomData_data_initminmax(type, &min, &max); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i); CustomData_data_dominmax(type, block, &min, &max); @@ -329,7 +330,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op) CustomData_data_multiply(type, &max, 0.5f); CustomData_data_add(type, &min, &max); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i); CustomData_data_copy_value(type, &min, block); @@ -342,21 +343,24 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op) { BMOperator weldop; BMOIter siter; - BMVert *v, *snapv = NULL; + BMVert *v, *vert_snap = NULL; float vec[3]; + BMOpSlot *slot_targetmap; - BMO_slot_vec_get(op, "merge_co", vec); + BMO_slot_vec_get(op->slots_in, "merge_co", vec); //BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { - if (!snapv) { - snapv = v; - copy_v3_v3(snapv->co, vec); + + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { + if (!vert_snap) { + vert_snap = v; + copy_v3_v3(vert_snap->co, vec); } else { - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", v, snapv); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, v, vert_snap); } } @@ -373,11 +377,13 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BLI_array_declare(edges); float min[3], max[3], center[3]; int i, tot; + BMOpSlot *slot_targetmap; BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); BMO_op_init(bm, &weldop, op->flag, "weld_verts"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); BMW_init(&walker, bm, BMW_SHELL, BMW_MASK_NOP, EDGE_MARK, BMW_MASK_NOP, @@ -408,9 +414,9 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) copy_v3_v3(edges[i]->v2->co, center); if (edges[i]->v1 != edges[0]->v1) - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", edges[i]->v1, edges[0]->v1); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v1, edges[0]->v1); if (edges[i]->v2 != edges[0]->v1) - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", edges[i]->v2, edges[0]->v1); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1); } } @@ -436,7 +442,7 @@ static void bmo_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer) /* clear all short flags */ BMO_mesh_flag_disable_all(bm, op, BM_ALL, (1 << 16) - 1); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); BMW_init(&walker, bm, BMW_LOOPDATA_ISLAND, BMW_MASK_NOP, EDGE_MARK, BMW_MASK_NOP, @@ -486,31 +492,32 @@ void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op) } } -static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, const char *targetmapname) +static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, + BMOperator *optarget, BMOpSlot *optarget_slot) { BMVert **verts; int verts_len; int i, j, keepvert = 0; - const float dist = BMO_slot_float_get(op, "dist"); + const float dist = BMO_slot_float_get(op->slots_in, "dist"); const float dist3 = dist * 3.0f; /* Test whether keep_verts arg exists and is non-empty */ - if (BMO_slot_exists(op, "keep_verts")) { + if (BMO_slot_exists(op->slots_in, "keep_verts")) { BMOIter oiter; - keepvert = BMO_iter_new(&oiter, bm, op, "keep_verts", BM_VERT) != NULL; + keepvert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL; } /* get the verts as an array we can sort */ - verts = BMO_slot_as_arrayN(op, "verts", &verts_len); + verts = BMO_slot_as_arrayN(op->slots_in, "verts", &verts_len); /* sort by vertex coordinates added together */ qsort(verts, verts_len, sizeof(BMVert *), vergaverco); /* Flag keep_verts */ if (keepvert) { - BMO_slot_buffer_flag_enable(bm, op, "keep_verts", BM_VERT, VERT_KEEP); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "keep_verts", BM_VERT, VERT_KEEP); } for (i = 0; i < verts_len; i++) { @@ -547,7 +554,7 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *opt BMO_elem_flag_enable(bm, v_other, VERT_DOUBLE); BMO_elem_flag_enable(bm, v_check, VERT_TARGET); - BMO_slot_map_ptr_insert(bm, optarget, targetmapname, v_other, v_check); + BMO_slot_map_elem_insert(optarget, optarget_slot, v_other, v_check); } } } @@ -558,9 +565,12 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *opt void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op) { BMOperator weldop; + BMOpSlot *slot_targetmap; BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - bmesh_find_doubles_common(bm, op, &weldop, "targetmap"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + bmesh_find_doubles_common(bm, op, + &weldop, slot_targetmap); BMO_op_exec(bm, &weldop); BMO_op_finish(bm, &weldop); } @@ -568,7 +578,10 @@ void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op) void bmo_find_doubles_exec(BMesh *bm, BMOperator *op) { - bmesh_find_doubles_common(bm, op, op, "targetmapout"); + BMOpSlot *slot_targetmap_out; + slot_targetmap_out = BMO_slot_get(op->slots_out, "targetmap.out"); + bmesh_find_doubles_common(bm, op, + op, slot_targetmap_out); } void bmo_automerge_exec(BMesh *bm, BMOperator *op) @@ -580,7 +593,7 @@ void bmo_automerge_exec(BMesh *bm, BMOperator *op) /* The "verts" input sent to this op is the set of verts that * can be merged away into any other verts. Mark all other verts * as VERT_KEEP. */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_IN); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_IN); BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { if (!BMO_elem_flag_test(bm, v, VERT_IN)) { BMO_elem_flag_enable(bm, v, VERT_KEEP); @@ -590,12 +603,14 @@ void bmo_automerge_exec(BMesh *bm, BMOperator *op) /* Search for doubles among all vertices, but only merge non-VERT_KEEP * vertices into VERT_KEEP vertices. */ BMO_op_initf(bm, &findop, op->flag, "find_doubles verts=%av keep_verts=%fv", VERT_KEEP); - BMO_slot_copy(op, &findop, "dist", "dist"); + BMO_slot_copy(op, slots_in, "dist", + &findop, slots_in, "dist"); BMO_op_exec(bm, &findop); /* weld the vertices */ BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - BMO_slot_copy(&findop, &weldop, "targetmapout", "targetmap"); + BMO_slot_copy(&findop, slots_out, "targetmap.out", + &weldop, slots_in, "targetmap"); BMO_op_exec(bm, &weldop); BMO_op_finish(bm, &findop); diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c index df03e50d2c4..548e1adf17d 100644 --- a/source/blender/bmesh/operators/bmo_similar.c +++ b/source/blender/bmesh/operators/bmo_similar.c @@ -103,10 +103,10 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) SimSel_FaceExt *f_ext = NULL; int *indices = NULL; float t_no[3]; /* temporary normal */ - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); const float thresh_radians = thresh * (float)M_PI; - const int compare = BMO_slot_int_get(op, "compare"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ float delta_fl; @@ -121,7 +121,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) * so the overall complexity will be less than $O(mn)$ where is the total number of selected faces, * and n is the total number of faces */ - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, fs, FACE_MARK)) { /* is this really needed ? */ BMO_elem_flag_enable(bm, fs, FACE_MARK); num_sels++; @@ -256,7 +256,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); /* transfer all marked faces to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_MARK); #undef FACE_MARK } @@ -299,9 +299,9 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) float angle; int num_sels = 0, num_total = 0; - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - const int compare = BMO_slot_int_get(op, "compare"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ float delta_fl; @@ -324,7 +324,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) num_total = BM_mesh_elem_count(bm, BM_EDGE); /* iterate through all selected edges and mark them */ - BMO_ITER (es, &es_iter, bm, op, "edges", BM_EDGE) { + BMO_ITER (es, &es_iter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, es, EDGE_MARK); num_sels++; } @@ -474,7 +474,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); /* transfer all marked edges to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_MARK); #undef EDGE_MARK } @@ -507,10 +507,10 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) SimSel_VertExt *v_ext = NULL; int *indices = NULL; int num_total = 0, num_sels = 0, i = 0, idx = 0; - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); const float thresh_radians = thresh * (float)M_PI; - const int compare = BMO_slot_int_get(op, "compare"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ // float delta_fl; @@ -519,7 +519,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) num_total = BM_mesh_elem_count(bm, BM_VERT); /* iterate through all selected edges and mark them */ - BMO_ITER (vs, &vs_iter, bm, op, "verts", BM_VERT) { + BMO_ITER (vs, &vs_iter, op->slots_in, "verts", BM_VERT) { BMO_elem_flag_enable(bm, vs, VERT_MARK); num_sels++; } @@ -608,7 +608,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); MEM_freeN(v_ext); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); #undef VERT_MARK } diff --git a/source/blender/bmesh/operators/bmo_slide.c b/source/blender/bmesh/operators/bmo_slide.c index 6db76119205..ea9f9bf9eba 100644 --- a/source/blender/bmesh/operators/bmo_slide.c +++ b/source/blender/bmesh/operators/bmo_slide.c @@ -53,11 +53,10 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) int selected_edges = 0; /* Get slide amount */ - const float distance_t = BMO_slot_float_get(op, "distance_t"); + const float factor = BMO_slot_float_get(op->slots_in, "factor"); /* Get start vertex */ - vertex = BMO_iter_new(&oiter, bm, op, "vert", BM_VERT); - + vertex = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert")); if (!vertex) { if (G.debug & G_DEBUG) { @@ -67,15 +66,13 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) return; } + /* BMESH_TODO - this is odd, it only uses one edge, why take a list at all? */ /* Count selected edges */ - BMO_ITER (h, &oiter, bm, op, "edge", BM_VERT | BM_EDGE) { - switch (h->htype) { - case BM_EDGE: - selected_edges++; - /* Mark all selected edges (cast BMHeader->BMEdge) */ - BMO_elem_flag_enable(bm, (BMElemF *)h, EDGE_MARK); - break; - } + BMO_ITER (h, &oiter, op->slots_in, "edges", BM_EDGE) { + selected_edges++; + /* Mark all selected edges (cast BMHeader->BMEdge) */ + BMO_elem_flag_enable(bm, (BMElemF *)h, EDGE_MARK); + break; } /* Only allow sliding if an edge is selected */ @@ -104,11 +101,11 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, vertex, VERT_MARK); /* Interpolate */ - interp_v3_v3v3(vertex->co, vertex->co, other->co, distance_t); + interp_v3_v3v3(vertex->co, vertex->co, other->co, factor); } /* Return the new edge. The same previously marked with VERT_MARK */ - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); return; } diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 51b9adb5de3..4a367a8fd6f 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -43,8 +43,8 @@ #include "intern/bmesh_operators_private.h" /* own include */ -#define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f -#define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f +// #define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f /* UNUSED */ +// #define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f /* UNUSED */ #define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f #define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15f @@ -78,8 +78,8 @@ static void delete_laplacian_system(LaplacianSystem *sys); static void delete_void_pointer(void *data); static void fill_laplacian_matrix(LaplacianSystem *sys); static void memset_laplacian_system(LaplacianSystem *sys, int val); -static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation); -static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez); +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume); +static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez); static void delete_void_pointer(void *data) { @@ -455,7 +455,7 @@ static float compute_volume(BMesh *bm) return fabs(vol); } -static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez) +static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez) { float beta; BMOIter siter; @@ -463,9 +463,9 @@ static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float ven if (vend != 0.0f) { beta = pow(vini / vend, 1.0f / 3.0f); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { if (usex) { - v->co[0] *= beta; + v->co[0] *= beta; } if (usey) { v->co[1] *= beta; @@ -478,7 +478,7 @@ static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float ven } } -static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation) +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume) { int m_vertex_id; float leni, lene; @@ -509,10 +509,10 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez } } - if (volumepreservation) { + if (preserve_volume) { vini = compute_volume(sys->bm); } - BMO_ITER (v, &siter, sys->bm, sys->op, "verts", BM_VERT) { + BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); if (sys->zerola[m_vertex_id] == 0) { if (usex) { @@ -526,9 +526,9 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez } } } - if (volumepreservation) { + if (preserve_volume) { vend = compute_volume(sys->bm); - volume_preservation(sys->bm, sys->op, vini, vend, usex, usey, usez); + volume_preservation(sys->op, vini, vend, usex, usey, usez); } } @@ -537,13 +537,14 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) { int i; int m_vertex_id; - int usex, usey, usez, volumepreservation; + int usex, usey, usez, preserve_volume; float lambda, lambda_border; float w; BMOIter siter; BMVert *v; LaplacianSystem *sys; + if (bm->totface == 0) return; sys = init_laplacian_system(bm->totedge, bm->totface, bm->totvert); if (!sys) return; sys->bm = bm; @@ -552,13 +553,13 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) memset_laplacian_system(sys, 0); BM_mesh_elem_index_ensure(bm, BM_VERT); - lambda = BMO_slot_float_get(op, "lambda"); - lambda_border = BMO_slot_float_get(op, "lambda_border"); + lambda = BMO_slot_float_get(op->slots_in, "lambda"); + lambda_border = BMO_slot_float_get(op->slots_in, "lambda_border"); sys->min_area = 0.00001f; - usex = BMO_slot_bool_get(op, "use_x"); - usey = BMO_slot_bool_get(op, "use_y"); - usez = BMO_slot_bool_get(op, "use_z"); - volumepreservation = BMO_slot_bool_get(op, "volume_preservation"); + usex = BMO_slot_bool_get(op->slots_in, "use_x"); + usey = BMO_slot_bool_get(op->slots_in, "use_y"); + usez = BMO_slot_bool_get(op->slots_in, "use_z"); + preserve_volume = BMO_slot_bool_get(op->slots_in, "preserve_volume"); nlNewContext(); @@ -573,7 +574,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) for (i = 0; i < bm->totvert; i++) { nlLockVariable(i); } - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); nlUnlockVariable(m_vertex_id); nlSetVariable(0, m_vertex_id, v->co[0]); @@ -583,7 +584,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) nlBegin(NL_MATRIX); init_laplacian_matrix(sys); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); nlRightHandSideAdd(0, m_vertex_id, v->co[0]); nlRightHandSideAdd(1, m_vertex_id, v->co[1]); @@ -612,7 +613,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE) ) { - validate_solution(sys, usex, usey, usez, volumepreservation); + validate_solution(sys, usex, usey, usez, preserve_volume); } delete_laplacian_system(sys); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 346daf830d0..7407eb4423a 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -165,7 +165,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar } /* apply the new difference to the rest of the shape keys, - * note that this doent take rotations into account, we _could_ support + * note that this dosn't take rotations into account, we _could_ support * this by getting the normals and coords for each shape key and * re-calculate the smooth value for each but this is quite involved. * for now its ok to simply apply the difference IMHO - campbell */ @@ -225,8 +225,9 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, BMVert *ev; float percent, percent2 = 0.0f; - if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) - percent = BMO_slot_map_float_get(bm, params->op, "edgepercents", edge); + if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) { + percent = BMO_slot_map_float_get(params->slot_edge_percents, edge); + } else { percent = 1.0f / (float)(totpoint + 1 - curpoint); percent2 = (float)(curpoint + 1) / (float)(totpoint + 1); @@ -714,21 +715,22 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BMFace *face; BLI_array_declare(verts); float smooth, fractal, along_normal; - int use_sphere, cornertype, use_singleedge, use_gridfill; + int use_sphere, cornertype, use_single_edge, use_grid_fill, use_only_quads; int skey, seed, i, j, matched, a, b, numcuts, totesel; - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, SUBD_SPLIT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); - numcuts = BMO_slot_int_get(op, "numcuts"); - seed = BMO_slot_int_get(op, "seed"); - smooth = BMO_slot_float_get(op, "smooth"); - fractal = BMO_slot_float_get(op, "fractal"); - along_normal = BMO_slot_float_get(op, "along_normal"); - cornertype = BMO_slot_int_get(op, "quadcornertype"); + numcuts = BMO_slot_int_get(op->slots_in, "cuts"); + seed = BMO_slot_int_get(op->slots_in, "seed"); + smooth = BMO_slot_float_get(op->slots_in, "smooth"); + fractal = BMO_slot_float_get(op->slots_in, "fractal"); + along_normal = BMO_slot_float_get(op->slots_in, "along_normal"); + cornertype = BMO_slot_int_get(op->slots_in, "quad_corner_type"); - use_singleedge = BMO_slot_bool_get(op, "use_singleedge"); - use_gridfill = BMO_slot_bool_get(op, "use_gridfill"); - use_sphere = BMO_slot_bool_get(op, "use_sphere"); + use_single_edge = BMO_slot_bool_get(op->slots_in, "use_single_edge"); + use_grid_fill = BMO_slot_bool_get(op->slots_in, "use_grid_fill"); + use_only_quads = BMO_slot_bool_get(op->slots_in, "use_only_quads"); + use_sphere = BMO_slot_bool_get(op->slots_in, "use_sphere"); BLI_srandom(seed); @@ -746,7 +748,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) break; } - if (use_singleedge) { + if (use_single_edge) { patterns[0] = &quad_1edge; patterns[2] = &tri_1edge; } @@ -755,7 +757,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) patterns[2] = NULL; } - if (use_gridfill) { + if (use_grid_fill) { patterns[3] = &quad_4edge; patterns[5] = &tri_3edge; } @@ -774,10 +776,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } /* first go through and tag edges */ - BMO_slot_buffer_from_enabled_flag(bm, op, "edges", BM_EDGE, SUBD_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); params.numcuts = numcuts; params.op = op; + params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents"); + params.slot_custom_patterns = BMO_slot_get(op->slots_in, "custom_patterns"); params.smooth = smooth; params.seed = seed; params.fractal = fractal; @@ -790,10 +794,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) params.off[1] = (float)BLI_drand() * 200.0f; params.off[2] = (float)BLI_drand() * 200.0f; - BMO_slot_map_to_flag(bm, op, "custompatterns", + BMO_slot_map_to_flag(bm, op->slots_in, "custom_patterns", BM_FACE, FACE_CUSTOMFILL); - BMO_slot_map_to_flag(bm, op, "edgepercents", + BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents", BM_EDGE, EDGE_PERCENT); @@ -801,6 +805,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BMEdge *e1 = NULL, *e2 = NULL; float vec1[3], vec2[3]; + /* skip non-quads if requested */ + if (use_only_quads && face->len != 4) + continue; + /* figure out which pattern to use */ BLI_array_empty(edges); @@ -825,7 +833,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } /* make sure the two edges have a valid angle to each other */ - if (totesel == 2 && BM_edge_share_vert_count(e1, e2)) { + if (totesel == 2 && BM_edge_share_vert_check(e1, e2)) { sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co); sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co); normalize_v3(vec1); @@ -837,8 +845,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } if (BMO_elem_flag_test(bm, face, FACE_CUSTOMFILL)) { - pat = BMO_slot_map_data_get(bm, op, - "custompatterns", face); + pat = BMO_slot_map_data_get(params.slot_custom_patterns, face); for (i = 0; i < pat->len; i++) { matched = 1; for (j = 0; j < pat->len; j++) { @@ -910,11 +917,11 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } } - einput = BMO_slot_get(op, "edges"); + einput = BMO_slot_get(op->slots_in, "edges"); /* go through and split edges */ for (i = 0; i < einput->len; i++) { - edge = ((BMEdge **)einput->data.p)[i]; + edge = einput->data.buf[i]; bm_subdivide_multicut(bm, edge, ¶ms, edge->v1, edge->v2); } @@ -1075,10 +1082,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_free(loops_split); BLI_array_free(loops); - BMO_slot_buffer_from_enabled_flag(bm, op, "outinner", BM_ALL, ELE_INNER); - BMO_slot_buffer_from_enabled_flag(bm, op, "outsplit", BM_ALL, ELE_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_inner.out", BM_ALL_NOLOOP, ELE_INNER); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, ELE_INNER | ELE_SPLIT | SUBD_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_INNER | ELE_SPLIT | SUBD_SPLIT); } /* editmesh-emulating function */ @@ -1086,7 +1093,8 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, float smooth, float fractal, float along_normal, int numcuts, int seltype, int cornertype, - const short use_singleedge, const short use_gridfill, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, int seed) { BMOperator op; @@ -1095,15 +1103,17 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BMO_op_initf(bm, &op, BMO_FLAG_DEFAULTS, "subdivide_edges edges=%he " "smooth=%f fractal=%f along_normal=%f " - "numcuts=%i " - "quadcornertype=%i " - "use_singleedge=%b use_gridfill=%b " + "cuts=%i " + "quad_corner_type=%i " + "use_single_edge=%b use_grid_fill=%b " + "use_only_quads=%b " "seed=%i", edge_hflag, smooth, fractal, along_normal, numcuts, cornertype, - use_singleedge, use_gridfill, + use_single_edge, use_grid_fill, + use_only_quads, seed); BMO_op_exec(bm, &op); @@ -1112,7 +1122,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BMOIter iter; BMElem *ele; - for (ele = BMO_iter_new(&iter, bm, &op, "outinner", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { + for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { BM_elem_select_set(bm, ele, TRUE); } } @@ -1123,7 +1133,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, /* deselect input */ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - for (ele = BMO_iter_new(&iter, bm, &op, "outinner", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { + for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { BM_elem_select_set(bm, ele, TRUE); if (ele->head.htype == BM_VERT) { @@ -1158,8 +1168,9 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) SubDParams params = {0}; int skey; - params.numcuts = BMO_slot_int_get(op, "numcuts"); + params.numcuts = BMO_slot_int_get(op->slots_in, "cuts"); params.op = op; + params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents"); BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY); skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1; @@ -1167,11 +1178,11 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) params.origkey = skey; /* go through and split edges */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { bm_subdivide_multicut(bm, e, ¶ms, e->v1, e->v2); } - BMO_slot_buffer_from_enabled_flag(bm, op, "outsplit", BM_ALL, ELE_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT); BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, skey); } diff --git a/source/blender/bmesh/operators/bmo_subdivide.h b/source/blender/bmesh/operators/bmo_subdivide.h index d4b926b9275..529075aab02 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.h +++ b/source/blender/bmesh/operators/bmo_subdivide.h @@ -39,6 +39,8 @@ typedef struct SubDParams { int seed; int origkey; /* shapekey holding displaced vertex coordinates for current geometry */ BMOperator *op; + BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */ + BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */ float off[3]; } SubDParams; diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c index a428405fb8b..248c7268ac6 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -96,7 +96,7 @@ static void symm_verts_mirror(Symm *symm) symm->vert_symm_map = BLI_ghash_ptr_new(AT); - BMO_ITER (src_v, &oiter, symm->bm, symm->op, "input", BM_VERT) { + BMO_ITER (src_v, &oiter, symm->op->slots_in, "input", BM_VERT) { SymmSide side = symm_co_side(symm, src_v->co); float co[3]; @@ -106,7 +106,7 @@ static void symm_verts_mirror(Symm *symm) copy_v3_v3(co, src_v->co); co[symm->axis] = -co[symm->axis]; - dst_v = BM_vert_create(symm->bm, co, src_v); + dst_v = BM_vert_create(symm->bm, co, src_v, 0); BMO_elem_flag_enable(symm->bm, dst_v, SYMM_OUTPUT_GEOM); BLI_ghash_insert(symm->vert_symm_map, src_v, dst_v); break; @@ -145,7 +145,7 @@ static void symm_split_asymmetric_edges(Symm *symm) symm->edge_split_map = BLI_ghash_ptr_new(AT); - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { float flipped[3]; copy_v3_v3(flipped, e->v1->co); @@ -183,7 +183,7 @@ static void symm_split_asymmetric_edges(Symm *symm) co[symm->axis] = 0; /* Edge is asymmetric, split it with a new vertex */ - v = BM_vert_create(symm->bm, co, e->v1); + v = BM_vert_create(symm->bm, co, e->v1, 0); BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM); BLI_ghash_insert(symm->edge_split_map, e, v); } @@ -195,7 +195,7 @@ static void symm_mirror_edges(Symm *symm) BMOIter oiter; BMEdge *e; - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { BMVert *v1 = NULL, *v2 = NULL; BMEdge *e_new; @@ -203,7 +203,7 @@ static void symm_mirror_edges(Symm *symm) v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2); if (v1 && v2) { - e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE); + e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); } else if (v1 || v2) { @@ -212,18 +212,18 @@ static void symm_mirror_edges(Symm *symm) /* Output the keep side of the split edge */ if (!v1) { - e_new = BM_edge_create(symm->bm, v_split, e->v2, e, TRUE); + e_new = BM_edge_create(symm->bm, v_split, e->v2, e, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); v1 = v_split; } else { - e_new = BM_edge_create(symm->bm, e->v1, v_split, e, TRUE); + e_new = BM_edge_create(symm->bm, e->v1, v_split, e, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); v2 = v_split; } /* Output the kill side of the split edge */ - e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE); + e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); } } @@ -245,6 +245,8 @@ typedef struct { /* True only if none of the polygon's edges were split */ int already_symmetric; + + BMFace *src_face; } SymmPoly; static void symm_poly_with_splits(const Symm *symm, @@ -255,6 +257,8 @@ static void symm_poly_with_splits(const Symm *symm, BMLoop *l; int i; + out->src_face = f; + /* Count vertices and check for edge splits */ out->len = f->len; out->already_symmetric = TRUE; @@ -351,7 +355,8 @@ static int symm_poly_next_crossing(const Symm *symm, return FALSE; } -static BMFace *symm_face_create_v(BMesh *bm, BMVert **fv, BMEdge **fe, int len) +static BMFace *symm_face_create_v(BMesh *bm, BMFace *example, + BMVert **fv, BMEdge **fe, int len) { BMFace *f_new; int i; @@ -360,11 +365,13 @@ static BMFace *symm_face_create_v(BMesh *bm, BMVert **fv, BMEdge **fe, int len) int j = (i + 1) % len; fe[i] = BM_edge_exists(fv[i], fv[j]); if (!fe[i]) { - fe[i] = BM_edge_create(bm, fv[i], fv[j], NULL, FALSE); + fe[i] = BM_edge_create(bm, fv[i], fv[j], NULL, 0); BMO_elem_flag_enable(bm, fe[i], SYMM_OUTPUT_GEOM); } } - f_new = BM_face_create(bm, fv, fe, len, TRUE); + f_new = BM_face_create(bm, fv, fe, len, BM_CREATE_NO_DOUBLE); + if (example) + BM_elem_attrs_copy(bm, bm, example, f_new); BM_face_select_set(bm, f_new, TRUE); BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM); return f_new; @@ -399,7 +406,7 @@ static void symm_mesh_output_poly_zero_splits(Symm *symm, } } - symm_face_create_v(symm->bm, fv, fe, j); + symm_face_create_v(symm->bm, sp->src_face, fv, fe, j); } static void symm_mesh_output_poly_with_splits(Symm *symm, @@ -422,7 +429,7 @@ static void symm_mesh_output_poly_with_splits(Symm *symm, fv[i] = v; } - symm_face_create_v(symm->bm, fv, fe, segment_len); + symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len); /* Output the kill side of the input polygon */ @@ -434,7 +441,7 @@ static void symm_mesh_output_poly_with_splits(Symm *symm, } - symm_face_create_v(symm->bm, fv, fe, segment_len); + symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len); } static void symm_mirror_polygons(Symm *symm) @@ -448,7 +455,7 @@ static void symm_mirror_polygons(Symm *symm) BLI_array_declare(fv); BLI_array_declare(fe); - BMO_ITER (f, &oiter, symm->bm, symm->op, "input", BM_FACE) { + BMO_ITER (f, &oiter, symm->op->slots_in, "input", BM_FACE) { BMIter iter; BMLoop *l; int mirror_all = TRUE, ignore_all = TRUE; @@ -482,7 +489,7 @@ static void symm_mirror_polygons(Symm *symm) fv[i] = l->v; } - symm_face_create_v(symm->bm, fv, fe, f->len); + symm_face_create_v(symm->bm, f, fv, fe, f->len); } else if (ignore_all) { BM_face_kill(symm->bm, f); @@ -589,7 +596,7 @@ static void symm_mirror_polygons(Symm *symm) BLI_assert(fv[0] && fv[1] && fv[2]); - symm_face_create_v(symm->bm, fv, fe, 3); + symm_face_create_v(symm->bm, NULL, fv, fe, 3); } } } @@ -607,7 +614,7 @@ static void symm_kill_unused(Symm *symm) BMVert *v; /* Kill unused edges */ - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { const int crosses = symm_edge_crosses_axis(symm, e); const int symmetric = (crosses && (!BLI_ghash_haskey(symm->edge_split_map, e))); @@ -617,13 +624,13 @@ static void symm_kill_unused(Symm *symm) !symmetric) { /* The edge might be used by a face outside the input set */ - if (BM_edge_face_count(e) == 0) + if (BM_edge_is_wire(e)) BM_edge_kill(symm->bm, e); } } /* Kill unused vertices */ - BMO_ITER (v, &oiter, symm->bm, symm->op, "input", BM_VERT) { + BMO_ITER (v, &oiter, symm->op->slots_in, "input", BM_VERT) { if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) { if (BM_vert_edge_count(v) == 0) BM_vert_kill(symm->bm, v); @@ -634,7 +641,7 @@ static void symm_kill_unused(Symm *symm) void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) { Symm symm; - BMO_SymmDirection direction = BMO_slot_int_get(op, "direction"); + BMO_SymmDirection direction = BMO_slot_int_get(op->slots_in, "direction"); symm.bm = bm; symm.op = op; @@ -658,6 +665,6 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) BLI_ghash_free(symm.vert_symm_map, NULL, NULL); BLI_ghash_free(symm.edge_split_map, NULL, NULL); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, - SYMM_OUTPUT_GEOM); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", + BM_ALL_NOLOOP, SYMM_OUTPUT_GEOM); } diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index de876477e5a..d20d01af114 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -52,9 +52,10 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op) float (*projectverts)[3] = NULL; BLI_array_declare(projectverts); int i; - const int use_beauty = BMO_slot_bool_get(op, "use_beauty"); + const int use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty"); + BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "face_map.out"); - for (face = BMO_iter_new(&siter, bm, op, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) { + for (face = BMO_iter_new(&siter, op->slots_in, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) { BLI_array_empty(projectverts); BLI_array_empty(newfaces); @@ -64,16 +65,14 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op) BM_face_triangulate(bm, face, projectverts, EDGE_NEW, FACE_NEW, newfaces, use_beauty); - BMO_slot_map_ptr_insert(bm, op, "facemap", face, face); + BMO_slot_map_elem_insert(op, slot_facemap_out, face, face); for (i = 0; newfaces[i]; i++) { - BMO_slot_map_ptr_insert(bm, op, "facemap", - newfaces[i], face); - + BMO_slot_map_elem_insert(op, slot_facemap_out, newfaces[i], face); } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_NEW); - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW); BLI_array_free(projectverts); BLI_array_free(newfaces); @@ -87,9 +86,9 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) BMEdge *e; int stop = 0; - BMO_slot_buffer_flag_enable(bm, op, "constrain_edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "constrain_edges", BM_EDGE, EDGE_MARK); - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { if (f->len == 3) { BMO_elem_flag_enable(bm, f, FACE_MARK); } @@ -152,7 +151,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_EDGE | BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW); } void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) @@ -170,7 +169,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) BLI_scanfill_begin(&sf_ctx); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, e, EDGE_MARK); if (!BLI_smallhash_haskey(&hash, (uintptr_t)e->v1)) { @@ -191,7 +190,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) /* sf_edge->tmp.p = e; */ /* UNUSED */ } - BLI_scanfill_calc(&sf_ctx, FALSE); + BLI_scanfill_calc(&sf_ctx, 0); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { BMFace *f = BM_face_create_quad_tri(bm, @@ -214,8 +213,8 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) /* clean up fill */ BMO_op_initf(bm, &bmop, op->flag, "beautify_fill faces=%ff constrain_edges=%fe", ELE_NEW, EDGE_MARK); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_FACE | BM_EDGE, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, ELE_NEW); BMO_op_finish(bm, &bmop); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_EDGE | BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW); } diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c index 3d44feac380..fae7db3d175 100644 --- a/source/blender/bmesh/operators/bmo_unsubdivide.c +++ b/source/blender/bmesh/operators/bmo_unsubdivide.c @@ -39,10 +39,10 @@ void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op) BMVert *v; BMIter iter; - const int iterations = max_ii(1, BMO_slot_int_get(op, "iterations")); + const int iterations = max_ii(1, BMO_slot_int_get(op->slots_in, "iterations")); - BMOpSlot *vinput = BMO_slot_get(op, "verts"); - BMVert **vinput_arr = (BMVert **)vinput->data.p; + BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts"); + BMVert **vinput_arr = (BMVert **)vinput->data.buf; int v_index; /* tag verts */ diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index e311b383b86..64dbf0cc0e7 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -45,21 +45,21 @@ void bmo_create_vert_exec(BMesh *bm, BMOperator *op) { float vec[3]; - BMO_slot_vec_get(op, "co", vec); + BMO_slot_vec_get(op->slots_in, "co", vec); - BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL), 1); - BMO_slot_buffer_from_enabled_flag(bm, op, "newvertout", BM_VERT, 1); + BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL, 0), 1); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, 1); } -void bmo_transform_exec(BMesh *bm, BMOperator *op) +void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op) { BMOIter iter; BMVert *v; float mat[4][4]; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); - BMO_ITER (v, &iter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) { mul_m4_v3(mat, v->co); } } @@ -68,33 +68,33 @@ void bmo_translate_exec(BMesh *bm, BMOperator *op) { float mat[4][4], vec[3]; - BMO_slot_vec_get(op, "vec", vec); + BMO_slot_vec_get(op->slots_in, "vec", vec); unit_m4(mat); copy_v3_v3(mat[3], vec); - BMO_op_callf(bm, op->flag, "transform mat=%m4 verts=%s", mat, op, "verts"); + BMO_op_callf(bm, op->flag, "transform matrix=%m4 verts=%s", mat, op, "verts"); } void bmo_scale_exec(BMesh *bm, BMOperator *op) { float mat[3][3], vec[3]; - BMO_slot_vec_get(op, "vec", vec); + BMO_slot_vec_get(op->slots_in, "vec", vec); unit_m3(mat); mat[0][0] = vec[0]; mat[1][1] = vec[1]; mat[2][2] = vec[2]; - BMO_op_callf(bm, op->flag, "transform mat=%m3 verts=%s", mat, op, "verts"); + BMO_op_callf(bm, op->flag, "transform matrix=%m3 verts=%s", mat, op, "verts"); } void bmo_rotate_exec(BMesh *bm, BMOperator *op) { float vec[3]; - BMO_slot_vec_get(op, "cent", vec); + BMO_slot_vec_get(op->slots_in, "cent", vec); /* there has to be a proper matrix way to do this, but * this is how editmesh did it and I'm too tired to think @@ -102,7 +102,7 @@ void bmo_rotate_exec(BMesh *bm, BMOperator *op) mul_v3_fl(vec, -1.0f); BMO_op_callf(bm, op->flag, "translate verts=%s vec=%v", op, "verts", vec); - BMO_op_callf(bm, op->flag, "transform mat=%s verts=%s", op, "mat", op, "verts"); + BMO_op_callf(bm, op->flag, "transform matrix=%s verts=%s", op, "matrix", op, "verts"); mul_v3_fl(vec, -1.0f); BMO_op_callf(bm, op->flag, "translate verts=%s vec=%v", op, "verts", vec); @@ -113,7 +113,7 @@ void bmo_reverse_faces_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMFace *f; - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BM_face_normal_flip(bm, f); } } @@ -122,8 +122,8 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e, *e2; - int ccw = BMO_slot_bool_get(op, "ccw"); - int is_single = BMO_slot_buffer_count(bm, op, "edges") == 1; + const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); + const int is_single = BMO_slot_buffer_count(op->slots_in, "edges") == 1; short check_flag = is_single ? BM_EDGEROT_CHECK_EXISTS : BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE; @@ -131,7 +131,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) #define EDGE_OUT 1 #define FACE_TAINT 1 - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /** * this ends up being called twice, could add option to not to call check in * #BM_edge_rotate to get some extra speed */ @@ -144,7 +144,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_test(bm, fb, FACE_TAINT) == FALSE) { - if (!(e2 = BM_edge_rotate(bm, e, ccw, check_flag))) { + if (!(e2 = BM_edge_rotate(bm, e, use_ccw, check_flag))) { #if 0 BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Could not rotate edge"); return; @@ -162,7 +162,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); #undef EDGE_OUT #undef FACE_TAINT @@ -180,7 +180,7 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces) BMOIter siter; if (!usefaces) { - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) @@ -202,7 +202,7 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces) BMFace *f, *f2; BMLoop *l; - BMO_ITER (f, &siter, bm, op, "geom", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f2, BM_ELEM_HIDDEN)) { @@ -224,7 +224,7 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) BMOIter siter; if (!usefaces) { - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) @@ -248,7 +248,7 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) BMFace *f, *f2; BMLoop *l; - BMO_ITER (f, &siter, bm, op, "geom", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f2, BM_ELEM_HIDDEN)) { @@ -265,24 +265,24 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) void bmo_region_extend_exec(BMesh *bm, BMOperator *op) { - int use_faces = BMO_slot_bool_get(op, "use_faces"); - int constrict = BMO_slot_bool_get(op, "constrict"); + int use_faces = BMO_slot_bool_get(op->slots_in, "use_faces"); + int constrict = BMO_slot_bool_get(op->slots_in, "use_constrict"); - BMO_slot_buffer_flag_enable(bm, op, "geom", BM_ALL, SEL_ORIG); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, SEL_ORIG); if (constrict) bmo_region_extend_constrict(bm, op, use_faces); else bmo_region_extend_extend(bm, op, use_faces); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, SEL_FLAG); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, SEL_FLAG); } /********* righthand faces implementation ****** */ #define FACE_VIS 1 #define FACE_FLAG 2 -#define FACE_MARK 4 +// #define FACE_MARK 4 /* UNUSED */ #define FACE_FLIP 8 /* NOTE: these are the original recalc_face_normals comment in editmesh_mods.c, @@ -314,15 +314,15 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) BLI_array_declare(fstack); BMLoop *l, *l2; float maxx, maxx_test, cent[3]; - int i, i_max, flagflip = BMO_slot_bool_get(op, "do_flip"); + int i, i_max, flagflip = BMO_slot_bool_get(op->slots_in, "use_flip"); startf = NULL; maxx = -1.0e10; - BMO_slot_buffer_flag_enable(bm, op, "faces", BM_FACE, FACE_FLAG); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_FLAG); /* find a starting face */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { /* clear dirty flag */ BM_elem_flag_disable(f, BM_ELEM_TAG); @@ -405,7 +405,7 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) BLI_array_free(fstack); /* check if we have faces yet to do. if so, recurse */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, f, FACE_VIS)) { bmo_recalc_face_normals_exec(bm, op); break; @@ -413,7 +413,7 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) } } -void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) +void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op) { BMOIter siter; BMIter iter; @@ -421,20 +421,20 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) BMEdge *e; BLI_array_declare(cos); float (*cos)[3] = NULL; - float *co, *co2, clipdist = BMO_slot_float_get(op, "clipdist"); + float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist"); int i, j, clipx, clipy, clipz; int xaxis, yaxis, zaxis; - clipx = BMO_slot_bool_get(op, "mirror_clip_x"); - clipy = BMO_slot_bool_get(op, "mirror_clip_y"); - clipz = BMO_slot_bool_get(op, "mirror_clip_z"); + clipx = BMO_slot_bool_get(op->slots_in, "mirror_clip_x"); + clipy = BMO_slot_bool_get(op->slots_in, "mirror_clip_y"); + clipz = BMO_slot_bool_get(op->slots_in, "mirror_clip_z"); - xaxis = BMO_slot_bool_get(op, "use_axis_x"); - yaxis = BMO_slot_bool_get(op, "use_axis_y"); - zaxis = BMO_slot_bool_get(op, "use_axis_z"); + xaxis = BMO_slot_bool_get(op->slots_in, "use_axis_x"); + yaxis = BMO_slot_bool_get(op->slots_in, "use_axis_y"); + zaxis = BMO_slot_bool_get(op->slots_in, "use_axis_z"); i = 0; - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BLI_array_grow_one(cos); co = cos[i]; @@ -454,18 +454,18 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) mul_v3_fl(co, 1.0f / (float)j); mid_v3_v3v3(co, co, v->co); - if (clipx && fabsf(v->co[0]) <= clipdist) + if (clipx && fabsf(v->co[0]) <= clip_dist) co[0] = 0.0f; - if (clipy && fabsf(v->co[1]) <= clipdist) + if (clipy && fabsf(v->co[1]) <= clip_dist) co[1] = 0.0f; - if (clipz && fabsf(v->co[2]) <= clipdist) + if (clipz && fabsf(v->co[2]) <= clip_dist) co[2] = 0.0f; i++; } i = 0; - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { if (xaxis) v->co[0] = cos[i][0]; if (yaxis) @@ -489,11 +489,11 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) BMFace *fs; /* current face */ BMIter l_iter; /* iteration loop */ - int dir = BMO_slot_int_get(op, "dir"); + const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPUV)) { - if (dir == DIRECTION_CW) { /* same loops direction */ + if (use_ccw == FALSE) { /* same loops direction */ BMLoop *lf; /* current face loops */ MLoopUV *f_luv; /* first face loop uv */ float p_uv[2]; /* previous uvs */ @@ -517,7 +517,7 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) copy_v2_v2(f_luv->uv, p_uv); } - else if (dir == DIRECTION_CCW) { /* counter loop direction */ + else { /* counter loop direction */ BMLoop *lf; /* current face loops */ MLoopUV *p_luv; /* previous loop uv */ MLoopUV *luv; @@ -556,7 +556,7 @@ void bmo_reverse_uvs_exec(BMesh *bm, BMOperator *op) BLI_array_declare(uvs); float (*uvs)[2] = NULL; - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPUV)) { BMLoop *lf; /* current face loops */ int i; @@ -594,11 +594,11 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op) BMFace *fs; /* current face */ BMIter l_iter; /* iteration loop */ - int dir = BMO_slot_int_get(op, "dir"); + const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL)) { - if (dir == DIRECTION_CW) { /* same loops direction */ + if (use_ccw == FALSE) { /* same loops direction */ BMLoop *lf; /* current face loops */ MLoopCol *f_lcol; /* first face loop color */ MLoopCol p_col; /* previous color */ @@ -622,7 +622,7 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op) *f_lcol = p_col; } - else if (dir == DIRECTION_CCW) { /* counter loop direction */ + else { /* counter loop direction */ BMLoop *lf; /* current face loops */ MLoopCol *p_lcol; /* previous loop color */ MLoopCol *lcol; @@ -661,7 +661,7 @@ void bmo_reverse_colors_exec(BMesh *bm, BMOperator *op) BLI_array_declare(cols); MLoopCol *cols = NULL; - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL)) { BMLoop *lf; /* current face loops */ int i; @@ -701,23 +701,18 @@ typedef struct ElemNode { void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) { - BMOIter vs_iter /* , vs2_iter */; /* selected verts iterator */ BMIter v_iter; /* mesh verts iterator */ - BMVert *vs, *sv, *ev; /* starting vertex, ending vertex */ + BMVert *sv, *ev; /* starting vertex, ending vertex */ BMVert *v; /* mesh vertex */ Heap *h = NULL; ElemNode *vert_list = NULL; int num_total = 0 /*, num_sels = 0 */, i = 0; - const int type = BMO_slot_int_get(op, "type"); + const int type = BMO_slot_int_get(op->slots_in, "type"); - BMO_ITER (vs, &vs_iter, bm, op, "startv", BM_VERT) { - sv = vs; - } - BMO_ITER (vs, &vs_iter, bm, op, "endv", BM_VERT) { - ev = vs; - } + sv = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_start")); + ev = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_end")); num_total = BM_mesh_elem_count(bm, BM_VERT); @@ -795,5 +790,5 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) BLI_heap_free(h, NULL); MEM_freeN(vert_list); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c index d572a1c5863..7401704310f 100644 --- a/source/blender/bmesh/operators/bmo_wireframe.c +++ b/source/blender/bmesh/operators/bmo_wireframe.c @@ -77,39 +77,60 @@ static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3 } } - l_a = bm_edge_tag_faceloop(e_a); - l_b = bm_edge_tag_faceloop(e_b); + if (e_a && e_b) { + l_a = bm_edge_tag_faceloop(e_a); + l_b = bm_edge_tag_faceloop(e_b); - /* average edge face normal */ - add_v3_v3v3(no_face, l_a->f->no, l_b->f->no); + /* average edge face normal */ + add_v3_v3v3(no_face, l_a->f->no, l_b->f->no); - /* average edge direction */ - v_a = BM_edge_other_vert(e_a, v); - v_b = BM_edge_other_vert(e_b, v); + /* average edge direction */ + v_a = BM_edge_other_vert(e_a, v); + v_b = BM_edge_other_vert(e_b, v); - sub_v3_v3v3(tvec_a, v->co, v_a->co); - sub_v3_v3v3(tvec_b, v_b->co, v->co); - normalize_v3(tvec_a); - normalize_v3(tvec_b); - add_v3_v3v3(no_edge, tvec_a, tvec_b); /* not unit length but this is ok */ + sub_v3_v3v3(tvec_a, v->co, v_a->co); + sub_v3_v3v3(tvec_b, v_b->co, v->co); + normalize_v3(tvec_a); + normalize_v3(tvec_b); + add_v3_v3v3(no_edge, tvec_a, tvec_b); /* not unit length but this is ok */ + /* check are we flipped the right way */ + BM_edge_calc_face_tangent(e_a, l_a, tvec_a); + BM_edge_calc_face_tangent(e_b, l_b, tvec_b); + add_v3_v3(tvec_a, tvec_b); + + *r_va_other = v_a; + *r_vb_other = v_b; + } + else { + /* degenerate case - vertex connects a boundary edged face to other faces, + * so we have only one boundary face - only use it for calculations */ + l_a = bm_edge_tag_faceloop(e_a); + + copy_v3_v3(no_face, l_a->f->no); + + /* edge direction */ + v_a = BM_edge_other_vert(e_a, v); + v_b = NULL; + + sub_v3_v3v3(no_edge, v->co, v_a->co); + + /* check are we flipped the right way */ + BM_edge_calc_face_tangent(e_a, l_a, tvec_a); + + *r_va_other = NULL; + *r_vb_other = NULL; + } /* find the normal */ cross_v3_v3v3(r_no, no_edge, no_face); normalize_v3(r_no); - /* check are we flipped the right way */ - BM_edge_calc_face_tangent(e_a, l_a, tvec_a); - BM_edge_calc_face_tangent(e_b, l_b, tvec_b); - add_v3_v3(tvec_a, tvec_b); - if (dot_v3v3(r_no, tvec_a) > 0.0f) { negate_v3(r_no); } copy_v3_v3(r_no_face, no_face); - *r_va_other = v_a; - *r_vb_other = v_b; } /* check if we are the only tagged loop-face around this edge */ @@ -134,12 +155,12 @@ extern float BM_vert_calc_mean_tagged_edge_length(BMVert *v); void bmo_wireframe_exec(BMesh *bm, BMOperator *op) { - const int use_boundary = BMO_slot_bool_get(op, "use_boundary"); - const int use_even_offset = BMO_slot_bool_get(op, "use_even_offset"); - const int use_relative_offset = BMO_slot_bool_get(op, "use_relative_offset"); - const int use_crease = (BMO_slot_bool_get(op, "use_crease") && + const int use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary"); + const int use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); + const int use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); + const int use_crease = (BMO_slot_bool_get(op->slots_in, "use_crease") && CustomData_has_layer(&bm->edata, CD_CREASE)); - const float depth = BMO_slot_float_get(op, "thickness"); + const float depth = BMO_slot_float_get(op->slots_in, "thickness"); const float inset = depth; const int totvert_orig = bm->totvert; @@ -184,7 +205,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) /* setup tags, all faces and verts will be tagged which will be duplicated */ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { verts_loop_tot += f_src->len; BM_elem_flag_enable(f_src, BM_ELEM_TAG); BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { @@ -206,9 +227,9 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } madd_v3_v3v3fl(tvec, v_src->co, v_src->no, -fac); - verts_neg[i] = BM_vert_create(bm, tvec, v_src); + verts_neg[i] = BM_vert_create(bm, tvec, v_src, 0); madd_v3_v3v3fl(tvec, v_src->co, v_src->no, fac); - verts_pos[i] = BM_vert_create(bm, tvec, v_src); + verts_pos[i] = BM_vert_create(bm, tvec, v_src, 0); } else { /* could skip this */ @@ -230,7 +251,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) verts_loop = MEM_mallocN(sizeof(BMVert **) * verts_loop_tot, __func__); verts_loop_tot = 0; /* count up again */ - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { BM_elem_index_set(l, verts_loop_tot); /* set_loop */ @@ -246,7 +267,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } madd_v3_v3v3fl(tvec, l->v->co, tvec, fac); - verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v); + verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v, 0); if (use_boundary) { @@ -269,16 +290,18 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) /* similar to code above but different angle calc */ fac = inset; if (use_even_offset) { - fac *= shell_angle_to_dist(((float)M_PI - angle_on_axis_v3v3v3_v3(va_other->co, - l_pair[i]->v->co, - vb_other->co, - no_face)) * 0.5f); + if (va_other) { /* for verts with only one boundary edge - this will be NULL */ + fac *= shell_angle_to_dist(((float)M_PI - angle_on_axis_v3v3v3_v3(va_other->co, + l_pair[i]->v->co, + vb_other->co, + no_face)) * 0.5f); + } } if (use_relative_offset) { fac *= verts_relfac[BM_elem_index_get(l_pair[i]->v)]; } madd_v3_v3v3fl(tvec, l_pair[i]->v->co, tvec, fac); - verts_boundary[BM_elem_index_get(l_pair[i]->v)] = BM_vert_create(bm, tvec, l_pair[i]->v); + verts_boundary[BM_elem_index_get(l_pair[i]->v)] = BM_vert_create(bm, tvec, l_pair[i]->v, 0); } } } @@ -288,7 +311,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { BM_elem_flag_disable(f_src, BM_ELEM_TAG); BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { BMFace *f_new; @@ -400,5 +423,5 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) MEM_freeN(verts_pos); MEM_freeN(verts_loop); - BMO_slot_buffer_from_enabled_hflag(bm, op, "faceout", BM_FACE, BM_ELEM_TAG); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index a632a4446ed..3f2ca21bcee 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -689,8 +689,16 @@ static BMFace *BME_bevel_poly(BMesh *bm, BMFace *f, float value, int options, BM BMO_elem_flag_test(bm, l->v, BME_BEVEL_ORIG) && !BMO_elem_flag_test(bm, l->prev->e, BME_BEVEL_BEVEL)) { - max = 1.0f; - l = BME_bevel_vert(bm, l, value, options, up_vec, td); + /* avoid making double vertices [#33438] */ + BME_TransData *vtd; + vtd = BME_get_transdata(td, l->v); + if (vtd->weight == 0.0f) { + BMO_elem_flag_disable(bm, l->v, BME_BEVEL_BEVEL); + } + else { + max = 1.0f; + l = BME_bevel_vert(bm, l, value, options, up_vec, td); + } } } @@ -1110,10 +1118,13 @@ BMesh *BME_bevel(BMesh *bm, float value, int res, int options, int defgrp_index, td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE); /* recursion math courtesy of Martin Poirier (theeth) */ for (i = 0; i < res - 1; i++) { - if (i == 0) fac += 1.0 / 3.0; else fac += 1.0 / (3.0 * i * 2.0); + if (i == 0) fac += 1.0 / 3.0; + else fac += 1.0 / (3.0 * i * 2.0); } d = 1.0 / fac; + BM_mesh_elem_toolflags_ensure(bm); + for (i = 0; i < res || (res == 0 && i == 0); i++) { BMO_push(bm, NULL); BME_bevel_initialize(bm, options, defgrp_index, angle, td); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c new file mode 100644 index 00000000000..9125800d3e8 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -0,0 +1,1835 @@ +/* + * ***** 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): + * Joseph Eagar, + * Aleksandr Mokhov, + * Howard Trickey, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/tools/bmesh_bevel.c + * \ingroup bmesh + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_array.h" +#include "BLI_math.h" +#include "BLI_memarena.h" + +#include "BKE_customdata.h" + +#include "bmesh.h" + + + +/* experemental - Campbell */ +// #define USE_ALTERNATE_ADJ + +#define BEVEL_EPSILON 1e-6 + +/* for testing */ +// #pragma GCC diagnostic error "-Wpadded" + +/* Constructed vertex, sometimes later instantiated as BMVert */ +typedef struct NewVert { + BMVert *v; + float co[3]; +// int _pad; +} NewVert; + +struct BoundVert; + +/* Data for one end of an edge involved in a bevel */ +typedef struct EdgeHalf { + struct EdgeHalf *next, *prev; /* in CCW order */ + BMEdge *e; /* original mesh edge */ + BMFace *fprev; /* face between this edge and previous, if any */ + BMFace *fnext; /* face between this edge and next, if any */ + struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */ + struct BoundVert *rightv; /* right boundary vert, if beveled */ + short is_bev; /* is this edge beveled? */ + short is_rev; /* is e->v2 the vertex at this end? */ + int seg; /* how many segments for the bevel */ + float offset; /* offset for this edge */ +// int _pad; +} EdgeHalf; + +/* An element in a cyclic boundary of a Vertex Mesh (VMesh) */ +typedef struct BoundVert { + struct BoundVert *next, *prev; /* in CCW order */ + NewVert nv; + EdgeHalf *efirst; /* first of edges attached here: in CCW order */ + EdgeHalf *elast; + EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */ + int index; /* used for vmesh indexing */ +// int _pad; +} BoundVert; + +/* Mesh structure replacing a vertex */ +typedef struct VMesh { + NewVert *mesh; /* allocated array - size and structure depends on kind */ + BoundVert *boundstart; /* start of boundary double-linked list */ + int count; /* number of vertices in the boundary */ + int seg; /* common # of segments for segmented edges */ + enum { + M_NONE, /* no polygon mesh needed */ + M_POLY, /* a simple polygon */ + M_ADJ, /* "adjacent edges" mesh pattern */ +// M_CROSS, /* "cross edges" mesh pattern */ + M_TRI_FAN, /* a simple polygon - fan filled */ + M_QUAD_STRIP, /* a simple polygon - cut into paralelle strips */ + } mesh_kind; +// int _pad; +} VMesh; + +/* Data for a vertex involved in a bevel */ +typedef struct BevVert { + BMVert *v; /* original mesh vertex */ + int edgecount; /* total number of edges around the vertex */ + int selcount; /* number of selected edges around the vertex */ + EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */ + VMesh *vmesh; /* mesh structure for replacing vertex */ +} BevVert; + +/* Bevel parameters and state */ +typedef struct BevelParams { + /* hash of BevVert for each vertex involved in bevel + * GHash: (key=(BMVert *), value=(BevVert *)) */ + GHash *vert_hash; + MemArena *mem_arena; /* use for all allocs while bevel runs, if we need to free we can switch to mempool */ + + float offset; /* blender units to offset each side of a beveled edge */ + int seg; /* number of segments in beveled edge profile */ +} BevelParams; + +// #pragma GCC diagnostic ignored "-Wpadded" + +//#include "bevdebug.c" + +/* Make a new BoundVert of the given kind, insert it at the end of the circular linked + * list with entry point bv->boundstart, and return it. */ +static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3]) +{ + BoundVert *ans = (BoundVert *)BLI_memarena_alloc(mem_arena, sizeof(BoundVert)); + + copy_v3_v3(ans->nv.co, co); + if (!vm->boundstart) { + ans->index = 0; + vm->boundstart = ans; + ans->next = ans->prev = ans; + } + else { + BoundVert *tail = vm->boundstart->prev; + ans->index = tail->index + 1; + ans->prev = tail; + ans->next = vm->boundstart; + tail->next = ans; + vm->boundstart->prev = ans; + } + vm->count++; + return ans; +} + +/* Mesh verts are indexed (i, j, k) where + * i = boundvert index (0 <= i < nv) + * j = ring index (0 <= j <= ns2) + * k = segment index (0 <= k <= ns) + * Not all of these are used, and some will share BMVerts */ +static NewVert *mesh_vert(VMesh *vm, int i, int j, int k) +{ + int nj = (vm->seg / 2) + 1; + int nk = vm->seg + 1; + + return &vm->mesh[i * nk * nj + j * nk + k]; +} + +static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg) +{ + NewVert *nv = mesh_vert(vm, i, j, k); + nv->v = BM_vert_create(bm, nv->co, eg, 0); +} + +static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, + int ifrom, int jfrom, int kfrom) +{ + NewVert *nvto, *nvfrom; + + nvto = mesh_vert(vm, ito, jto, kto); + nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom); + nvto->v = nvfrom->v; + copy_v3_v3(nvto->co, nvfrom->co); +} + +/* find the EdgeHalf in bv's array that has edge bme */ +static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme) +{ + int i; + + for (i = 0; i < bv->edgecount; i++) { + if (bv->edges[i].e == bme) + return &bv->edges[i]; + } + return NULL; +} + +/* Return the next EdgeHalf after from_e that is beveled. + * If from_e is NULL, find the first beveled edge. */ +static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e) +{ + EdgeHalf *e; + + if (from_e == NULL) + from_e = &bv->edges[bv->edgecount - 1]; + e = from_e; + do { + if (e->is_bev) { + return e; + } + } while ((e = e->next) != from_e); + return NULL; +} + +/* find the BevVert corresponding to BMVert bmv */ +static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv) +{ + return BLI_ghash_lookup(bp->vert_hash, bmv); +} + +/* Return a good respresentative face (for materials, etc.) for faces + * created around/near BoundVert v */ +static BMFace *boundvert_rep_face(BoundVert *v) +{ + BMFace *fans = NULL; + BMFace *firstf = NULL; + BMEdge *e1, *e2; + BMFace *f1, *f2; + BMIter iter1, iter2; + + BLI_assert(v->efirst != NULL && v->elast != NULL); + e1 = v->efirst->e; + e2 = v->elast->e; + BM_ITER_ELEM (f1, &iter1, e1, BM_FACES_OF_EDGE) { + if (!firstf) + firstf = f1; + BM_ITER_ELEM (f2, &iter2, e2, BM_FACES_OF_EDGE) { + if (f1 == f2) { + fans = f1; + break; + } + } + } + if (!fans) + fans = firstf; + + return fans; +} + +/** + * Make ngon from verts alone. + * Make sure to properly copy face attributes and do custom data interpolation from + * example face, facerep. + * + * \note ALL face creation goes through this function, this is important to keep! + */ +static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BMFace *facerep) +{ + BMIter iter; + BMLoop *l; + BMFace *f; + + if (totv == 3) { + f = BM_face_create_quad_tri_v(bm, vert_arr, 3, facerep, FALSE); + } + else if (totv == 4) { + f = BM_face_create_quad_tri_v(bm, vert_arr, 4, facerep, FALSE); + } + else { + int i; + BMEdge **ee = NULL; + BLI_array_fixedstack_declare(ee, BM_DEFAULT_NGON_STACK_SIZE, totv, __func__); + + for (i = 0; i < totv; i++) { + ee[i] = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, BM_CREATE_NO_DOUBLE); + } + f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, 0); + BLI_array_fixedstack_free(ee); + } + if (facerep && f) { + int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); + BM_elem_attrs_copy(bm, bm, facerep, f); + BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { + BM_loop_interp_from_face(bm, l, facerep, TRUE, TRUE); + if (has_mdisps) + BM_loop_interp_multires(bm, l, facerep); + } + } + + /* not essential for bevels own internal logic, + * this is done so the operator can select newly created faces */ + if (f) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + + return f; +} + +static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + BMFace *facerep) +{ + BMVert *varr[4] = {v1, v2, v3, v4}; + return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep); +} + +/* + * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco. + * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of + * the bevel vertex, e1 precedes e2 in CCW order. + * If on_right is true, offset edge is on right of both edges, where e1 enters v and + * e2 leave it. If on_right is false, then the offset edge is on the left. + * When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2), + * but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may + * lead to different offsets) then meeting point can be found be intersecting offset lines. + */ +static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, + int on_right, float meetco[3]) +{ + float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3], + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + + /* get direction vectors for two offset lines */ + sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); + + if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + /* special case: e1 and e2 are parallel; put offset point perp to both, from v. + * need to find a suitable plane. + * if offsets are different, we're out of luck: just use e1->offset */ + if (f) + copy_v3_v3(norm_v, f->no); + else + copy_v3_v3(norm_v, v->no); + cross_v3_v3v3(norm_perp1, dir1, norm_v); + normalize_v3(norm_perp1); + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + copy_v3_v3(meetco, off1a); + } + else { + /* get normal to plane where meet point should be */ + cross_v3_v3v3(norm_v, dir2, dir1); + normalize_v3(norm_v); + if (!on_right) + negate_v3(norm_v); + + /* get vectors perp to each edge, perp to norm_v, and pointing into face */ + if (f) { + copy_v3_v3(norm_v, f->no); + } + cross_v3_v3v3(norm_perp1, dir1, norm_v); + cross_v3_v3v3(norm_perp2, dir2, norm_v); + normalize_v3(norm_perp1); + normalize_v3(norm_perp2); + + /* get points that are offset distances from each line, then another point on each line */ + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + add_v3_v3v3(off1b, off1a, dir1); + copy_v3_v3(off2a, v->co); + madd_v3_v3fl(off2a, norm_perp2, e2->offset); + add_v3_v3v3(off2b, off2a, dir2); + + /* intersect the lines; by construction they should be on the same plane and not parallel */ + if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { + BLI_assert(!"offset_meet failure"); + copy_v3_v3(meetco, off1a); /* just to do something */ + } + } +} + +/* Like offset_meet, but here f1 and f2 must not be NULL and give the + * planes in which to run the offset lines. + * They may not meet exactly: the offsets for the edges may be different + * or both the planes and the lines may be angled so that they can't meet. + * In that case, pick a close point on emid, which should be the dividing + * edge between the two planes. + * TODO: should have a global 'offset consistency' prepass to adjust offset + * widths so that all edges have the same offset at both ends. */ +static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, + BMVert *v, BMFace *f1, BMFace *f2, float meetco[3]) +{ + float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3], + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], co[3], + f1no[3], f2no[3]; + int iret; + + BLI_assert(f1 != NULL && f2 != NULL); + + /* get direction vectors for two offset lines */ + sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); + sub_v3_v3v3(dirmid, BM_edge_other_vert(emid->e, v)->co, v->co); + + /* get directions into offset planes */ + /* calculate face normals at corner in case faces are nonplanar */ + cross_v3_v3v3(f1no, dirmid, dir1); + cross_v3_v3v3(f2no, dirmid, dir2); + cross_v3_v3v3(norm_perp1, dir1, f1no); + normalize_v3(norm_perp1); + cross_v3_v3v3(norm_perp2, dir2, f2no); + normalize_v3(norm_perp2); + + /* get points that are offset distances from each line, then another point on each line */ + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + sub_v3_v3v3(off1b, off1a, dir1); + copy_v3_v3(off2a, v->co); + madd_v3_v3fl(off2a, norm_perp2, e2->offset); + add_v3_v3v3(off2b, off2a, dir2); + + if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + /* lines are parallel; off1a is a good meet point */ + copy_v3_v3(meetco, off1a); + } + else { + iret = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2); + if (iret == 0) { + /* lines colinear: another test says they are parallel. so shouldn't happen */ + copy_v3_v3(meetco, off1a); + } + else if (iret == 2) { + /* lines are not coplanar; meetco and isect2 are nearest to first and second lines */ + if (len_v3v3(meetco, isect2) > 100.0f * (float)BEVEL_EPSILON) { + /* offset lines don't meet: project average onto emid; this is not ideal (see TODO above) */ + mid_v3_v3v3(co, meetco, isect2); + closest_to_line_v3(meetco, co, v->co, BM_edge_other_vert(emid->e, v)->co); + } + } + /* else iret == 1 and the lines are coplanar so meetco has the intersection */ + } +} + +/* Offset by e->offset in plane with normal plane_no, on left if left==TRUE, + * else on right. If no is NULL, choose an arbitrary plane different + * from eh's direction. */ +static void offset_in_plane(EdgeHalf *e, const float plane_no[3], int left, float r[3]) +{ + float dir[3], no[3], fdir[3]; + BMVert *v; + + v = e->is_rev ? e->e->v2 : e->e->v1; + + sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co); + normalize_v3(dir); + if (plane_no) { + copy_v3_v3(no, plane_no); + } + else { + zero_v3(no); + if (fabs(dir[0]) < fabs(dir[1])) + no[0] = 1.0f; + else + no[1] = 1.0f; + } + if (left) + cross_v3_v3v3(fdir, dir, no); + else + cross_v3_v3v3(fdir, no, dir); + normalize_v3(fdir); + copy_v3_v3(r, v->co); + madd_v3_v3fl(r, fdir, e->offset); +} + +/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */ +static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) +{ + float dir[3], len; + + sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co); + len = normalize_v3(dir); + if (d > len) + d = len - (float)(50.0 * BEVEL_EPSILON); + copy_v3_v3(slideco, v->co); + madd_v3_v3fl(slideco, dir, -d); +} + +/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */ +static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3], float projco[3]) +{ + float otherco[3]; + + if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, projco, otherco)) { + BLI_assert(!"project meet failure"); + copy_v3_v3(projco, e->v1->co); + } +} + +/* return 1 if a and b are in CCW order on the normal side of f, + * and -1 if they are reversed, and 0 if there is no shared face f */ +static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) +{ + BMLoop *la, *lb; + + if (!f) + return 0; + la = BM_face_edge_share_loop(f, a); + lb = BM_face_edge_share_loop(f, b); + if (!la || !lb) + return 0; + return lb->next == la ? 1 : -1; +} + +#ifdef USE_ALTERNATE_ADJ + +static void vmesh_cent(VMesh *vm, float r_cent[3]) +{ + BoundVert *v; + zero_v3(r_cent); + + v = vm->boundstart; + do { + add_v3_v3(r_cent, v->nv.co); + } while ((v = v->next) != vm->boundstart); + mul_v3_fl(r_cent, 1.0f / (float)vm->count); +} + +/** + * + * This example shows a tri fan of quads, + * but could be an NGon fan of quads too. + *
+ *      The whole triangle   X
+ *      represents the      / \
+ *      new bevel face.    /   \
+ *                        /     \
+ *       Split into      /       \
+ *       a quad fan.    /         \
+ *                     /           \
+ *                    /             \
+ *                   /               \
+ *          co_prev +-.             .-+
+ *                 /   `-._     _.-'   \
+ *                / co_cent`-+-'        \
+ *               /           |           \
+ * Quad of      /            |            \
+ * interest -- / ---> X      |             \
+ *            /              |              \
+ *           /               |               \
+ *          /         co_next|                \
+ * co_orig +-----------------+-----------------+
+ *
+ *         For each quad, calcualte UV's based on the following:
+ *           U = k    / (vm->seg * 2)
+ *           V = ring / (vm->seg * 2)
+ *           quad = (co_orig, co_prev, co_cent, co_next)
+ *           ... note that co_cent is the same for all quads in the fan.
+ * 
+ * + */ + +static void get_point_uv(float uv[2], + /* all these args are int's originally + * but pass as floats to the function */ + const float seg, const float ring, const float k) +{ + uv[0] = (ring / seg) * 2.0f; + uv[1] = (k / seg) * 2.0f; +} + +/* TODO: make this a lot smarter!, + * this is the main reason USE_ALTERNATE_ADJ isn't so good right now :S */ +static float get_point_uv_factor(const float uv[2]) +{ + return sinf(1.0f - max_ff(uv[0], uv[1]) / 2.0f); +} + +static void get_point_on_round_edge(const float uv[2], + float quad[4][3], + float r_co[3]) +{ + interp_bilinear_quad_v3(quad, uv[0], uv[1], r_co); +} + +#else /* USE_ALTERNATE_ADJ */ + +/* Fill matrix r_mat so that a point in the sheared parallelogram with corners + * va, vmid, vb (and the 4th that is implied by it being a parallelogram) + * is transformed to the unit square by multiplication with r_mat. + * If it can't be done because the parallelogram is degenerate, return FALSE + * else return TRUE. + * Method: + * Find vo, the origin of the parallelogram with other three points va, vmid, vb. + * Also find vd, which is in direction normal to parallelogram and 1 unit away + * from the origin. + * The quarter circle in first quadrant of unit square will be mapped to the + * quadrant of a sheared ellipse in the parallelgram, using a matrix. + * The matrix mat is calculated to map: + * (0,1,0) -> va + * (1,1,0) -> vmid + * (1,0,0) -> vb + * (0,1,1) -> vd + * We want M to make M*A=B where A has the left side above, as columns + * and B has the right side as columns - both extended into homogeneous coords. + * So M = B*(Ainverse). Doing Ainverse by hand gives the code below. +*/ +static int make_unit_square_map(const float va[3], const float vmid[3], const float vb[3], + float r_mat[4][4]) +{ + float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3]; + + sub_v3_v3v3(va_vmid, vmid, va); + sub_v3_v3v3(vb_vmid, vmid, vb); + if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > 100.f *(float)BEVEL_EPSILON) { + sub_v3_v3v3(vo, va, vb_vmid); + cross_v3_v3v3(vddir, vb_vmid, va_vmid); + normalize_v3(vddir); + add_v3_v3v3(vd, vo, vddir); + + /* The cols of m are: {vmid - va, vmid - vb, vmid + vd - va -vb, va + vb - vmid; + * blender transform matrices are stored such that m[i][*] is ith column; + * the last elements of each col remain as they are in unity matrix */ + sub_v3_v3v3(&r_mat[0][0], vmid, va); + r_mat[0][3] = 0.0f; + sub_v3_v3v3(&r_mat[1][0], vmid, vb); + r_mat[1][3] = 0.0f; + add_v3_v3v3(&r_mat[2][0], vmid, vd); + sub_v3_v3(&r_mat[2][0], va); + sub_v3_v3(&r_mat[2][0], vb); + r_mat[2][3] = 0.0f; + add_v3_v3v3(&r_mat[3][0], va, vb); + sub_v3_v3(&r_mat[3][0], vmid); + r_mat[3][3] = 1.0f; + + return TRUE; + } + else + return FALSE; +} + +/* + * Find the point (/n) of the way around the round profile for e, + * where start point is va, midarc point is vmid, and end point is vb. + * Return the answer in profileco. + * If va -- vmid -- vb is approximately a straight line, just + * interpolate along the line. + */ +static void get_point_on_round_edge(EdgeHalf *e, int k, + const float va[3], const float vmid[3], const float vb[3], + float r_co[3]) +{ + float p[3], angle; + float m[4][4]; + int n = e->seg; + + if (make_unit_square_map(va, vmid, vb, m)) { + /* Find point k/(e->seg) along quarter circle from (0,1,0) to (1,0,0) */ + angle = (float)M_PI * (float)k / (2.0f * (float)n); /* angle from y axis */ + p[0] = sinf(angle); + p[1] = cosf(angle); + p[2] = 0.0f; + mul_v3_m4v3(r_co, m, p); + } + else { + /* degenerate case: profile is a line */ + interp_v3_v3v3(r_co, va, vb, (float)k / (float)n); + } +} + +/* Calculate a snapped point to the transformed profile of edge e, extended as + * in a cylinder-like surface in the direction of e. + * co is the point to snap and is modified in place. + * va and vb are the limits of the profile (with peak on e). */ +static void snap_to_edge_profile(EdgeHalf *e, const float va[3], const float vb[3], + float co[3]) +{ + float m[4][4], minv[4][4]; + float edir[3], va0[3], vb0[3], vmid0[3], p[3], snap[3]; + + sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co); + normalize_v3(edir); + + /* project va and vb onto plane P, with normal edir and containing co */ + closest_to_plane_v3(va0, co, edir, va); + closest_to_plane_v3(vb0, co, edir, vb); + project_to_edge(e->e, va0, vb0, vmid0); + if (make_unit_square_map(va0, vmid0, vb0, m)) { + /* Transform co and project it onto the unit circle. + * Projecting is in fact just normalizing the transformed co */ + if (!invert_m4_m4(minv, m)) { + /* shouldn't happen, by angle test and construction of vd */ + BLI_assert(!"failed inverse during profile snap"); + return; + } + mul_v3_m4v3(p, minv, co); + normalize_v3(p); + mul_v3_m4v3(snap, m, p); + copy_v3_v3(co, snap); + } + else { + /* planar case: just snap to line va--vb */ + closest_to_line_segment_v3(p, co, va, vb); + copy_v3_v3(co, p); + } +} + +#endif /* !USE_ALTERNATE_ADJ */ + +/* Make a circular list of BoundVerts for bv, each of which has the coordinates + * of a vertex on the the boundary of the beveled vertex bv->v. + * Also decide on the mesh pattern that will be used inside the boundary. + * Doesn't make the actual BMVerts */ +static void build_boundary(MemArena *mem_arena, BevVert *bv) +{ + EdgeHalf *efirst, *e; + BoundVert *v; + VMesh *vm; + float co[3]; + const float *no; + float lastd; + + e = efirst = next_bev(bv, NULL); + vm = bv->vmesh; + + BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */ + + if (bv->edgecount == 2 && bv->selcount == 1) { + /* special case: beveled edge meets non-beveled one at valence 2 vert */ + no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL); + offset_in_plane(e, no, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = v->ebev = e; + e->leftv = v; + no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL); + offset_in_plane(e, no, FALSE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e; + e->rightv = v; + /* make artifical extra point along unbeveled edge, and form triangle */ + slide_dist(e->next, bv->v, e->offset, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e->next; + e->next->leftv = e->next->rightv = v; + /* could use M_POLY too, but tri-fan looks nicer)*/ + vm->mesh_kind = M_TRI_FAN; + return; + } + + lastd = e->offset; + vm->boundstart = NULL; + do { + if (e->is_bev) { + /* handle only left side of beveled edge e here: next iteration should do right side */ + if (e->prev->is_bev) { + BLI_assert(e->prev != e); /* see: wire edge special case */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->rightv = v; + } + else { + /* e->prev is not beveled */ + if (e->prev->prev->is_bev) { + BLI_assert(e->prev->prev != e); /* see: edgecount 2, selcount 1 case */ + /* find meet point between e->prev->prev and e and attach e->prev there */ + offset_in_two_planes(e->prev->prev, e, e->prev, bv->v, + e->prev->prev->fnext, e->fprev, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->leftv = v; + e->prev->prev->rightv = v; + } + else { + /* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->leftv = v; + } + } + lastd = len_v3v3(bv->v->co, v->nv.co); + } + else { + /* e is not beveled */ + if (e->next->is_bev) { + /* next iteration will place e between beveled previous and next edges */ + /* do nothing... */ + } + else if (e->prev->is_bev) { + /* on-edge meet between e->prev and e */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = e; + e->leftv = v; + e->prev->rightv = v; + } + else { + /* None of e->prev, e, e->next are beveled. + * could either leave alone or add slide points to make + * one polygon around bv->v. For now, we choose latter. + * Could slide to make an even bevel plane but for now will + * just use last distance a meet point moved from bv->v. */ + slide_dist(e, bv->v, lastd, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e; + e->leftv = v; + } + } + } while ((e = e->next) != efirst); + + BLI_assert(vm->count >= 2); + if (vm->count == 2 && bv->edgecount == 3) { + vm->mesh_kind = M_NONE; + } + else if (bv->selcount == 2) { + vm->mesh_kind = M_QUAD_STRIP; + } + else if (efirst->seg == 1 || bv->selcount == 1) { + if (vm->count == 3 && bv->selcount == 1) { + vm->mesh_kind = M_TRI_FAN; + } + else { + vm->mesh_kind = M_POLY; + } + } + else { + vm->mesh_kind = M_ADJ; + } +} + +/* + * Given that the boundary is built and the boundary BMVerts have been made, + * calculate the positions of the interior mesh points for the M_ADJ pattern, + * then make the BMVerts and the new faces. */ +static void bevel_build_rings(BMesh *bm, BevVert *bv) +{ + int k, ring, i, n, ns, ns2, nn; + VMesh *vm = bv->vmesh; + BoundVert *v, *vprev, *vnext; + NewVert *nv, *nvprev, *nvnext; + EdgeHalf *e1, *e2, *epipe; + BMVert *bmv, *bmv1, *bmv2, *bmv3, *bmv4; + BMFace *f; + float co[3], coa[3], cob[3], midco[3]; + float va_pipe[3], vb_pipe[3]; + +#ifdef USE_ALTERNATE_ADJ + /* ordered as follows (orig, prev, center, next)*/ + float quad_plane[4][3]; + float quad_orig[4][3]; +#endif + + +#ifdef USE_ALTERNATE_ADJ + /* the rest are initialized inline, this remains the same for all */ + vmesh_cent(vm, quad_plane[2]); + copy_v3_v3(quad_orig[2], bv->v->co); +#endif + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + BLI_assert(n > 2 && ns > 1); + + /* special case: two beveled edges are in line and share a face, making a "pipe" */ + epipe = NULL; + if (bv->selcount > 2) { + for (e1 = &bv->edges[0]; epipe == NULL && e1 != &bv->edges[bv->edgecount]; e1++) { + if (e1->is_bev) { + for (e2 = &bv->edges[0]; e2 != &bv->edges[bv->edgecount]; e2++) { + if (e1 != e2 && e2->is_bev) { + if ((e1->fnext == e2->fprev) || (e1->fprev == e2->fnext)) { + float dir1[3], dir2[3]; + sub_v3_v3v3(dir1, bv->v->co, BM_edge_other_vert(e1->e, bv->v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, bv->v)->co, bv->v->co); + if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + epipe = e1; + break; + } + } + } + } + } + } + } + + /* Make initial rings, going between points on neighbors. + * After this loop, will have coords for all (i, r, k) where + * BoundVert for i has a bevel, 0 <= r <= ns2, 0 <= k <= ns */ + for (ring = 1; ring <= ns2; ring++) { + v = vm->boundstart; + + do { + i = v->index; + if (v->ebev) { + /* get points coords of points a and b, on outer rings + * of prev and next edges, k away from this edge */ + vprev = v->prev; + vnext = v->next; + + if (vprev->ebev) + nvprev = mesh_vert(vm, vprev->index, 0, ns - ring); + else + nvprev = mesh_vert(vm, vprev->index, 0, ns); + copy_v3_v3(coa, nvprev->co); + nv = mesh_vert(vm, i, ring, 0); + copy_v3_v3(nv->co, coa); + nv->v = nvprev->v; + + if (vnext->ebev) + nvnext = mesh_vert(vm, vnext->index, 0, ring); + else + nvnext = mesh_vert(vm, vnext->index, 0, 0); + copy_v3_v3(cob, nvnext->co); + nv = mesh_vert(vm, i, ring, ns); + copy_v3_v3(nv->co, cob); + nv->v = nvnext->v; + +#ifdef USE_ALTERNATE_ADJ + /* plane */ + copy_v3_v3(quad_plane[0], v->nv.co); + mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co); + /* quad[2] is set */ + mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co); + + /* orig */ + copy_v3_v3(quad_orig[0], v->nv.co); /* only shared location between 2 quads */ + project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig[1]); + project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig[3]); + + //bl_debug_draw_quad_add(UNPACK4(quad_plane)); + //bl_debug_draw_quad_add(UNPACK4(quad_orig)); +#endif + +#ifdef USE_ALTERNATE_ADJ + for (k = 1; k < ns; k++) { + float uv[2]; + float fac; + float co_plane[3]; + float co_orig[3]; + + get_point_uv(uv, v->ebev->seg, ring, k); + get_point_on_round_edge(uv, quad_plane, co_plane); + get_point_on_round_edge(uv, quad_orig, co_orig); + fac = get_point_uv_factor(uv); + interp_v3_v3v3(co, co_plane, co_orig, fac); + copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); + } +#else + /* TODO: better calculation of new midarc point? */ + project_to_edge(v->ebev->e, coa, cob, midco); + + for (k = 1; k < ns; k++) { + get_point_on_round_edge(v->ebev, k, coa, midco, cob, co); + copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); + } + + if (v->ebev == epipe) { + /* save profile extremes for later snapping */ + copy_v3_v3(va_pipe, mesh_vert(vm, i, 0, 0)->co); + copy_v3_v3(vb_pipe, mesh_vert(vm, i, 0, ns)->co); + } +#endif + } + } while ((v = v->next) != vm->boundstart); + } + + /* Now make sure cross points of rings share coordinates and vertices. + * After this loop, will have BMVerts for all (i, r, k) where + * i is for a BoundVert that is beveled and has either a predecessor or + * successor BoundVert beveled too, and + * for odd ns: 0 <= r <= ns2, 0 <= k <= ns + * for even ns: 0 <= r < ns2, 0 <= k <= ns except k=ns2 */ + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + vprev = v->prev; + vnext = v->next; + if (vprev->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = 1; k <= ns2; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; /* center line is special case: do after the rest are done */ + nv = mesh_vert(vm, i, ring, k); + nvprev = mesh_vert(vm, vprev->index, k, ns - ring); + mid_v3_v3v3(co, nv->co, nvprev->co); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); + +#ifndef USE_ALTERNATE_ADJ + copy_v3_v3(nv->co, co); +#endif + BLI_assert(nv->v == NULL && nvprev->v == NULL); + create_mesh_bmvert(bm, vm, i, ring, k, bv->v); + copy_mesh_vert(vm, vprev->index, k, ns - ring, i, ring, k); + } + } + if (!vprev->prev->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = 1; k <= ns2; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; + create_mesh_bmvert(bm, vm, vprev->index, ring, k, bv->v); + } + } + } + if (!vnext->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = ns - ns2; k < ns; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; + create_mesh_bmvert(bm, vm, i, ring, k, bv->v); + } + } + } + } + } + } while ((v = v->next) != vm->boundstart); + + if (ns % 2 == 0) { + /* Do special case center lines. + * This loop makes verts for (i, ns2, k) for 1 <= k <= ns-1, k!=ns2 + * and for (i, r, ns2) for 1 <= r <= ns2-1, + * whenever i is in a sequence of at least two beveled verts */ + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + vprev = v->prev; + vnext = v->next; + for (k = 1; k < ns2; k++) { + nv = mesh_vert(vm, i, k, ns2); + if (vprev->ebev) + nvprev = mesh_vert(vm, vprev->index, ns2, ns - k); + if (vnext->ebev) + nvnext = mesh_vert(vm, vnext->index, ns2, k); + if (vprev->ebev && vnext->ebev) { + mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->co); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); +#ifndef USE_ALTERNATE_ADJ + copy_v3_v3(nv->co, co); +#endif + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); + copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); + + } + else if (vprev->ebev) { + mid_v3_v3v3(co, nvprev->co, nv->co); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); +#ifndef USE_ALTERNATE_ADJ + copy_v3_v3(nv->co, co); +#endif + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); + + create_mesh_bmvert(bm, vm, i, ns2, ns - k, bv->v); + } + else if (vnext->ebev) { + mid_v3_v3v3(co, nv->co, nvnext->co); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); +#ifndef USE_ALTERNATE_ADJ + copy_v3_v3(nv->co, co); +#endif + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); + + create_mesh_bmvert(bm, vm, i, ns2, k, bv->v); + } + } + } + } while ((v = v->next) != vm->boundstart); + + /* center point need to be average of all centers of rings */ + /* TODO: this is wrong if not all verts have ebev: could have + * several disconnected sections of mesh. */ + zero_v3(midco); + nn = 0; + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + nv = mesh_vert(vm, i, ns2, ns2); + add_v3_v3(midco, nv->co); + nn++; + } + } while ((v = v->next) != vm->boundstart); + mul_v3_fl(midco, 1.0f / nn); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, midco); + bmv = BM_vert_create(bm, midco, NULL, 0); + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + nv = mesh_vert(vm, i, ns2, ns2); + copy_v3_v3(nv->co, midco); + nv->v = bmv; + } + } while ((v = v->next) != vm->boundstart); + } + + /* Make the ring quads */ + for (ring = 0; ring < ns2; ring++) { + v = vm->boundstart; + do { + i = v->index; + f = boundvert_rep_face(v); + if (v->ebev && (v->prev->ebev || v->next->ebev)) { + for (k = 0; k < ns2 + (ns % 2); k++) { + bmv1 = mesh_vert(vm, i, ring, k)->v; + bmv2 = mesh_vert(vm, i, ring, k + 1)->v; + bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, ring + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + if (bmv3 == bmv4 || bmv1 == bmv4) + bmv4 = NULL; + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + else if (v->prev->ebev && v->prev->prev->ebev) { + /* finish off a sequence of beveled edges */ + i = v->prev->index; + f = boundvert_rep_face(v->prev); + for (k = ns2 + (ns % 2); k < ns; k++) { + bmv1 = mesh_vert(vm, i, ring, k)->v; + bmv2 = mesh_vert(vm, i, ring, k + 1)->v; + bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, ring + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + if (bmv2 == bmv3) { + bmv3 = bmv4; + bmv4 = NULL; + } + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + } while ((v = v->next) != vm->boundstart); + } + + /* Make center ngon if odd number of segments and fully beveled */ + if (ns % 2 == 1 && vm->count == bv->selcount) { + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + do { + i = v->index; + BLI_assert(v->ebev); + BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v); + } while ((v = v->next) != vm->boundstart); + f = boundvert_rep_face(vm->boundstart); + bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + BLI_array_free(vv); + } + + /* Make 'rest-of-vmesh' polygon if not fully beveled */ + if (vm->count > bv->selcount) { + int j; + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + f = boundvert_rep_face(v); + j = 0; + do { + i = v->index; + if (v->ebev) { + if (!v->prev->ebev) { + for (k = 0; k < ns2; k++) { + bmv1 = mesh_vert(vm, i, ns2, k)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, k)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + } + } + bmv1 = mesh_vert(vm, i, ns2, ns2)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, ns2)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + if (!v->next->ebev) { + for (k = ns - ns2; k < ns; k++) { + bmv1 = mesh_vert(vm, i, ns2, k)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, k)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + } + } + } + else { + BLI_assert(mesh_vert(vm, i, 0, 0)->v != NULL); + BLI_array_append(vv, mesh_vert(vm, i, 0, 0)->v); + j++; + } + } while ((v = v->next) != vm->boundstart); + if (vv[0] == vv[j - 1]) + j--; + bev_create_ngon(bm, vv, j, f); + + BLI_array_free(vv); + } +} + +static BMFace *bevel_build_poly_ex(BMesh *bm, BevVert *bv) +{ + BMFace *f; + int n, k; + VMesh *vm = bv->vmesh; + BoundVert *v; + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + n = 0; + do { + /* accumulate vertices for vertex ngon */ + BLI_array_append(vv, v->nv.v); + n++; + if (v->ebev && v->ebev->seg > 1) { + for (k = 1; k < v->ebev->seg; k++) { + BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v); + n++; + } + } + } while ((v = v->next) != vm->boundstart); + if (n > 2) { + f = bev_create_ngon(bm, vv, n, boundvert_rep_face(v)); + } + else { + f = NULL; + } + BLI_array_free(vv); + return f; +} + +static void bevel_build_poly(BMesh *bm, BevVert *bv) +{ + bevel_build_poly_ex(bm, bv); +} + +static void bevel_build_trifan(BMesh *bm, BevVert *bv) +{ + BMFace *f; + BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1); + + f = bevel_build_poly_ex(bm, bv); + + if (f) { + /* we have a polygon which we know starts at the previous vertex, make it into a fan */ + BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev; + BMVert *v_fan = l_fan->v; + + while (f->len > 3) { + BMLoop *l_new; + BMFace *f_new; + BLI_assert(v_fan == l_fan->v); + f_new = BM_face_split(bm, f, l_fan->v, l_fan->next->next->v, &l_new, NULL, FALSE); + + if (f_new->len > f->len) { + f = f_new; + if (l_new->v == v_fan) { l_fan = l_new; } + else if (l_new->next->v == v_fan) { l_fan = l_new->next; } + else if (l_new->prev->v == v_fan) { l_fan = l_new->prev; } + else { BLI_assert(0); } + } + else { + if (l_fan->v == v_fan) { l_fan = l_fan; } + else if (l_fan->next->v == v_fan) { l_fan = l_fan->next; } + else if (l_fan->prev->v == v_fan) { l_fan = l_fan->prev; } + else { BLI_assert(0); } + } + } + } +} + +static void bevel_build_quadstrip(BMesh *bm, BevVert *bv) +{ + BMFace *f; + BLI_assert(bv->selcount == 2); + + f = bevel_build_poly_ex(bm, bv); + + if (f) { + /* we have a polygon which we know starts at this vertex, make it into strips */ + EdgeHalf *eh_a = bv->vmesh->boundstart->elast; + EdgeHalf *eh_b = next_bev(bv, eh_a->next); /* since (selcount == 2) we know this is valid */ + BMLoop *l_a = BM_face_vert_share_loop(f, eh_a->rightv->nv.v); + BMLoop *l_b = BM_face_vert_share_loop(f, eh_b->leftv->nv.v); + int split_count = bv->vmesh->seg + 1; /* ensure we don't walk past the segments */ + + while (f->len > 4 && split_count > 0) { + BMLoop *l_new; + BLI_assert(l_a->f == f); + BLI_assert(l_b->f == f); + + if (l_a-> v == l_b->v || l_a->next == l_b) { + /* l_a->v and l_b->v can be the same or such that we'd make a 2-vertex poly */ + l_a = l_a->prev; + l_b = l_b->next; + } + else { + BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE); + f = l_new->f; + + /* walk around the new face to get the next verts to split */ + l_a = l_new->prev; + l_b = l_new->next->next; + } + split_count--; + } + } +} + +/* Given that the boundary is built, now make the actual BMVerts + * for the boundary and the interior of the vertex mesh. */ +static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv) +{ + VMesh *vm = bv->vmesh; + BoundVert *v, *weld1, *weld2; + int n, ns, ns2, i, k, weld; + float *va, *vb, co[3]; + +#ifdef USE_ALTERNATE_ADJ + /* ordered as follows (orig, prev, center, next)*/ + float quad_plane[4][3]; + float quad_orig_a[4][3]; + float quad_orig_b[4][3]; + const int is_odd = (vm->seg % 2); +#else + float midco[3]; +#endif + +#ifdef USE_ALTERNATE_ADJ + /* the rest are initialized inline, this remains the same for all */ + /* NOTE; in this usage we only interpolate on the 'V' so cent and next points are unused (2,3)*/ + vmesh_cent(vm, quad_plane[2]); + copy_v3_v3(quad_orig_a[2], bv->v->co); + copy_v3_v3(quad_orig_b[2], bv->v->co); +#endif + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + + vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, n * (ns2 + 1) * (ns + 1) * sizeof(NewVert)); + + /* special case: two beveled ends welded together */ + weld = (bv->selcount == 2) && (vm->count == 2); + weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */ + + /* make (i, 0, 0) mesh verts for all i */ + v = vm->boundstart; + do { + i = v->index; + copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, v->nv.co); + create_mesh_bmvert(bm, vm, i, 0, 0, bv->v); + v->nv.v = mesh_vert(vm, i, 0, 0)->v; + if (weld && v->ebev) { + if (!weld1) + weld1 = v; + else + weld2 = v; + } + } while ((v = v->next) != vm->boundstart); + + /* copy other ends to (i, 0, ns) for all i, and fill in profiles for beveled edges */ + v = vm->boundstart; + do { + i = v->index; + copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0); + if (v->ebev) { + +#ifdef USE_ALTERNATE_ADJ + copy_v3_v3(quad_plane[0], v->nv.co); + mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co); + /* quad[2] is set */ + mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co); + + /* orig 'A' */ + copy_v3_v3(quad_orig_a[0], v->nv.co); /* only shared location between 2 quads */ + project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_a[1]); + project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_a[3]); + + /* orig 'B' */ + copy_v3_v3(quad_orig_b[3], v->next->nv.co); /* only shared location between 2 quads */ + project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_b[1]); + project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_b[0]); + + //bl_debug_draw_quad_add(UNPACK4(quad_plane)); + //bl_debug_draw_quad_add(UNPACK4(quad_orig_a)); + //bl_debug_draw_quad_add(UNPACK4(quad_orig_b)); +#endif /* USE_ALTERNATE_ADJ */ + +#ifdef USE_ALTERNATE_ADJ + for (k = 1; k < ns; k++) { + float uv[2]; + float fac; + float co_plane[3]; + float co_orig[3]; + + /* quad_plane */ + get_point_uv(uv, v->ebev->seg, 0, k); + get_point_on_round_edge(uv, quad_plane, co_plane); + + /* quad_orig */ + /* each half has different UV's */ + if (k <= ns2) { + get_point_uv(uv, v->ebev->seg, 0, k); + get_point_on_round_edge(uv, quad_orig_a, co_orig); + } + else { + get_point_uv(uv, v->ebev->seg, 0, (k - ns2) - (is_odd ? 0.5f : 0.0f)); + get_point_on_round_edge(uv, quad_orig_b, co_orig); + uv[1] = 1.0f - uv[1]; /* so we can get the factor */ + } + fac = get_point_uv_factor(uv); + + /* done. interp */ + interp_v3_v3v3(co, co_plane, co_orig, fac); + copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); + if (!weld) + create_mesh_bmvert(bm, vm, i, 0, k, bv->v); + } +#else /* USE_ALTERNATE_ADJ */ + va = mesh_vert(vm, i, 0, 0)->co; + vb = mesh_vert(vm, i, 0, ns)->co; + project_to_edge(v->ebev->e, va, vb, midco); + for (k = 1; k < ns; k++) { + get_point_on_round_edge(v->ebev, k, va, midco, vb, co); + copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); + if (!weld) + create_mesh_bmvert(bm, vm, i, 0, k, bv->v); + } +#endif /* !USE_ALTERNATE_ADJ */ + } + } while ((v = v->next) != vm->boundstart); + + if (weld) { + vm->mesh_kind = M_NONE; + for (k = 1; k < ns; k++) { + va = mesh_vert(vm, weld1->index, 0, k)->co; + vb = mesh_vert(vm, weld2->index, 0, ns - k)->co; + mid_v3_v3v3(co, va, vb); + copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co); + create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v); + } + for (k = 1; k < ns; k++) + copy_mesh_vert(vm, weld2->index, 0, ns - k, weld1->index, 0, k); + } + + switch (vm->mesh_kind) { + case M_NONE: + /* do nothing */ + break; + case M_POLY: + bevel_build_poly(bm, bv); + break; + case M_ADJ: + bevel_build_rings(bm, bv); + break; + case M_TRI_FAN: + bevel_build_trifan(bm, bv); + break; + case M_QUAD_STRIP: + bevel_build_quadstrip(bm, bv); + break; + } +} + +/* take care, this flag isn't cleared before use, it just so happens that its not set */ +#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_elem_flag_enable( (bme)->l, BM_ELEM_TAG) +#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_elem_flag_disable( (bme)->l, BM_ELEM_TAG) +#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_elem_flag_test( (bme)->l, BM_ELEM_TAG) + +/* + * Construction around the vertex + */ +static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) +{ + BMEdge *bme; + BevVert *bv; + BMEdge *bme2, *unflagged_bme; + BMFace *f; + BMIter iter, iter2; + EdgeHalf *e; + int i, found_shared_face, ccw_test_sum; + int nsel = 0; + int ntot = 0; + + /* Gather input selected edges. + * Only bevel selected edges that have exactly two incident faces. + */ + + BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(bme, BM_ELEM_TAG)) { + BLI_assert(BM_edge_is_manifold(bme)); + nsel++; + } + ntot++; + } + + if (nsel == 0) { + /* signal this vert isn't being beveled */ + BM_elem_flag_disable(v, BM_ELEM_TAG); + return; + } + + /* avoid calling BM_vert_edge_count since we loop over edges already */ + // ntot = BM_vert_edge_count(v); + // BLI_assert(ntot == BM_vert_edge_count(v)); + + bv = (BevVert *)BLI_memarena_alloc(bp->mem_arena, (sizeof(BevVert))); + bv->v = v; + bv->edgecount = ntot; + bv->selcount = nsel; + bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, ntot * sizeof(EdgeHalf)); + bv->vmesh = (VMesh *)BLI_memarena_alloc(bp->mem_arena, sizeof(VMesh)); + bv->vmesh->seg = bp->seg; + BLI_ghash_insert(bp->vert_hash, v, bv); + + /* add edges to bv->edges in order that keeps adjacent edges sharing + * a face, if possible */ + i = 0; + bme = v->e; + BM_BEVEL_EDGE_TAG_ENABLE(bme); + e = &bv->edges[0]; + e->e = bme; + for (i = 0; i < ntot; i++) { + if (i > 0) { + /* find an unflagged edge bme2 that shares a face f with previous bme */ + found_shared_face = 0; + unflagged_bme = NULL; + BM_ITER_ELEM (bme2, &iter, v, BM_EDGES_OF_VERT) { + if (BM_BEVEL_EDGE_TAG_TEST(bme2)) + continue; + if (!unflagged_bme) + unflagged_bme = bme2; + BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) { + if (BM_face_edge_share_loop(f, bme)) { + found_shared_face = 1; + break; + } + } + if (found_shared_face) + break; + } + e = &bv->edges[i]; + if (found_shared_face) { + e->e = bme2; + e->fprev = f; + bv->edges[i - 1].fnext = f; + } + else { + e->e = unflagged_bme; + } + } + bme = e->e; + BM_BEVEL_EDGE_TAG_ENABLE(bme); + if (BM_elem_flag_test(bme, BM_ELEM_TAG)) { + e->is_bev = TRUE; + e->seg = bp->seg; + } + else { + e->is_bev = FALSE; + e->seg = 0; + } + e->is_rev = (bme->v2 == v); + e->offset = e->is_bev ? bp->offset : 0.0f; + } + /* find wrap-around shared face */ + BM_ITER_ELEM (f, &iter2, bme, BM_FACES_OF_EDGE) { + if (BM_face_edge_share_loop(f, bv->edges[0].e)) { + if (bv->edges[0].fnext == f) + continue; /* if two shared faces, want the other one now */ + bv->edges[ntot - 1].fnext = f; + bv->edges[0].fprev = f; + break; + } + } + + /* do later when we loop over edges */ +#if 0 + /* clear BEVEL_EDGE_TAG now that we are finished with it*/ + for (i = 0; i < ntot; i++) { + BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[i].e); + } +#endif + + /* if edge array doesn't go CCW around vertex from average normal side, + * reverse the array, being careful to reverse face pointers too */ + if (ntot > 1) { + ccw_test_sum = 0; + for (i = 0; i < ntot; i++) + ccw_test_sum += bev_ccw_test(bv->edges[i].e, bv->edges[(i + 1) % ntot].e, + bv->edges[i].fnext); + if (ccw_test_sum < 0) { + for (i = 0; i <= (ntot / 2) - 1; i++) { + SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]); + SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); + SWAP(BMFace *, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext); + } + if (ntot % 2 == 1) { + i = ntot / 2; + SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); + } + } + } + + for (i = 0, e = bv->edges; i < ntot; i++, e++) { + e->next = &bv->edges[(i + 1) % ntot]; + e->prev = &bv->edges[(i + ntot - 1) % ntot]; + BM_BEVEL_EDGE_TAG_DISABLE(e->e); + } + + build_boundary(bp->mem_arena, bv); + build_vmesh(bp->mem_arena, bm, bv); +} + +/* Face f has at least one beveled vertex. Rebuild f */ +static int bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) +{ + BMIter liter; + BMLoop *l, *lprev; + BevVert *bv; + BoundVert *v, *vstart, *vend; + EdgeHalf *e, *eprev; + VMesh *vm; + int i, k; + int do_rebuild = FALSE; + BMVert *bmv; + BMVert **vv = NULL; + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); + + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + lprev = l->prev; + bv = find_bevvert(bp, l->v); + e = find_edge_half(bv, l->e); + eprev = find_edge_half(bv, lprev->e); + BLI_assert(e != NULL && eprev != NULL); + vstart = eprev->leftv; + if (e->is_bev) + vend = e->rightv; + else + vend = e->leftv; + v = vstart; + vm = bv->vmesh; + BLI_array_append(vv, v->nv.v); + while (v != vend) { + if (vm->mesh_kind == M_NONE && v->ebev && v->ebev->seg > 1 && v->ebev != e && v->ebev != eprev) { + /* case of 3rd face opposite a beveled edge, with no vmesh */ + i = v->index; + e = v->ebev; + for (k = 1; k < e->seg; k++) { + bmv = mesh_vert(vm, i, 0, k)->v; + BLI_array_append(vv, bmv); + } + } + v = v->prev; + BLI_array_append(vv, v->nv.v); + } + + do_rebuild = TRUE; + } + else { + BLI_array_append(vv, l->v); + } + } + if (do_rebuild) { + BMFace *f_new = bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + /* don't select newly created boundary faces... */ + if (f_new) { + BM_elem_flag_disable(f_new, BM_ELEM_TAG); + } + } + + BLI_array_free(vv); + return do_rebuild; +} + +/* All polygons touching v need rebuilding because beveling v has made new vertices */ +static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *v) +{ + void *faces_stack[BM_DEFAULT_ITER_STACK_SIZE]; + int faces_len, f_index; + BMFace **faces = BM_iter_as_arrayN(bm, BM_FACES_OF_VERT, v, &faces_len, + faces_stack, BM_DEFAULT_ITER_STACK_SIZE); + + if (LIKELY(faces != NULL)) { + for (f_index = 0; f_index < faces_len; f_index++) { + BMFace *f = faces[f_index]; + if (bev_rebuild_polygon(bm, bp, f)) { + BM_face_kill(bm, f); + } + } + + if (faces != (BMFace **)faces_stack) { + MEM_freeN(faces); + } + } +} + + +/* + * Build the polygons along the selected Edge + */ +static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) +{ + BevVert *bv1, *bv2; + BMVert *bmv1, *bmv2, *bmv3, *bmv4, *bmv1i, *bmv2i, *bmv3i, *bmv4i; + VMesh *vm1, *vm2; + EdgeHalf *e1, *e2; + BMFace *f1, *f2, *f; + int k, nseg, i1, i2; + + if (!BM_edge_is_manifold(bme)) + return; + + bv1 = find_bevvert(bp, bme->v1); + bv2 = find_bevvert(bp, bme->v2); + + BLI_assert(bv1 && bv2); + + e1 = find_edge_half(bv1, bme); + e2 = find_edge_half(bv2, bme); + + BLI_assert(e1 && e2); + + /* v4 v3 + * \ / + * e->v1 - e->v2 + * / \ + * v1 v2 + */ + nseg = e1->seg; + BLI_assert(nseg > 0 && nseg == e2->seg); + + bmv1 = e1->leftv->nv.v; + bmv4 = e1->rightv->nv.v; + bmv2 = e2->rightv->nv.v; + bmv3 = e2->leftv->nv.v; + + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + + f1 = boundvert_rep_face(e1->leftv); + f2 = boundvert_rep_face(e1->rightv); + + if (nseg == 1) { + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f1); + } + else { + i1 = e1->leftv->index; + i2 = e2->leftv->index; + vm1 = bv1->vmesh; + vm2 = bv2->vmesh; + bmv1i = bmv1; + bmv2i = bmv2; + for (k = 1; k <= nseg; k++) { + bmv4i = mesh_vert(vm1, i1, 0, k)->v; + bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v; + f = (k <= nseg / 2 + (nseg % 2)) ? f1 : f2; + bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f); + bmv1i = bmv4i; + bmv2i = bmv3i; + } + } +} + +/** + * - Currently only bevels BM_ELEM_TAG'd verts and edges. + * + * - Newly created faces are BM_ELEM_TAG'd too, + * the caller needs to ensure this is cleared before calling + * if its going to use this face tag. + * + * \warning all tagged edges _must_ be manifold. + */ +void BM_mesh_bevel(BMesh *bm, const float offset, const float segments) +{ + BMIter iter; + BMVert *v; + BMEdge *e; + BevelParams bp = {NULL}; + + bp.offset = offset; + bp.seg = segments; + + if (bp.offset > 0) { + /* primary alloc */ + bp.vert_hash = BLI_ghash_ptr_new(__func__); + bp.mem_arena = BLI_memarena_new((1 << 16), __func__); + BLI_memarena_use_calloc(bp.mem_arena); + + /* The analysis of the input vertices and execution additional constructions */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + bevel_vert_construct(bm, &bp, v); + } + } + + /* Build polygons for edges */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + bevel_build_edge_polygons(bm, &bp, e); + } + } + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + bevel_rebuild_existing_polygons(bm, &bp, v); + } + } + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + BLI_assert(find_bevvert(&bp, v) != NULL); + BM_vert_kill(bm, v); + } + } + + /* primary free */ + BLI_ghash_free(bp.vert_hash, NULL, NULL); + BLI_memarena_free(bp.mem_arena); + } +} diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h new file mode 100644 index 00000000000..a80e4f3a4a2 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -0,0 +1,32 @@ +/* + * ***** 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): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BMESH_BEVEL_H__ +#define __BMESH_BEVEL_H__ + +/** \file blender/bmesh/tools/bmesh_bevel.h + * \ingroup bmesh + */ + +void BM_mesh_bevel(BMesh *bm, const float offset, const float segments); + +#endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h similarity index 86% rename from source/blender/bmesh/intern/bmesh_decimate.h rename to source/blender/bmesh/tools/bmesh_decimate.h index 04dc0cfd2ea..4a557c20ae3 100644 --- a/source/blender/bmesh/intern/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -23,7 +23,7 @@ #ifndef __BMESH_DECIMATE_H__ #define __BMESH_DECIMATE_H__ -/** \file blender/bmesh/intern/bmesh_decimate.h +/** \file blender/bmesh/tools/bmesh_decimate.h * \ingroup bmesh */ @@ -37,5 +37,8 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int BMEdge **einput_arr, const int einput_len); void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries); +/* these weights are accumulated so too high values may reach 'inf' too quickly */ +#define BM_MESH_DECIM_WEIGHT_MAX 100000.0f +#define BM_MESH_DECIM_WEIGHT_EPS (1.0f / BM_MESH_DECIM_WEIGHT_MAX) #endif /* __BMESH_DECIMATE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c similarity index 85% rename from source/blender/bmesh/intern/bmesh_decimate_collapse.c rename to source/blender/bmesh/tools/bmesh_decimate_collapse.c index feeb2a926f3..7c054d84405 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_collapse.c +/** \file blender/bmesh/tools/bmesh_decimate_collapse.c * \ingroup bmesh * * BMesh decimator that uses an edge collapse method. @@ -39,17 +39,21 @@ #include "BKE_customdata.h" #include "bmesh.h" -#include "bmesh_structure.h" #include "bmesh_decimate.h" /* own include */ +#include "../intern/bmesh_structure.h" + /* defines for testing */ #define USE_CUSTOMDATA #define USE_TRIANGULATE +#define USE_VERT_NORMAL_INTERP /* has the advantage that flipped faces don't mess up vertex normals */ /* these checks are for rare cases that we can't avoid since they are valid meshes still */ #define USE_SAFETY_CHECKS #define BOUNDARY_PRESERVE_WEIGHT 100.0f +#define OPTIMIZE_EPS 0.01f /* FLT_EPSILON is too small, see [#33106] */ +#define COST_INVALID FLT_MAX typedef enum CD_UseFlag { CD_DO_VERT = (1 << 0), @@ -96,7 +100,7 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) f = e->l->f; cross_v3_v3v3(edge_cross, edge_vector, f->no); - if (fabsf(normalize_v3(edge_cross)) > FLT_EPSILON) { + if (normalize_v3(edge_cross) > FLT_EPSILON) { Quadric q; BLI_quadric_from_v3_dist(&q, edge_cross, -dot_v3v3(edge_cross, e->v1->co)); BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT); @@ -122,7 +126,7 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], &vquadrics[BM_elem_index_get(e->v2)]); - if (BLI_quadric_optimize(&q, optimize_co)) { + if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) { return; /* all is good */ } else { @@ -130,6 +134,56 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], } } +static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) +{ + BMIter liter; + BMLoop *l; + unsigned int i; + + for (i = 0; i < 2; i++) { + /* loop over both verts */ + BMVert *v = *((&e->v1) + i); + + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + if (l->e != e && l->prev->e != e) { + float *co_prev = l->prev->v->co; + float *co_next = l->next->v->co; + float cross_exist[3]; + float cross_optim[3]; + +#if 1 + float vec_other[3]; /* line between the two outer verts, re-use for both cross products */ + float vec_exist[3]; /* before collapse */ + float vec_optim[3]; /* after collapse */ + + sub_v3_v3v3(vec_other, co_prev, co_next); + sub_v3_v3v3(vec_exist, co_prev, v->co); + sub_v3_v3v3(vec_optim, co_prev, optimize_co); + + cross_v3_v3v3(cross_exist, vec_other, vec_exist); + cross_v3_v3v3(cross_optim, vec_other, vec_optim); + + /* normalize isn't really needed, but ensures the value at a unit we can compare against */ + normalize_v3(cross_exist); + normalize_v3(cross_optim); +#else + normal_tri_v3(cross_exist, v->co, co_prev, co_next); + normal_tri_v3(cross_optim, optimize_co, co_prev, co_next); +#endif + + /* use a small value rather then zero so we don't flip a face in multiple steps + * (first making it zero area, then flipping again)*/ + if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) { + //printf("no flip\n"); + return TRUE; + } + } + } + } + + return FALSE; +} + static void bm_decim_build_edge_cost_single(BMEdge *e, const Quadric *vquadrics, const float *vweights, Heap *eheap, HeapNode **eheap_table) @@ -169,8 +223,8 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, } if (vweights) { - if ((vweights[BM_elem_index_get(e->v1)] < FLT_EPSILON) && - (vweights[BM_elem_index_get(e->v2)] < FLT_EPSILON)) + if ((vweights[BM_elem_index_get(e->v1)] >= BM_MESH_DECIM_WEIGHT_MAX) && + (vweights[BM_elem_index_get(e->v2)] >= BM_MESH_DECIM_WEIGHT_MAX)) { /* skip collapsing this edge */ eheap_table[BM_elem_index_get(e)] = NULL; @@ -190,14 +244,25 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, BLI_quadric_evaluate(q2, optimize_co)); } else { - cost = ((BLI_quadric_evaluate(q1, optimize_co) * vweights[BM_elem_index_get(e->v1)]) + - (BLI_quadric_evaluate(q2, optimize_co) * vweights[BM_elem_index_get(e->v2)])); + /* add 1.0 so planar edges are still weighted against */ + cost = (((BLI_quadric_evaluate(q1, optimize_co) + 1.0f) * vweights[BM_elem_index_get(e->v1)]) + + ((BLI_quadric_evaluate(q2, optimize_co) + 1.0f) * vweights[BM_elem_index_get(e->v2)])); } // print("COST %.12f\n"); eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e); } + +/* use this for degenerate cases - add back to the heap with an invalid cost, + * this way it may be calculated again if surrounding geometry changes */ +static void bm_decim_invalid_edge_cost_single(BMEdge *e, + Heap *eheap, HeapNode **eheap_table) +{ + BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL); + eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e); +} + static void bm_decim_build_edge_cost(BMesh *bm, const Quadric *vquadrics, const float *vweights, Heap *eheap, HeapNode **eheap_table) @@ -523,7 +588,7 @@ BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) #endif } -static int bm_edge_collapse_is_degenerate(BMEdge *e_first) +static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) { /* simply check that there is no overlap between faces and edges of each vert, * (excluding the 2 faces attached to 'e' and 'e' its self) */ @@ -627,11 +692,6 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e { BMVert *v_other; - /* disallow collapsing which results in degenerate cases */ - if (bm_edge_collapse_is_degenerate(e_clear)) { - return FALSE; - } - v_other = BM_edge_other_vert(e_clear, v_clear); BLI_assert(v_other != NULL); @@ -702,8 +762,11 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e BM_edge_kill(bm, e_clear); + v_other->head.hflag |= v_clear->head.hflag; BM_vert_splice(bm, v_clear, v_other); + e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; + e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag; BM_edge_splice(bm, e_a_other[0], e_a_other[1]); BM_edge_splice(bm, e_b_other[0], e_b_other[1]); @@ -748,8 +811,10 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e BM_edge_kill(bm, e_clear); + v_other->head.hflag |= v_clear->head.hflag; BM_vert_splice(bm, v_clear, v_other); + e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; BM_edge_splice(bm, e_a_other[0], e_a_other[1]); // BM_mesh_validate(bm); @@ -774,12 +839,28 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, float optimize_co[3]; float customdata_fac; +#ifdef USE_VERT_NORMAL_INTERP + float v_clear_no[3]; + copy_v3_v3(v_clear_no, e->v2->no); +#endif + + /* disallow collapsing which results in degenerate cases */ + if (UNLIKELY(bm_edge_collapse_is_degenerate_topology(e))) { + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ + return; + } + bm_decim_calc_target_co(e, optimize_co, vquadrics); + /* check if this would result in an overlapping face */ + if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) { + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ + return; + } + /* use for customdata merging */ if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); - #if 0 /* simple test for stupid collapse */ if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) { @@ -797,9 +878,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, int i; if (vweights) { - const int fac = CLAMPIS(customdata_fac, 0.0f, 1.0f); - vweights[BM_elem_index_get(v_other)] = (vweights[v_clear_index] * (1.0f - fac)) + - (vweights[BM_elem_index_get(v_other)] * fac); + vweights[BM_elem_index_get(v_other)] += vweights[v_clear_index]; } e = NULL; /* paranoid safety check */ @@ -822,7 +901,13 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, /* in fact face normals are not used for progressive updates, no need to update them */ // BM_vert_normal_update_all(v); +#ifdef USE_VERT_NORMAL_INTERP + interp_v3_v3v3(v_other->no, v_other->no, v_clear_no, customdata_fac); + normalize_v3(v_other->no); +#else BM_vert_normal_update(v_other); +#endif + /* update error costs and the eheap */ if (LIKELY(v_other->e)) { @@ -835,7 +920,10 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first); } -#if 0 + /* this block used to be disabled, + * but enable now since surrounding faces may have been + * set to COST_INVALID because of a face overlap that no longer occurs */ +#if 1 /* optional, update edges around the vertex face fan */ { BMIter liter; @@ -850,13 +938,17 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); - bm_decim_build_edge_cost_single(e_outer, vquadrics, eheap, eheap_table); + bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table); } } } /* end optional update */ #endif } + else { + /* add back with a high cost */ + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); + } } @@ -867,7 +959,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, * \brief BM_mesh_decimate * \param bm The mesh * \param factor face count multiplier [0 - 1] - * \param vertex_weights Optional array of vertex aligned weights [0 - 1], + * \param vweights Optional array of vertex aligned weights [0 - 1], * a vertex group is the usual source for this. */ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate) @@ -912,7 +1004,10 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c #endif /* iterative edge collapse and maintain the eheap */ - while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == FALSE)) { + while ((bm->totface > face_tot_target) && + (BLI_heap_is_empty(eheap) == FALSE) && + (BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID)) + { // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); BMEdge *e = BLI_heap_popmin(eheap); BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */ diff --git a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c similarity index 97% rename from source/blender/bmesh/intern/bmesh_decimate_dissolve.c rename to source/blender/bmesh/tools/bmesh_decimate_dissolve.c index d1371a18160..f67f01e4585 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_dissolve.c +/** \file blender/bmesh/tools/bmesh_decimate_dissolve.c * \ingroup bmesh * * BMesh decimator that dissolves flat areas into polygons (ngons). @@ -69,9 +69,6 @@ static int dissolve_elem_cmp(const void *a1, const void *a2) return 0; } -/** - * \param do_all_verts Collapse all verts between 2 faces - don't check their edge angle. - */ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len) @@ -231,8 +228,8 @@ void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_ int vinput_len; int einput_len; - BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len); - BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len); + BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len, NULL, 0); + BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len, NULL, 0); BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, vinput_arr, vinput_len, diff --git a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c similarity index 97% rename from source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c rename to source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 68c0652d2c4..acdab2510a4 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_unsubdivide.c +/** \file blender/bmesh/tools/bmesh_decimate_unsubdivide.c * \ingroup bmesh * * BMesh decimator that uses a grid un-subdivide method. @@ -247,9 +247,9 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int #ifdef USE_WALKER /* Walk over selected elements starting at active */ BMW_init(&walker, bm, BMW_CONNECTED_VERTEX, - ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP, - BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ - BMW_NIL_LAY); + ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP, + BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ + BMW_NIL_LAY); BLI_assert(walker.order == BMW_BREADTH_FIRST); for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) { diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 374f6385ea7..44e74e320cc 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -844,7 +844,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector& a * This function returns the aspet ration from the Collada camera. * * Note:COLLADA allows to specify either XFov, or YFov alone. - * In tghat case the aspect ratio can be determined from + * In that case the aspect ratio can be determined from * the viewport aspect ratio (which is 1:1 ?) * XXX: check this: its probably wrong! * If both values are specified, then the aspect ration is simply xfov/yfov diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 1c4f0974c6d..084f71e0afc 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -552,8 +552,8 @@ bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScen } /** When this method is called, the writer must handle all nodes contained in the -* library nodes. -* \return The writer should return true, if writing succeeded, false otherwise.*/ + * library nodes. + * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes) { if (mImportStage != General) diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h index e878a5a5b48..d54b8db9f00 100644 --- a/source/blender/collada/DocumentImporter.h +++ b/source/blender/collada/DocumentImporter.h @@ -81,8 +81,8 @@ public: /** * This method will be called if an error in the loading process occurred and the loader cannot * continue to load. The writer should undo all operations that have been performed. - \param errorMessage A message containing informations about the error that occurred. - */ + * \param errorMessage A message containing informations about the error that occurred. + */ void cancel(const COLLADAFW::String& errorMessage); /** This is the method called. The writer hast to prepare to receive data.*/ diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index 2e0c0f1ea57..aba290f5ce4 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -61,7 +61,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) if (not_yet_exported) { - ImBuf *imbuf = BKE_image_get_ibuf(image, NULL); + ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (!imbuf) { fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name); return; @@ -147,6 +147,8 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) img.add(mSW); fprintf(stdout, "Collada export: Added image: %s\n", export_file); mImages.push_back(translated_name); + + BKE_image_release_ibuf(image, imbuf, NULL); } } diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp index 5a1d8b7602a..4aece997f72 100644 --- a/source/blender/collada/MaterialExporter.cpp +++ b/source/blender/collada/MaterialExporter.cpp @@ -70,7 +70,7 @@ void MaterialsExporter::operator()(Material *ma, Object *ob) { std::string name(id_name(ma)); - openMaterial(get_material_id(ma), get_material_id(ma)); + openMaterial(get_material_id(ma), translate_id(name)); std::string efid = translate_id(name) + "-effect"; addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid)); diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 8337a977b3b..de8d1e85eb9 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -589,7 +589,7 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) for (int i = 0; i < edge_count; i++, med++) { med->bweight = 0; med->crease = 0; - med->flag = 0; + med->flag |= ME_LOOSEEDGE; med->v1 = indices[2 * i]; med->v2 = indices[2 * i + 1]; } diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp index d10cd7378e9..61793589422 100644 --- a/source/blender/collada/TransformReader.cpp +++ b/source/blender/collada/TransformReader.cpp @@ -84,7 +84,7 @@ void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[ COLLADAFW::Rotate *ro = (COLLADAFW::Rotate *)tm; COLLADABU::Math::Vector3& axis = ro->getRotationAxis(); const float angle = (float)DEG2RAD(ro->getRotationAngle()); - const float ax[] = {axis[0], axis[1], axis[2]}; + const float ax[] = {(float)axis[0], (float)axis[1], (float)axis[2]}; // float quat[4]; // axis_angle_to_quat(quat, axis, angle); // quat_to_mat4(m, quat); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 35844b549de..7bdda387d5e 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -139,7 +139,7 @@ Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob, BC_export_mesh_type e { Mesh *tmpmesh; CustomDataMask mask = CD_MASK_MESH; - DerivedMesh *dm; + DerivedMesh *dm = NULL; switch (export_mesh_type) { case BC_MESH_TYPE_VIEW: { dm = mesh_create_derived_view(scene, ob, mask); @@ -151,7 +151,7 @@ Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob, BC_export_mesh_type e } } - tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here + tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here DM_to_mesh(dm, tmpmesh, ob); dm->release(dm); return tmpmesh; diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index b3e76a287ea..8259cb6f297 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -267,6 +267,8 @@ set(SRC nodes/COM_MathNode.h nodes/COM_MapValueNode.cpp nodes/COM_MapValueNode.h + nodes/COM_MapRangeNode.cpp + nodes/COM_MapRangeNode.h operations/COM_NormalizeOperation.cpp operations/COM_NormalizeOperation.h @@ -572,6 +574,8 @@ set(SRC operations/COM_SetAlphaOperation.h operations/COM_MapValueOperation.cpp operations/COM_MapValueOperation.h + operations/COM_MapRangeOperation.cpp + operations/COM_MapRangeOperation.h # Distort operation operations/COM_TranslateOperation.h diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 2b09c9d5b8c..9c4a32f20c9 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -83,6 +83,7 @@ #include "COM_LuminanceMatteNode.h" #include "COM_MapUVNode.h" #include "COM_MapValueNode.h" +#include "COM_MapRangeNode.h" #include "COM_MaskNode.h" #include "COM_MathNode.h" #include "COM_MixNode.h" @@ -351,6 +352,9 @@ Node *Converter::convert(bNode *b_node, bool fast) case CMP_NODE_MAP_VALUE: node = new MapValueNode(b_node); break; + case CMP_NODE_MAP_RANGE: + node = new MapRangeNode(b_node); + break; case CMP_NODE_TRANSFORM: node = new TransformNode(b_node); break; diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index 0553aebbba6..ffc36281874 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -352,7 +352,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph) startEvaluated = true; numberEvaluated++; - WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); + if (bTree->update_draw) + bTree->update_draw(bTree->udh); } else if (state == COM_ES_SCHEDULED) { finished = false; diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h index c7a7d06134e..00104c24194 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.h +++ b/source/blender/compositor/intern/COM_ExecutionGroup.h @@ -193,7 +193,7 @@ private: /** * @brief try to schedule a specific chunk. - * @note scheduling succeeds when all input requirements are met and the chunks hasen't been scheduled yet. + * @note scheduling succeeds when all input requirements are met and the chunks hasn't been scheduled yet. * @param graph * @param xChunk * @param yChunk @@ -245,7 +245,7 @@ public: /** * @brief add an operation to this ExecutionGroup - * @note this method will add input of the operations recursivly + * @note this method will add input of the operations recursively * @note this method can create multiple ExecutionGroup's * @param system * @param operation @@ -369,7 +369,7 @@ public: /** * @brief this method determines the MemoryProxy's where this execution group depends on. * @note After this method determineDependingAreaOfInterest can be called to determine - * @note the area of the MemoryProxy.creator thas has to be executed. + * @note the area of the MemoryProxy.creator that has to be executed. * @param memoryProxies result */ void determineDependingMemoryProxies(vector *memoryProxies); diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index c6e0f6c2cfb..1ec4ac7699b 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -247,9 +247,14 @@ void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation) */ static void debug_check_node_connections(Node *node) { + /* note: connected inputs are not checked here, + * it would break quite a lot and such inputs are ignored later anyway + */ +#if 0 for (int i = 0; i < node->getNumberOfInputSockets(); ++i) { BLI_assert(!node->getInputSocket(i)->isConnected()); } +#endif for (int i = 0; i < node->getNumberOfOutputSockets(); ++i) { BLI_assert(!node->getOutputSocket(i)->isConnected()); } diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index 300d7ef1952..d49bb5f96fb 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -137,18 +137,26 @@ void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocke graph->addOperation(operation); } -/* when a node has no valid data (missing image or group pointer) */ +NodeOperation *Node::convertToOperations_invalid_index(ExecutionSystem *graph, int index) +{ + const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; + SetColorOperation *operation = new SetColorOperation(); + operation->setChannels(warning_color); + + /* link the operation */ + this->getOutputSocket(index)->relinkConnections(operation->getOutputSocket()); + graph->addOperation(operation); + return operation; +} + +/* when a node has no valid data (missing image / group pointer, or missing renderlayer from EXR) */ void Node::convertToOperations_invalid(ExecutionSystem *graph, CompositorContext *context) { /* this is a really bad situation - bring on the pink! - so artists know this is bad */ - const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; int index; vector &outputsockets = this->getOutputSockets(); for (index = 0; index < outputsockets.size(); index++) { - SetColorOperation *operation = new SetColorOperation(); - this->getOutputSocket(index)->relinkConnections(operation->getOutputSocket()); - operation->setChannels(warning_color); - graph->addOperation(operation); + convertToOperations_invalid_index(graph, index); } } diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h index 468a95ed434..c098d6da32b 100644 --- a/source/blender/compositor/intern/COM_Node.h +++ b/source/blender/compositor/intern/COM_Node.h @@ -105,6 +105,10 @@ public: */ void addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex); + /** + * Create dummy warning operation, use when we can't get the source data. + */ + NodeOperation *convertToOperations_invalid_index(ExecutionSystem *graph, int index); /** * when a node has no valid data (missing image or a group nodes ID pointer is NULL) * call this function from #convertToOperations, this way the node sockets are converted diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index 42d90eca38f..f856d8e6a11 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -77,7 +77,7 @@ private: ThreadMutex m_mutex; /** - * @brief reference to the editing bNodeTree only used for break callback + * @brief reference to the editing bNodeTree, used for break and update callback */ const bNodeTree *m_btree; @@ -247,6 +247,10 @@ public: return this->m_btree->test_break(this->m_btree->tbh); } + inline void updateDraw() { + if (this->m_btree->update_draw) + this->m_btree->update_draw(this->m_btree->udh); + } protected: NodeOperation(); diff --git a/source/blender/compositor/intern/COM_WorkPackage.h b/source/blender/compositor/intern/COM_WorkPackage.h index 953a164e95e..2bb124a1c84 100644 --- a/source/blender/compositor/intern/COM_WorkPackage.h +++ b/source/blender/compositor/intern/COM_WorkPackage.h @@ -44,7 +44,7 @@ private: unsigned int m_chunkNumber; public: /** - * @constructor + * constructor * @param group the ExecutionGroup * @param chunkNumber the number of the chunk */ diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index 4f120ea5a6e..6a4987c2075 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -31,6 +31,7 @@ #include "COM_FastGaussianBlurOperation.h" #include "COM_MathBaseOperation.h" #include "COM_SetValueOperation.h" +#include "COM_GammaCorrectOperation.h" BlurNode::BlurNode(bNode *editorNode) : Node(editorNode) { @@ -48,16 +49,17 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value; CompositorQuality quality = context->getQuality(); - + NodeOperation *input_operation = NULL, *output_operation = NULL; + if (data->filtertype == R_FILTER_FAST_GAUSS) { FastGaussianBlurOperation *operationfgb = new FastGaussianBlurOperation(); operationfgb->setData(data); operationfgb->setbNode(editorNode); - this->getInputSocket(0)->relinkConnections(operationfgb->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operationfgb->getInputSocket(1), 1, graph); - this->getOutputSocket(0)->relinkConnections(operationfgb->getOutputSocket(0)); graph->addOperation(operationfgb); - addPreviewOperation(graph, context, operationfgb->getOutputSocket()); + + input_operation = operationfgb; + output_operation = operationfgb; } else if (editorNode->custom1 & CMP_NODEFLAG_BLUR_VARIABLE_SIZE) { MathAddOperation *clamp = new MathAddOperation(); @@ -93,48 +95,68 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co operation->setData(data); operation->setbNode(editorNode); operation->setQuality(quality); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); addLink(graph, operationy->getOutputSocket(), operation->getInputSocket(1)); graph->addOperation(operation); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, context, operation->getOutputSocket()); + + output_operation = operation; + input_operation = operation; } else if (!data->bokeh) { GaussianXBlurOperation *operationx = new GaussianXBlurOperation(); operationx->setData(data); operationx->setbNode(editorNode); operationx->setQuality(quality); - this->getInputSocket(0)->relinkConnections(operationx->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operationx->getInputSocket(1), 1, graph); graph->addOperation(operationx); GaussianYBlurOperation *operationy = new GaussianYBlurOperation(); operationy->setData(data); operationy->setbNode(editorNode); operationy->setQuality(quality); - this->getOutputSocket(0)->relinkConnections(operationy->getOutputSocket()); + graph->addOperation(operationy); addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1)); - addPreviewOperation(graph, context, operationy->getOutputSocket()); if (!connectedSizeSocket) { operationx->setSize(size); operationy->setSize(size); } + + input_operation = operationx; + output_operation = operationy; } else { GaussianBokehBlurOperation *operation = new GaussianBokehBlurOperation(); operation->setData(data); operation->setbNode(editorNode); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); operation->setQuality(quality); graph->addOperation(operation); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, context, operation->getOutputSocket()); if (!connectedSizeSocket) { operation->setSize(size); } + + input_operation = operation; + output_operation = operation; + } + + if (data->gamma) { + GammaCorrectOperation *correct = new GammaCorrectOperation(); + GammaUncorrectOperation *inverse = new GammaUncorrectOperation(); + + this->getInputSocket(0)->relinkConnections(correct->getInputSocket(0), 0, graph); + addLink(graph, correct->getOutputSocket(), input_operation->getInputSocket(0)); + addLink(graph, output_operation->getOutputSocket(), inverse->getInputSocket(0)); + this->getOutputSocket()->relinkConnections(inverse->getOutputSocket()); + graph->addOperation(correct); + graph->addOperation(inverse); + + addPreviewOperation(graph, context, inverse->getOutputSocket()); + } + else { + this->getInputSocket(0)->relinkConnections(input_operation->getInputSocket(0), 0, graph); + this->getOutputSocket()->relinkConnections(output_operation->getOutputSocket()); + addPreviewOperation(graph, context, output_operation->getOutputSocket()); } } diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index 4ebd28d710a..4293e344c65 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -73,7 +73,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c /* force a load, we assume iuser index will be set OK anyway */ if (image && image->type == IMA_TYPE_MULTILAYER) { bool is_multilayer_ok = false; - BKE_image_get_ibuf(image, imageuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL); if (image->rr) { RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer); if (rl) { @@ -83,6 +83,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c is_multilayer_ok = true; for (index = 0; index < numberOfOutputs; index++) { + NodeOperation *operation = NULL; socket = this->getOutputSocket(index); if (socket->isConnected() || index == 0) { bNodeSocket *bnodeSocket = socket->getbNodeSocket(); @@ -91,7 +92,6 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex); if (rpass) { - NodeOperation *operation = NULL; imageuser->pass = passindex; switch (rpass->channels) { case 1: @@ -105,19 +105,25 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c case 4: operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR); break; - default: - /* XXX add a dummy operation? */ + /* dummy operation is added below */ break; } + if (index == 0 && operation) { addPreviewOperation(graph, context, operation->getOutputSocket()); } } } + + /* incase we can't load the layer */ + if (operation == NULL) { + convertToOperations_invalid_index(graph, index); + } } } } + BKE_image_release_ibuf(image, ibuf, NULL); /* without this, multilayer that fail to load will crash blender [#32490] */ if (is_multilayer_ok == false) { diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.cpp b/source/blender/compositor/nodes/COM_MapRangeNode.cpp new file mode 100644 index 00000000000..232be3d41b0 --- /dev/null +++ b/source/blender/compositor/nodes/COM_MapRangeNode.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#include "COM_MapRangeNode.h" + +#include "COM_MapRangeOperation.h" +#include "COM_ExecutionSystem.h" + +MapRangeNode::MapRangeNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void MapRangeNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + InputSocket *valueSocket = this->getInputSocket(0); + InputSocket *sourceMinSocket = this->getInputSocket(1); + InputSocket *sourceMaxSocket = this->getInputSocket(2); + InputSocket *destMinSocket = this->getInputSocket(3); + InputSocket *destMaxSocket = this->getInputSocket(4); + OutputSocket *outputSocket = this->getOutputSocket(0); + + MapRangeOperation *operation = new MapRangeOperation(); + + valueSocket->relinkConnections(operation->getInputSocket(0), 0, graph); + sourceMinSocket->relinkConnections(operation->getInputSocket(1), 1, graph); + sourceMaxSocket->relinkConnections(operation->getInputSocket(2), 2, graph); + destMinSocket->relinkConnections(operation->getInputSocket(3), 3, graph); + destMaxSocket->relinkConnections(operation->getInputSocket(4), 4, graph); + outputSocket->relinkConnections(operation->getOutputSocket(0)); + + operation->setUseClamp(this->getbNode()->custom1); + + graph->addOperation(operation); +} diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.h b/source/blender/compositor/nodes/COM_MapRangeNode.h new file mode 100644 index 00000000000..6667720be3d --- /dev/null +++ b/source/blender/compositor/nodes/COM_MapRangeNode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#ifndef __COM_MAPRANGENODE_H__ +#define __COM_MAPRANGENODE_H__ + +#include "COM_Node.h" +#include "DNA_node_types.h" +/** + * @brief MapRangeNode + * @ingroup Node + */ +class MapRangeNode : public Node { +public: + MapRangeNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); +}; + +#endif /* __COM_MAPRANGENODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_MuteNode.cpp b/source/blender/compositor/nodes/COM_MuteNode.cpp index 4502dcf469c..de12fff3591 100644 --- a/source/blender/compositor/nodes/COM_MuteNode.cpp +++ b/source/blender/compositor/nodes/COM_MuteNode.cpp @@ -43,6 +43,10 @@ void MuteNode::reconnect(ExecutionSystem *graph, OutputSocket *output) if (input->getDataType() == output->getDataType()) { if (input->isConnected()) { output->relinkConnections(input->getConnection()->getFromSocket(), false); + /* output connections have been redirected, + * remove the input connection to completely unlink the node. + */ + input->unlinkConnections(graph); return; } } diff --git a/source/blender/compositor/nodes/COM_NormalNode.cpp b/source/blender/compositor/nodes/COM_NormalNode.cpp index e00e71e50e9..fbfff8386d0 100644 --- a/source/blender/compositor/nodes/COM_NormalNode.cpp +++ b/source/blender/compositor/nodes/COM_NormalNode.cpp @@ -41,9 +41,14 @@ void NormalNode::convertToOperations(ExecutionSystem *graph, CompositorContext * SetVectorOperation *operationSet = new SetVectorOperation(); bNodeSocket *insock = (bNodeSocket *)editorNode->outputs.first; bNodeSocketValueVector *dval = (bNodeSocketValueVector *)insock->default_value; - operationSet->setX(dval->value[0]); - operationSet->setY(dval->value[1]); - operationSet->setZ(dval->value[2]); + float normal[3]; + + /* animation can break normalization, this restores it */ + normalize_v3_v3(normal, dval->value); + + operationSet->setX(normal[0]); + operationSet->setY(normal[1]); + operationSet->setZ(normal[2]); operationSet->setW(0.0f); outputSocket->relinkConnections(operationSet->getOutputSocket(0)); diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp index 921b9e63a73..3b1871b307b 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp @@ -41,6 +41,12 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte * otherwise, it overwrites the output files just * scrubbing through the timeline when the compositor updates. */ + + /* still, need to unlink input sockets to remove the node from the graph completely */ + int num_inputs = getNumberOfInputSockets(); + for (int i = 0; i < num_inputs; ++i) { + getInputSocket(i)->unlinkConnections(graph); + } return; } diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cpp b/source/blender/compositor/nodes/COM_ScaleNode.cpp index c51782b77af..6f7bd33db6f 100644 --- a/source/blender/compositor/nodes/COM_ScaleNode.cpp +++ b/source/blender/compositor/nodes/COM_ScaleNode.cpp @@ -26,6 +26,7 @@ #include "COM_ExecutionSystem.h" #include "BKE_node.h" #include "COM_SetValueOperation.h" +#include "COM_SetSamplerOperation.h" ScaleNode::ScaleNode(bNode *editorNode) : Node(editorNode) { @@ -38,7 +39,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c InputSocket *inputXSocket = this->getInputSocket(1); InputSocket *inputYSocket = this->getInputSocket(2); OutputSocket *outputSocket = this->getOutputSocket(0); + BaseScaleOperation *scaleoperation = NULL; bNode *bnode = this->getbNode(); + switch (bnode->custom1) { case CMP_SCALE_RELATIVE: { ScaleOperation *operation = new ScaleOperation(); @@ -46,8 +49,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph); inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); + + scaleoperation = operation; } break; case CMP_SCALE_SCENEPERCENT: { @@ -57,9 +60,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); addLink(graph, scaleFactorOperation->getOutputSocket(), operation->getInputSocket(1)); addLink(graph, scaleFactorOperation->getOutputSocket(), operation->getInputSocket(2)); - outputSocket->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(scaleFactorOperation); - graph->addOperation(operation); + + scaleoperation = operation; } break; @@ -75,9 +78,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c operation->setNewWidth(rd->xsch * rd->size / 100.0f); operation->setNewHeight(rd->ysch * rd->size / 100.0f); inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); operation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true); - graph->addOperation(operation); + + scaleoperation = operation; } break; @@ -87,9 +90,12 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph); inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); + + scaleoperation = operation; } break; } + + outputSocket->relinkConnections(scaleoperation->getOutputSocket(0)); + graph->addOperation(scaleoperation); } diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp index b28ee3eade1..a579503a829 100644 --- a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp +++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp @@ -72,6 +72,8 @@ void Stabilize2dNode::convertToOperations(ExecutionSystem *graph, CompositorCont addLink(graph, scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1)); addLink(graph, scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2)); + scaleOperation->setSampler((PixelSampler)this->getbNode()->custom1); + addLink(graph, scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0)); addLink(graph, angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1)); rotateOperation->setDoDegree2RadConversion(false); diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp index 16c19f3ebaa..4f9cd771988 100644 --- a/source/blender/compositor/operations/COM_CropOperation.cpp +++ b/source/blender/compositor/operations/COM_CropOperation.cpp @@ -58,6 +58,12 @@ void CropBaseOperation::updateArea() this->m_ymax = max(this->m_settings->y1, this->m_settings->y2) + 1; this->m_ymin = min(this->m_settings->y1, this->m_settings->y2); } + else { + this->m_xmax = 0; + this->m_xmin = 0; + this->m_ymax = 0; + this->m_ymin = 0; + } } void CropBaseOperation::initExecution() diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index 4bdb2591cb7..9231261986d 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -230,6 +230,7 @@ FastGaussianBlurValueOperation::FastGaussianBlurValueOperation() : NodeOperation this->m_iirgaus = NULL; this->m_inputprogram = NULL; this->m_sigma = 1.0f; + this->m_overlay = 0; setComplex(true); } @@ -281,7 +282,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect) if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) { float *src = newBuf->getBuffer(); float *dst = copy->getBuffer(); - for (int i = copy->getWidth() * copy->getHeight() * COM_NUMBER_OF_CHANNELS; i != 0; i--, src++, dst++) { + for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) { if (*src < *dst) { *dst = *src; } @@ -290,7 +291,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect) else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) { float *src = newBuf->getBuffer(); float *dst = copy->getBuffer(); - for (int i = copy->getWidth() * copy->getHeight() * COM_NUMBER_OF_CHANNELS; i != 0; i--, src++, dst++) { + for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) { if (*src > *dst) { *dst = *src; } diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp b/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp index af990f4f3e0..8f92dc02a57 100644 --- a/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp +++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp @@ -48,15 +48,13 @@ void GammaCorrectOperation::executePixel(float output[4], float x, float y, Pixe output[0] = inputColor[0] > 0.0f ? inputColor[0] * inputColor[0] : 0.0f; output[1] = inputColor[1] > 0.0f ? inputColor[1] * inputColor[1] : 0.0f; output[2] = inputColor[2] > 0.0f ? inputColor[2] * inputColor[2] : 0.0f; - - inputColor[0] *= inputColor[3]; - inputColor[1] *= inputColor[3]; - inputColor[2] *= inputColor[3]; - - output[0] = inputColor[0]; - output[1] = inputColor[1]; - output[2] = inputColor[2]; output[3] = inputColor[3]; + + if (inputColor[3] > 0.0f) { + output[0] *= inputColor[3]; + output[1] *= inputColor[3]; + output[2] *= inputColor[3]; + } } void GammaCorrectOperation::deinitExecution() @@ -89,15 +87,13 @@ void GammaUncorrectOperation::executePixel(float output[4], float x, float y, Pi output[0] = inputColor[0] > 0.0f ? sqrtf(inputColor[0]) : 0.0f; output[1] = inputColor[1] > 0.0f ? sqrtf(inputColor[1]) : 0.0f; output[2] = inputColor[2] > 0.0f ? sqrtf(inputColor[2]) : 0.0f; - - inputColor[0] *= inputColor[3]; - inputColor[1] *= inputColor[3]; - inputColor[2] *= inputColor[3]; - - output[0] = inputColor[0]; - output[1] = inputColor[1]; - output[2] = inputColor[2]; output[3] = inputColor[3]; + + if (inputColor[3] > 0.0f) { + output[0] *= inputColor[3]; + output[1] *= inputColor[3]; + output[2] *= inputColor[3]; + } } void GammaUncorrectOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index fb3efbb67ed..84557118a1c 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -65,8 +65,9 @@ ImBuf *BaseImageOperation::getImBuf() { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(this->m_image, this->m_imageUser); + ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, NULL); if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { + BKE_image_release_ibuf(this->m_image, ibuf, NULL); return NULL; } @@ -93,6 +94,7 @@ void BaseImageOperation::initExecution() void BaseImageOperation::deinitExecution() { this->m_imageBuffer = NULL; + BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL); } void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -106,6 +108,8 @@ void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigne resolution[0] = stackbuf->x; resolution[1] = stackbuf->y; } + + BKE_image_release_ibuf(this->m_image, stackbuf, NULL); } void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index c9b129d8dcf..201dc99eb9e 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -151,22 +151,25 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE); zero_v3(site->color); - for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { - if (pattern_ibuf->rect_float) { - add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); - } - else { - unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; - site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); - site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); - site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + if (pattern_ibuf) { + for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { + if (pattern_ibuf->rect_float) { + add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); + } + else { + unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; + + site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); + site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); + site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + } } + + mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); + IMB_freeImBuf(pattern_ibuf); } - mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); - IMB_freeImBuf(pattern_ibuf); - site->co[0] = pos[0] * width; site->co[1] = pos[1] * height; @@ -199,9 +202,9 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri INIT_MINMAX2(min, max); - DO_MINMAX2(a->co, min, max); - DO_MINMAX2(b->co, min, max); - DO_MINMAX2(c->co, min, max); + minmax_v2v2_v2(min, max, a->co); + minmax_v2v2_v2(min, max, b->co); + minmax_v2v2_v2(min, max, c->co); rect->xmin = min[0]; rect->ymin = min[1]; diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.cpp b/source/blender/compositor/operations/COM_MapRangeOperation.cpp new file mode 100644 index 00000000000..1fe74ade0fc --- /dev/null +++ b/source/blender/compositor/operations/COM_MapRangeOperation.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#include "COM_MapRangeOperation.h" + +MapRangeOperation::MapRangeOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputOperation = NULL; + this->m_useClamp = FALSE; +} + +void MapRangeOperation::initExecution() +{ + this->m_inputOperation = this->getInputSocketReader(0); + this->m_sourceMinOperation = this->getInputSocketReader(1); + this->m_sourceMaxOperation = this->getInputSocketReader(2); + this->m_destMinOperation = this->getInputSocketReader(3); + this->m_destMaxOperation = this->getInputSocketReader(4); +} + +/* The code below assumes all data is inside range +- this, and that input buffer is single channel */ +#define BLENDER_ZMAX 10000.0f + +void MapRangeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputs[8]; /* includes the 5 inputs + 3 pads */ + float value; + float source_min, source_max; + float dest_min, dest_max; + + this->m_inputOperation->read(inputs, x, y, sampler); + this->m_sourceMinOperation->read(inputs + 1, x, y, sampler); + this->m_sourceMaxOperation->read(inputs + 2, x, y, sampler); + this->m_destMinOperation->read(inputs + 3, x, y, sampler); + this->m_destMaxOperation->read(inputs + 4, x, y, sampler); + + value = inputs[0]; + source_min = inputs[1]; + source_max = inputs[2]; + dest_min = inputs[3]; + dest_max = inputs[4]; + + if (value >= -BLENDER_ZMAX && value <= BLENDER_ZMAX) { + value = (value - source_min) / (source_max - source_min); + value = dest_min + value * (dest_max - dest_min); + } + else if (value > BLENDER_ZMAX) + value = dest_max; + else + value = dest_min; + + if (this->m_useClamp) { + if (dest_max > dest_min) { + CLAMP(value, dest_min, dest_max); + } + else { + CLAMP(value, dest_max, dest_min); + } + } + + output[0] = value; +} + +void MapRangeOperation::deinitExecution() +{ + this->m_inputOperation = NULL; + this->m_sourceMinOperation = NULL; + this->m_sourceMaxOperation = NULL; + this->m_destMinOperation = NULL; + this->m_destMaxOperation = NULL; +} diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.h b/source/blender/compositor/operations/COM_MapRangeOperation.h new file mode 100644 index 00000000000..00dfc68168c --- /dev/null +++ b/source/blender/compositor/operations/COM_MapRangeOperation.h @@ -0,0 +1,71 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#ifndef _COM_MapRangeOperation_h +#define _COM_MapRangeOperation_h +#include "COM_NodeOperation.h" +#include "DNA_texture_types.h" + +/** + * this program converts an input color to an output value. + * it assumes we are in sRGB color space. + */ +class MapRangeOperation : public NodeOperation { +private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputOperation; + SocketReader *m_sourceMinOperation; + SocketReader *m_sourceMaxOperation; + SocketReader *m_destMinOperation; + SocketReader *m_destMaxOperation; + + bool m_useClamp; +public: + /** + * Default constructor + */ + MapRangeOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + /** + * Clamp the output + */ + void setUseClamp(bool value) { this->m_useClamp = value; } + +}; +#endif diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index df48c7a6716..68a61dff801 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -50,6 +50,7 @@ MovieDistortionOperation::MovieDistortionOperation(bool distortion) : NodeOperat this->m_cache = NULL; this->m_distortion = distortion; } + void MovieDistortionOperation::initExecution() { this->m_inputOperation = this->getInputSocketReader(0); @@ -105,21 +106,9 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P if (this->m_cache != NULL) { float u, v; this->m_cache->getUV(&this->m_movieClip->tracking, x, y, &u, &v); - this->m_inputOperation->read(output, u, v, sampler); + this->m_inputOperation->read(output, u, v, COM_PS_BILINEAR); } else { - this->m_inputOperation->read(output, x, y, sampler); + this->m_inputOperation->read(output, x, y, COM_PS_BILINEAR); } } - -bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) -{ - rcti newInput; - - newInput.xmax = input->xmax + 100; - newInput.xmin = input->xmin - 100; - newInput.ymax = input->ymax + 100; - newInput.ymin = input->ymin - 100; - - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); -} diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 93cc555fdbc..9f8aa065e3e 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -155,7 +155,6 @@ protected: public: MovieDistortionOperation(bool distortion); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); void executePixel(float output[4], float x, float y, PixelSampler sampler); void initExecution(); diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cpp b/source/blender/compositor/operations/COM_NormalizeOperation.cpp index 5f7ac6bb9ca..f81b50e6836 100644 --- a/source/blender/compositor/operations/COM_NormalizeOperation.cpp +++ b/source/blender/compositor/operations/COM_NormalizeOperation.cpp @@ -43,6 +43,12 @@ void NormalizeOperation::executePixel(float output[4], int x, int y, void *data) this->m_imageReader->read(output, x, y, NULL); output[0] = (output[0] - minmult->x) * minmult->y; + + /* clamp infinities */ + if (output[0] > 1.0f) + output[0] = 1.0f; + else if (output[0] < 0.0f) + output[0] = 0.0f; } void NormalizeOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_PixelateOperation.h b/source/blender/compositor/operations/COM_PixelateOperation.h index b16b21b2ec1..83603a59331 100644 --- a/source/blender/compositor/operations/COM_PixelateOperation.h +++ b/source/blender/compositor/operations/COM_PixelateOperation.h @@ -35,7 +35,7 @@ class PixelateOperation : public NodeOperation { private: /** - * @brief cached refeerence to the input operation + * @brief cached reference to the input operation */ SocketReader *m_inputOperation; public: diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp index a4015c6283f..2ca499683d3 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp @@ -69,6 +69,46 @@ void RenderLayersBaseProg::initExecution() } } +void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) +{ + unsigned int offset; + int ix, iy; + int width = this->getWidth(), height = this->getHeight(); + + switch (sampler) { + case COM_PS_NEAREST: + ix = x; + iy = y; + offset = (iy * width + ix) * this->m_elementsize; + + if (this->m_elementsize == 1) + output[0] = this->m_inputBuffer[offset]; + else if (this->m_elementsize == 3) + copy_v3_v3(output, &this->m_inputBuffer[offset]); + else + copy_v4_v4(output, &this->m_inputBuffer[offset]); + + break; + + case COM_PS_BILINEAR: + BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + + case COM_PS_BICUBIC: + BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + } + + if (this->m_elementsize == 1) { + output[1] = 0.0f; + output[2] = 0.0f; + output[3] = 0.0f; + } + else if (this->m_elementsize == 3) { + output[3] = 1.0f; + } +} + void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler) { int ix = x; @@ -78,20 +118,7 @@ void RenderLayersBaseProg::executePixel(float output[4], float x, float y, Pixel zero_v4(output); } else { - unsigned int offset = (iy * this->getWidth() + ix) * this->m_elementsize; - if (this->m_elementsize == 1) { - output[0] = this->m_inputBuffer[offset]; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; - } - else if (this->m_elementsize == 3) { - copy_v3_v3(output, &this->m_inputBuffer[offset]); - output[3] = 1.0f; - } - else { - copy_v4_v4(output, &this->m_inputBuffer[offset]); - } + doInterpolation(output, x, y, sampler); } } diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h index ea57d4bc421..3916862a0b3 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h @@ -80,6 +80,7 @@ protected: */ inline float *getInputBuffer() { return this->m_inputBuffer; } + void doInterpolation(float output[4], float x, float y, PixelSampler sampler); public: /** * setter for the scene field. Will be called from diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp index 276b2f54b6e..9e8f5af0ef0 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cpp +++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp @@ -29,7 +29,16 @@ * note: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1) */ -ScaleOperation::ScaleOperation() : NodeOperation() +BaseScaleOperation::BaseScaleOperation() +{ +#ifdef USE_FORCE_BILINEAR + m_sampler = (int) COM_PS_BILINEAR; +#else + m_sampler = -1; +#endif +} + +ScaleOperation::ScaleOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VALUE); @@ -59,22 +68,20 @@ void ScaleOperation::deinitExecution() void ScaleOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); float scaleX[4]; float scaleY[4]; - this->m_inputXOperation->read(scaleX, x, y, sampler); - this->m_inputYOperation->read(scaleY, x, y, sampler); + this->m_inputXOperation->read(scaleX, x, y, effective_sampler); + this->m_inputYOperation->read(scaleY, x, y, effective_sampler); const float scx = scaleX[0]; const float scy = scaleY[0]; float nx = this->m_centerX + (x - this->m_centerX) / scx; float ny = this->m_centerY + (y - this->m_centerY) / scy; - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) @@ -94,12 +101,12 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOpe newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy; newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } // SCALE ABSOLUTE -ScaleAbsoluteOperation::ScaleAbsoluteOperation() : NodeOperation() +ScaleAbsoluteOperation::ScaleAbsoluteOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VALUE); @@ -129,15 +136,13 @@ void ScaleAbsoluteOperation::deinitExecution() void ScaleAbsoluteOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); float scaleX[4]; float scaleY[4]; - this->m_inputXOperation->read(scaleX, x, y, sampler); - this->m_inputYOperation->read(scaleY, x, y, sampler); + this->m_inputXOperation->read(scaleX, x, y, effective_sampler); + this->m_inputYOperation->read(scaleY, x, y, effective_sampler); const float scx = scaleX[0]; // target absolute scale const float scy = scaleY[0]; // target absolute scale @@ -151,7 +156,7 @@ void ScaleAbsoluteOperation::executePixel(float output[4], float x, float y, Pix float nx = this->m_centerX + (x - this->m_centerX) / relativeXScale; float ny = this->m_centerY + (y - this->m_centerY) / relativeYScale; - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) @@ -176,12 +181,12 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadB newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / relateveYScale; newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / relateveYScale; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } // Absolute fixed siez -ScaleFixedSizeOperation::ScaleFixedSizeOperation() : NodeOperation() +ScaleFixedSizeOperation::ScaleFixedSizeOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); this->addOutputSocket(COM_DT_COLOR); @@ -250,17 +255,15 @@ void ScaleFixedSizeOperation::deinitExecution() void ScaleFixedSizeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); if (this->m_is_offset) { float nx = ((x - this->m_offsetX) * this->m_relX); float ny = ((y - this->m_offsetY) * this->m_relY); - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } else { - this->m_inputOperation->read(output, x * this->m_relX, y * this->m_relY, sampler); + this->m_inputOperation->read(output, x * this->m_relX, y * this->m_relY, effective_sampler); } } @@ -273,7 +276,7 @@ bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, Read newInput.ymax = input->ymax * this->m_relY; newInput.ymin = input->ymin * this->m_relY; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -281,7 +284,7 @@ void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], un unsigned int nr[2]; nr[0] = this->m_newWidth; nr[1] = this->m_newHeight; - NodeOperation::determineResolution(resolution, nr); + BaseScaleOperation::determineResolution(resolution, nr); resolution[0] = this->m_newWidth; resolution[1] = this->m_newHeight; } diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h index 4239ff063fb..f42cdbd78ed 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.h +++ b/source/blender/compositor/operations/COM_ScaleOperation.h @@ -25,7 +25,19 @@ #include "COM_NodeOperation.h" -class ScaleOperation : public NodeOperation { +class BaseScaleOperation : public NodeOperation { +public: + void setSampler(PixelSampler sampler) { this->m_sampler = (int) sampler; } + +protected: + BaseScaleOperation(); + + PixelSampler getEffectiveSampler(PixelSampler sampler) { return (m_sampler == -1) ? sampler : (PixelSampler) m_sampler; } + + int m_sampler; +}; + +class ScaleOperation : public BaseScaleOperation { private: SocketReader *m_inputOperation; SocketReader *m_inputXOperation; @@ -41,7 +53,7 @@ public: void deinitExecution(); }; -class ScaleAbsoluteOperation : public NodeOperation { +class ScaleAbsoluteOperation : public BaseScaleOperation { SocketReader *m_inputOperation; SocketReader *m_inputXOperation; SocketReader *m_inputYOperation; @@ -57,7 +69,7 @@ public: void deinitExecution(); }; -class ScaleFixedSizeOperation : public NodeOperation { +class ScaleFixedSizeOperation : public BaseScaleOperation { SocketReader *m_inputOperation; int m_newWidth; int m_newHeight; diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp index d41d1c128da..8b5288321c1 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp @@ -92,7 +92,7 @@ void TrackPositionOperation::initExecution() } else if (this->m_position == POSITION_RELATIVE_FRAME) { int relative_clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, - this->m_relativeFrame); + this->m_relativeFrame); marker = BKE_tracking_marker_get(track, relative_clip_framenr); copy_v2_v2(this->m_relativePos, marker->pos); diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index 4d4c1199f3e..d5f2c283c72 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -87,27 +87,23 @@ void ViewerBaseOperation::initImage() /* now we combine the input with ibuf */ this->m_outputBuffer = ibuf->rect_float; - /* needed for display buffer update - * - * no need to lock / reference the image buffer because it's seems - * to be the single place which changes buffers of viewer image - * which is this node - */ + /* needed for display buffer update */ this->m_ibuf = ibuf; if (m_doDepthBuffer) { this->m_depthBuffer = ibuf->zbuf_float; } - BKE_image_release_ibuf(this->m_image, this->m_lock); + BKE_image_release_ibuf(this->m_image, this->m_ibuf, this->m_lock); } + void ViewerBaseOperation:: updateImage(rcti *rect) { IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0, this->m_viewSettings, this->m_displaySettings, rect->xmin, rect->ymin, rect->xmax, rect->ymax, FALSE); - WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); + this->updateDraw(); } void ViewerBaseOperation::deinitExecution() diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index f19dbe740bc..fe836204c27 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1560,6 +1560,8 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op) /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */ static void ANIM_OT_channels_setting_enable(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Enable Channel Setting"; ot->idname = "ANIM_OT_channels_setting_enable"; @@ -1575,13 +1577,16 @@ static void ANIM_OT_channels_setting_enable(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */ static void ANIM_OT_channels_setting_disable(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Disable Channel Setting"; ot->idname = "ANIM_OT_channels_setting_disable"; @@ -1597,13 +1602,16 @@ static void ANIM_OT_channels_setting_disable(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Toggle Channel Setting"; ot->idname = "ANIM_OT_channels_setting_toggle"; @@ -1619,13 +1627,16 @@ static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Toggle Channel Editability"; ot->idname = "ANIM_OT_channels_editable_toggle"; @@ -1642,7 +1653,8 @@ static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot) /* flag-setting mode */ RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); /* setting to set */ - RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", ""); + prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ } /* ********************** Expand Channels Operator *********************** */ diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 01c0a95e200..0f0584ad8fe 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -381,7 +381,7 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short rest return RAD2DEGF(1.0f); /* radians to degrees */ } } - + /* TODO: other rotation types here as necessary */ } } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 721b3473792..5e215fbd6a2 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -175,7 +175,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction) return 1; case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */ -{ + { /* TODO, other methods to get the mask */ // Sequence *seq = BKE_sequencer_active_get(ac->scene); //MovieClip *clip = ac->scene->clip; @@ -189,7 +189,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->mode = saction->mode; return 1; -} + } case SACTCONT_DOPESHEET: /* DopeSheet */ /* update scene-pointer (no need to check for pinning yet, as not implemented) */ saction->ads.source = (ID *)ac->scene; @@ -911,14 +911,16 @@ static short skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_i /* only consider if F-Curve involves sequence_editor.sequences */ if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { Editing *ed = BKE_sequencer_editing_get(scene, FALSE); - Sequence *seq; + Sequence *seq = NULL; char *seq_name; - - /* get strip name, and check if this strip is selected */ - seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE); - if (seq_name) MEM_freeN(seq_name); - + + if (ed) { + /* get strip name, and check if this strip is selected */ + seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); + seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE); + if (seq_name) MEM_freeN(seq_name); + } + /* can only add this F-Curve if it is selected */ if (ads->filterflag & ADS_FILTER_ONLYSEL) { if ((seq == NULL) || (seq->flag & SELECT) == 0) diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 852f3fa5469..1b980790fdc 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -706,8 +706,13 @@ static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *e } /* note, init has to be called succesfully */ -static void ed_marker_move_apply(wmOperator *op) +static void ed_marker_move_apply(bContext *C, wmOperator *op) { +#ifdef DURIAN_CAMERA_SWITCH + bScreen *sc = CTX_wm_screen(C); + Scene *scene = CTX_data_scene(C); + Object *camera = scene->camera; +#endif MarkerMove *mm = op->customdata; TimeMarker *marker; int a, offs; @@ -719,17 +724,27 @@ static void ed_marker_move_apply(wmOperator *op) a++; } } + + WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); + +#ifdef DURIAN_CAMERA_SWITCH + /* so we get view3d redraws */ + BKE_scene_camera_switch_update(scene); + + if (camera != scene->camera) { + BKE_screen_view3d_scene_sync(sc); + WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); + } +#endif } /* only for modal */ static int ed_marker_move_cancel(bContext *C, wmOperator *op) { RNA_int_set(op->ptr, "frames", 0); - ed_marker_move_apply(op); + ed_marker_move_apply(C, op); ed_marker_move_exit(C, op); - - WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); - WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); return OPERATOR_CANCELLED; } @@ -789,7 +804,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) offs = (int)fac; RNA_int_set(op->ptr, "frames", offs); - ed_marker_move_apply(op); + ed_marker_move_apply(C, op); /* cruft below is for header print */ for (a = 0, marker = mm->markers->first; marker; marker = marker->next) { @@ -840,29 +855,29 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) } } - WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); - WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); ED_area_headerprint(CTX_wm_area(C), str); } } if (evt->val == KM_PRESS) { - float vec; - char str_tx[NUM_STR_REP_LEN]; - if (handleNumInput(&mm->num, evt)) { - applyNumInput(&mm->num, &vec); - outputNumInput(&mm->num, str_tx); - - RNA_int_set(op->ptr, "frames", vec); - ed_marker_move_apply(op); - // ed_marker_header_update(C, op, str, (int)vec[0]); + char str_tx[NUM_STR_REP_LEN]; + float value = RNA_int_get(op->ptr, "frames"); + applyNumInput(&mm->num, &value); + + if (hasNumInput(&mm->num)) { + outputNumInput(&mm->num, str_tx); + } + else { + BLI_snprintf(str_tx, sizeof(str_tx), "%d", (int)value); + } + + RNA_int_set(op->ptr, "frames", value); + ed_marker_move_apply(C, op); + // ed_marker_header_update(C, op, str, (int)value); // strcat(str, str_tx); BLI_snprintf(str, sizeof(str), "Marker offset %s", str_tx); ED_area_headerprint(CTX_wm_area(C), str); - - WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); - WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); } } @@ -872,7 +887,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) static int ed_marker_move_exec(bContext *C, wmOperator *op) { if (ed_marker_move_init(C, op)) { - ed_marker_move_apply(op); + ed_marker_move_apply(C, op); ed_marker_move_exit(C, op); return OPERATOR_FINISHED; } @@ -1394,6 +1409,11 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int ed_marker_make_links_scene_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +{ + return ed_markers_opwrap_invoke_custom(C, op, evt, WM_menu_invoke); +} + static void MARKER_OT_make_links_scene(wmOperatorType *ot) { PropertyRNA *prop; @@ -1405,7 +1425,7 @@ static void MARKER_OT_make_links_scene(wmOperatorType *ot) /* api callbacks */ ot->exec = ed_marker_make_links_scene_exec; - ot->invoke = ed_markers_opwrap_invoke; + ot->invoke = ed_marker_make_links_scene_invoke_wrapper; ot->poll = ed_markers_poll_selected_markers; /* flags */ diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index ae7abd82600..28db7bf572d 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -325,8 +325,9 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in keying set"); return OPERATOR_CANCELLED; } - else + else { ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1); + } /* try to add to keyingset using property retrieved from UI */ uiContextActiveProperty(C, &ptr, &prop, &index); @@ -360,9 +361,10 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) if (success) { /* send updates */ DAG_ids_flush_update(bmain, 0); - - /* for now, only send ND_KEYS for KeyingSets */ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL); + + /* show notification/report header, so that users notice that something changed */ + BKE_reportf(op->reports, RPT_INFO, "Property added to Keying Set: '%s'", ks->name); } return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; @@ -411,8 +413,9 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Cannot remove property from built in keying set"); return OPERATOR_CANCELLED; } - else + else { ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1); + } /* try to add to keyingset using property retrieved from UI */ uiContextActiveProperty(C, &ptr, &prop, &index); @@ -425,7 +428,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) /* try to find a path matching this description */ ksp = BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME); - + if (ksp) { BKE_keyingset_free_path(ks, ksp); success = 1; @@ -440,9 +443,10 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) if (success) { /* send updates */ DAG_ids_flush_update(bmain, 0); - - /* for now, only send ND_KEYS for KeyingSets */ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL); + + /* show warning */ + BKE_report(op->reports, RPT_INFO, "Property removed from Keying Set"); } return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; @@ -891,11 +895,13 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks) ksi->iter(ksi, C, ks); /* if we don't have any paths now, then this still qualifies as invalid context */ + // FIXME: we need some error conditions (to be retrieved from the iterator why this failed!) if (ks->paths.first == NULL) return MODIFYKEY_INVALID_CONTEXT; } else { /* poll callback tells us that KeyingSet is useless in current context */ + // FIXME: the poll callback needs to give us more info why return MODIFYKEY_INVALID_CONTEXT; } } diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 48da23d5e8d..e801d3689e5 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -3569,16 +3569,16 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); bArmature *arm = obedit->data; EditBone *newbone, *tbone; - int numcuts, i; + int cuts, i; /* there may not be a number_cuts property defined (for 'simple' subdivide) */ - numcuts = RNA_int_get(op->ptr, "number_cuts"); + cuts = RNA_int_get(op->ptr, "number_cuts"); /* loop over all editable bones */ // XXX the old code did this in reverse order though! CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { - for (i = numcuts + 1; i > 1; i--) { + for (i = cuts + 1; i > 1; i--) { /* compute cut ratio first */ float cutratio = 1.0f / (float)i; float cutratioI = 1.0f - cutratio; diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index da8fc328343..f9cf4a29269 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -2104,15 +2104,15 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, if (sketch->depth_peels.first != NULL) { float colors[8][3] = { - {1, 0, 0}, - {0, 1, 0}, - {0, 0, 1}, - {1, 1, 0}, - {1, 0, 1}, - {0, 1, 1}, - {1, 1, 1}, - {0, 0, 0} - }; + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + {1, 1, 0}, + {1, 0, 1}, + {0, 1, 1}, + {1, 1, 1}, + {0, 0, 0} + }; DepthPeel *p; GLUquadric *quad = gluNewQuadric(); gluQuadricNormals(quad, GLU_SMOOTH); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 485d73974cd..23fed4ce8fc 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1069,7 +1069,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) Nurb *nu = editnurb->nurbs.first; CVKeyIndex *keyIndex; char rna_path[64], orig_rna_path[64]; - AnimData *ad = BKE_animdata_from_id(&cu->id); + AnimData *adt = BKE_animdata_from_id(&cu->id); ListBase curves = {NULL, NULL}; FCurve *fcu, *next; @@ -1089,14 +1089,14 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) char handle_path[64], orig_handle_path[64]; BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path); BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path); - fcurve_path_rename(ad, orig_handle_path, handle_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path); BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path); - fcurve_path_rename(ad, orig_handle_path, handle_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); } - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); keyIndex->nu_index = nu_index; keyIndex->pt_index = pt_index; @@ -1116,7 +1116,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) if (keyIndex) { BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index); BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].points[%d]", keyIndex->nu_index, keyIndex->pt_index); - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); keyIndex->nu_index = nu_index; keyIndex->pt_index = pt_index; @@ -1140,7 +1140,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) char *ch = strchr(fcu->rna_path, '.'); if (ch && (!strncmp(ch, ".bezier_points", 14) || !strncmp(ch, ".points", 7))) - fcurve_remove(ad, orig_curves, fcu); + fcurve_remove(adt, orig_curves, fcu); } } @@ -1156,7 +1156,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) if (keyIndex) { BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index); BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index); - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); } nu_index++; @@ -1168,7 +1168,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) for (fcu = orig_curves->first; fcu; fcu = next) { next = fcu->next; - if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(ad, orig_curves, fcu); + if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(adt, orig_curves, fcu); else BLI_addtail(&curves, fcu); } @@ -1178,14 +1178,14 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) /* return 0 if animation data wasn't changed, 1 otherwise */ int ED_curve_updateAnimPaths(Curve *cu) { - AnimData *ad = BKE_animdata_from_id(&cu->id); + AnimData *adt = BKE_animdata_from_id(&cu->id); if (!curve_is_animated(cu)) return 0; - if (ad->action) - curve_rename_fcurves(cu, &ad->action->curves); + if (adt->action) + curve_rename_fcurves(cu, &adt->action->curves); - curve_rename_fcurves(cu, &ad->drivers); + curve_rename_fcurves(cu, &adt->drivers); return 1; } @@ -3678,10 +3678,12 @@ static int is_u_selected(Nurb *nu, int u) /* what about resolu == 2? */ bp = &nu->bp[u]; for (v = 0; v < nu->pntsv - 1; v++, bp += nu->pntsu) { - if (v) if (bp->f1 & SELECT) return 1; + if ((v != 0) && (bp->f1 & SELECT)) { + return TRUE; + } } - return 0; + return FALSE; } typedef struct NurbSort { @@ -6464,9 +6466,9 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type bp->vec[0] += fac * grid; fac = (float)b - 1.5f; bp->vec[1] += fac * grid; - if (a == 1 || a == 2) if (b == 1 || b == 2) { - bp->vec[2] += grid; - } + if ((a == 1 || a == 2) && (b == 1 || b == 2)) { + bp->vec[2] += grid; + } mul_m4_v3(mat, bp->vec); bp->vec[3] = 1.0; bp++; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index fd87e6752f2..257dfca051f 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1289,6 +1289,13 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) insert_into_textbuf(obedit, ascii); accentcode = 0; } + else if (ascii) { + insert_into_textbuf(obedit, ascii); + accentcode = 0; + } + else { + BLI_assert(0); + } kill_selection(obedit, 1); text_update_edited(C, scene, obedit, 1, FO_EDIT); diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index a59a3f7a5ec..aee97f40c31 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -49,6 +49,7 @@ #include "ED_anim_api.h" #include "ED_gpencil.h" #include "ED_keyframes_edit.h" +#include "ED_markers.h" #include "gpencil_intern.h" @@ -460,11 +461,12 @@ void paste_gpdata(Scene *scene) /* undo and redraw stuff */ BIF_undo_push("Paste Grease Pencil Frames"); } +#endif /* XXX disabled until Grease Pencil code stabilises again... */ /* -------------------------------------- */ /* Snap Tools */ -static short snap_gpf_nearest(bGPDframe *gpf, Scene *scene) +static short snap_gpf_nearest(bGPDframe *gpf, Scene *UNUSED(scene)) { if (gpf->flag & GP_FRAME_SELECT) gpf->framenum = (int)(floor(gpf->framenum + 0.5)); @@ -475,7 +477,7 @@ static short snap_gpf_nearestsec(bGPDframe *gpf, Scene *scene) { float secf = (float)FPS; if (gpf->flag & GP_FRAME_SELECT) - gpf->framenum = (int)(floor(gpf->framenum / secf + 0.5f) * secf); + gpf->framenum = (int)(floorf(gpf->framenum / secf + 0.5f) * secf); return 0; } @@ -489,33 +491,32 @@ static short snap_gpf_cframe(bGPDframe *gpf, Scene *scene) static short snap_gpf_nearmarker(bGPDframe *gpf, Scene *scene) { if (gpf->flag & GP_FRAME_SELECT) - gpf->framenum = (int)find_nearest_marker_time(&scene->markers, (float)gpf->framenum); + gpf->framenum = (int)ED_markers_find_nearest_marker_time(&scene->markers, (float)gpf->framenum); return 0; } - /* snap selected frames to ... */ -void snap_gplayer_frames(bGPDlayer *gpl, Scene *scene, short mode) +void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode) { switch (mode) { - case 1: /* snap to nearest frame */ + case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); break; - case 2: /* snap to current frame */ + case SNAP_KEYS_CURFRAME: /* snap to current frame */ ED_gplayer_frames_looper(gpl, scene, snap_gpf_cframe); break; - case 3: /* snap to nearest marker */ + case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker); break; - case 4: /* snap to nearest second */ + case SNAP_KEYS_NEARSEC: /* snap to nearest second */ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec); break; default: /* just in case */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); break; } } +#if 0 /* XXX disabled until grease pencil code stabilises again */ /* -------------------------------------- */ /* Mirror Tools */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index ed8a1ea8280..e9ca7392752 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -40,8 +40,10 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_rand.h" #include "BLI_utildefines.h" +#include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_node_types.h" @@ -51,14 +53,19 @@ #include "DNA_view3d_types.h" #include "DNA_gpencil_types.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_library.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_tracking.h" +#include "UI_interface.h" #include "WM_api.h" #include "WM_types.h" @@ -71,6 +78,7 @@ #include "ED_gpencil.h" #include "ED_view3d.h" #include "ED_clip.h" +#include "ED_keyframing.h" #include "gpencil_intern.h" @@ -131,11 +139,11 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) return &sseq->gpd; } break; - + case SPACE_IMAGE: /* Image/UV Editor */ { SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C); - + /* for now, Grease Pencil data is associated with the space... */ /* XXX our convention for everything else is to link to data though... */ if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr); @@ -151,19 +159,19 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) if (clip) { if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); - + if (!track) return NULL; - + if (ptr) RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr); - + return &track->gpd; } else { if (ptr) RNA_id_pointer_create(&clip->id, ptr); - + return &clip->gpd; } } @@ -387,6 +395,14 @@ enum { GP_STROKECONVERT_CURVE, }; +/* Defines for possible timing modes */ +enum { + GP_STROKECONVERT_TIMING_NONE = 1, + GP_STROKECONVERT_TIMING_LINEAR = 2, + GP_STROKECONVERT_TIMING_FULL = 3, + GP_STROKECONVERT_TIMING_CUSTOMGAP = 4, +}; + /* RNA enum define */ static EnumPropertyItem prop_gpencil_convertmodes[] = { {GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""}, @@ -394,6 +410,31 @@ static EnumPropertyItem prop_gpencil_convertmodes[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem prop_gpencil_convert_timingmodes[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"}, + {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps", + "Use the original timing, but with custom gap lengths (in frames)"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), + int *free) +{ + *free = FALSE; + if (RNA_boolean_get(ptr, "use_timing_data")) { + return prop_gpencil_convert_timingmodes; + } + return prop_gpencil_convert_timingmodes_restricted; +} + /* --- */ /* convert the coordinates from the given stroke point into 3d-coordinates @@ -430,7 +471,7 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin mvalf[1] = (float)pt->y / 100.0f * ar->winy; } } - + /* convert screen coordinate to 3d coordinates * - method taken from editview.c - mouse_cursor() */ @@ -440,47 +481,510 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin /* --- */ +/* temp struct for gp_stroke_path_animation() */ +typedef struct tGpTimingData { + /* Data set from operator settings */ + int mode; + int frame_range; /* Number of frames evaluated for path animation */ + int start_frame, end_frame; + int realtime; /* A bool, actually, will overwrite end_frame in case of Original or CustomGap timing... */ + float gap_duration, gap_randomness; /* To be used with CustomGap mode*/ + int seed; + + /* Data set from points, used to compute final timing FCurve */ + int num_points, cur_point; + + /* Distances */ + float *dists; + float tot_dist; + + /* Times */ + float *times; /* Note: Gap times will be negative! */ + float tot_time, gap_tot_time; + double inittime; +} tGpTimingData; + +/* init point buffers for timing data */ +static void _gp_timing_data_set_nbr(tGpTimingData *gtd, int nbr) +{ + float *tmp; + + BLI_assert(nbr > gtd->num_points); + + /* distances */ + tmp = gtd->dists; + gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + /* times */ + tmp = gtd->times; + gtd->times = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + gtd->num_points = nbr; +} + +/* add stroke point to timing buffers */ +static void gp_timing_data_add_point(tGpTimingData *gtd, double stroke_inittime, float time, float delta_dist) +{ + if (time < 0.0f) { + /* This is a gap, negative value! */ + gtd->times[gtd->cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time); + gtd->tot_time = -gtd->times[gtd->cur_point]; + + gtd->gap_tot_time += gtd->times[gtd->cur_point] - gtd->times[gtd->cur_point - 1]; + } + else { + gtd->times[gtd->cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time); + gtd->tot_time = (gtd->times[gtd->cur_point]); + } + + gtd->tot_dist += delta_dist; + gtd->dists[gtd->cur_point] = gtd->tot_dist; + + gtd->cur_point++; +} + +/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can't set + * arbitrarily close points - this is esp. important with NoGaps mode! + */ +#define MIN_TIME_DELTA 0.02f + +/* Loop over next points to find the end of the stroke, and compute */ +static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, int idx, int nbr_gaps, int *nbr_done_gaps, + float tot_gaps_time, float delta_time, float *next_delta_time) +{ + int j; + + for (j = idx + 1; j < gtd->num_points; j++) { + if (gtd->times[j] < 0) { + gtd->times[j] = -gtd->times[j]; + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* In this mode, gap time between this stroke and the next should be 0 currently... + * So we have to compute its final duration! + */ + if (gtd->gap_randomness > 0.0f) { + /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range, + * and which sum to exactly tot_gaps_time... + */ + int rem_gaps = nbr_gaps - (*nbr_done_gaps); + if (rem_gaps < 2) { + /* Last gap, just give remaining time! */ + *next_delta_time = tot_gaps_time; + } + else { + float delta, min, max; + + /* This code ensures that if the first gaps have been shorter than average gap_duration, + * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa! + */ + delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps)); + + /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */ + min = -gtd->gap_randomness - delta; + CLAMP(min, -gtd->gap_randomness, 0.0f); + + /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */ + max = gtd->gap_randomness - delta; + CLAMP(max, 0.0f, gtd->gap_randomness); + *next_delta_time += gtd->gap_duration + (BLI_frand() * (max - min)) + min; + } + } + else { + *next_delta_time += gtd->gap_duration; + } + } + (*nbr_done_gaps)++; + break; + } + } + + return j - 1; +} + +static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, int *nbr_gaps, float *tot_gaps_time) +{ + int i; + float delta_time = 0.0f; + + for (i = 0; i < gtd->num_points; i++) { + if (gtd->times[i] < 0 && i) { + (*nbr_gaps)++; + gtd->times[i] = -gtd->times[i] - delta_time; + delta_time += gtd->times[i] - gtd->times[i - 1]; + gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */ + } + else { + gtd->times[i] -= delta_time; + } + } + gtd->tot_time -= delta_time; + + *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; + gtd->tot_time += *tot_gaps_time; + if (G.debug & G_DEBUG) { + printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps); + } + if (gtd->gap_randomness > 0.0f) { + BLI_srandom(gtd->seed); + } +} + +static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, + Curve *cu, tGpTimingData *gtd, float time_range, + int nbr_gaps, float tot_gaps_time) +{ + /* Use actual recorded timing! */ + float time_start = (float)gtd->start_frame; + + float last_valid_time = 0.0f; + int end_stroke_idx = -1, start_stroke_idx = 0; + float end_stroke_time = 0.0f; + + /* CustomGaps specific */ + float delta_time = 0.0f, next_delta_time = 0.0f; + int nbr_done_gaps = 0; + + int i; + float cfra; + + /* This is a bit tricky, as: + * - We can't add arbitrarily close points on FCurve (in time). + * - We *must* have all "caps" points of all strokes in FCurve, as much as possible! + */ + for (i = 0; i < gtd->num_points; i++) { + /* If new stroke... */ + if (i > end_stroke_idx) { + start_stroke_idx = i; + delta_time = next_delta_time; + /* find end of that new stroke */ + end_stroke_idx = gp_find_end_of_stroke_idx(gtd, i, nbr_gaps, &nbr_done_gaps, + tot_gaps_time, delta_time, &next_delta_time); + /* This one should *never* be negative! */ + end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range); + } + + /* Simple proportional stuff... */ + cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen; + cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range); + + /* And now, the checks about timing... */ + if (i == start_stroke_idx) { + /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and + * that the end point of the stroke is far enough! + * In case it is not, we keep the end point... + * Note that with CustomGaps mode, this is here we set the actual gap timing! + */ + if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) { + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx); + } + } + else if (i == end_stroke_idx) { + /* Always try to insert end point of a curve (should be safe enough, anyway...) */ + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else { + /* Else ("middle" point), we only insert it if it's far enough from last keyframe, + * and also far enough from (not yet added!) end_stroke keyframe! + */ + if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) { + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n", + i, end_stroke_idx); + } + } + } +} + +static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd) +{ + Scene *scene = CTX_data_scene(C); + bAction *act; + FCurve *fcu; + PointerRNA ptr; + PropertyRNA *prop = NULL; + int nbr_gaps = 0, i; + + if (gtd->mode == GP_STROKECONVERT_TIMING_NONE) + return; + + /* gap_duration and gap_randomness are in frames, but we need seconds!!! */ + gtd->gap_duration = FRA2TIME(gtd->gap_duration); + gtd->gap_randomness = FRA2TIME(gtd->gap_randomness); + + /* Enable path! */ + cu->flag |= CU_PATH; + cu->pathlen = gtd->frame_range; + + /* Get RNA pointer to read/write path time values */ + RNA_id_pointer_create((ID *)cu, &ptr); + prop = RNA_struct_find_property(&ptr, "eval_time"); + + /* Ensure we have an F-Curve to add keyframes to */ + act = verify_adt_action((ID *)cu, TRUE); + fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, TRUE); + + if (G.debug & G_DEBUG) { + printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + } + + if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) { + float cfra; + + /* Linear extrapolation! */ + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + + cu->ctime = 0.0f; + cfra = (float)gtd->start_frame; + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + + cu->ctime = cu->pathlen; + if (gtd->realtime) { + cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + cfra = (float)gtd->end_frame; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + } + else { + /* Use actual recorded timing! */ + float time_range; + + /* CustomGaps specific */ + float tot_gaps_time = 0.0f; + + /* Pre-process gaps, in case we don't want to keep their original timing */ + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + gp_stroke_path_animation_preprocess_gaps(gtd, &nbr_gaps, &tot_gaps_time); + } + + if (gtd->realtime) { + time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + time_range = (float)(gtd->end_frame - gtd->start_frame); + } + + if (G.debug & G_DEBUG) { + printf("GP Stroke Path Conversion: Starting keying!\n"); + } + + gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, time_range, + nbr_gaps, tot_gaps_time); + } + + /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */ + calchandles_fcurve(fcu); + + if (G.debug & G_DEBUG) { + printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + printf("\n\n"); + } + + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* send updates */ + DAG_id_tag_update(&cu->id, 0); +} + +#undef MIN_TIME_DELTA + +#define GAP_DFAC 0.05f +#define WIDTH_CORR_FAC 0.1f +#define BEZT_HANDLE_FAC 0.3f + /* convert stroke to 3d path */ -static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect) +static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd) { bGPDspoint *pt; - Nurb *nu; - BPoint *bp; - int i; + Nurb *nu = (curnu) ? *curnu : NULL; + BPoint *bp, *prev_bp = NULL; + const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + int i, old_nbp = 0; - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); - - nu->pntsu = gps->totpoints; - nu->pntsv = 1; - nu->orderu = gps->totpoints; - nu->flagu = CU_NURB_ENDPOINT; - nu->resolu = 32; - - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * gps->totpoints, "bpoints"); + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbp = nu->pntsu; + + /* If stitch, the first point of this stroke is already present in current nu. + * Else, we have to add to additional points to make the zero-radius link between strokes. + */ + BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2)); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); + + nu->pntsu = gps->totpoints; + nu->pntsv = 1; + nu->orderu = 2; /* point-to-point! */ + nu->type = CU_NURBS; + nu->flagu = CU_NURB_ENDPOINT; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->knotsu = NULL; + + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints"); + + stitch = FALSE; /* Security! */ + } + + if (do_gtd) { + _gp_timing_data_set_nbr(gtd, nu->pntsu); + } + + /* If needed, make the link between both strokes with two zero-radius additional points */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + if (curnu && !stitch && old_nbp) { + float p1[3], p2[3], p[3], next_p[3]; + float delta_time; + + prev_bp = NULL; + if ((old_nbp > 1) && gps->prev && (gps->prev->totpoints > 1)) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bp = nu->bp + old_nbp - 2; + } + bp = nu->bp + old_nbp - 1; + + /* XXX We do this twice... Not sure it's worth to bother about this! */ + gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect); + if (prev_bp) { + interp_v3_v3v3(p1, prev_bp->vec, bp->vec, 1.0f + GAP_DFAC); + } + else { + interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC); + } + + if (gps->totpoints > 1) { + /* XXX We do this twice... Not sure it's worth to bother about this! */ + gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect); + interp_v3_v3v3(p2, p, next_p, -GAP_DFAC); + } + else { + interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC); + } + + /* First point */ + bp++; + copy_v3_v3(bp->vec, p1); + bp->vec[3] = 1.0f; + bp->f1 = SELECT; + minmax_weights[0] = bp->radius = bp->weight = 0.0f; + if (do_gtd) { + if (prev_bp) { + delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC; + } + else { + delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bp - 1)->vec, p1)); + } + + /* Second point */ + bp++; + copy_v3_v3(bp->vec, p2); + bp->vec[3] = 1.0f; + bp->f1 = SELECT; + minmax_weights[0] = bp->radius = bp->weight = 0.0f; + if (do_gtd) { + /* This negative delta_time marks the gap! */ + if (gps->totpoints > 1) { + delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC; + } + else { + delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2)); + } + + old_nbp += 2; + } + if (old_nbp && do_gtd) { + prev_bp = nu->bp + old_nbp - 1; + } /* add points */ - for (i = 0, pt = gps->points, bp = nu->bp; i < gps->totpoints; i++, pt++, bp++) { + for (i = (stitch) ? 1 : 0, pt = gps->points + ((stitch) ? 1 : 0), bp = nu->bp + old_nbp; + i < gps->totpoints; + i++, pt++, bp++) + { float p3d[3]; + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; /* get coordinates to add at */ gp_strokepoint_convertcoords(C, gps, pt, p3d, subrect); copy_v3_v3(bp->vec, p3d); + bp->vec[3] = 1.0f; /* set settings */ bp->f1 = SELECT; - bp->radius = bp->weight = pt->pressure * gpl->thickness; + bp->radius = width * rad_fac; + bp->weight = width; + CLAMP(bp->weight, 0.0f, 1.0f); + if (bp->weight < minmax_weights[0]) { + minmax_weights[0] = bp->weight; + } + else if (bp->weight > minmax_weights[1]) { + minmax_weights[1] = bp->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, gps->inittime, pt->time, (prev_bp) ? len_v3v3(prev_bp->vec, p3d) : 0.0f); + } + prev_bp = bp; } /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } + + BKE_nurb_knot_calc_u(nu); } static int gp_camera_view_subrect(bContext *C, rctf *subrect) { View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); - + if (v3d) { RegionView3D *rv3d = ar->regiondata; @@ -491,48 +995,178 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect) return 1; } } - + return 0; } /* convert stroke to 3d bezier */ -static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect) +static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd) { bGPDspoint *pt; - Nurb *nu; - BezTriple *bezt; - int i, tot; + Nurb *nu = (curnu) ? *curnu : NULL; + BezTriple *bezt, *prev_bezt = NULL; + int i, tot, old_nbezt = 0; float p3d_cur[3], p3d_prev[3], p3d_next[3]; + const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbezt = nu->pntsu; + /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke, + * so no need to add it. + * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes. + */ + BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2)); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); + + nu->pntsu = gps->totpoints; + nu->resolu = 12; + nu->resolv = 12; + nu->type = CU_BEZIER; + nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts"); + + stitch = FALSE; /* Security! */ + } - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); - - nu->pntsu = gps->totpoints; - nu->resolu = 12; - nu->resolv = 12; - nu->type = CU_BEZIER; - nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts"); + if (do_gtd) { + _gp_timing_data_set_nbr(gtd, nu->pntsu); + } tot = gps->totpoints; /* get initial coordinates */ pt = gps->points; if (tot) { - gp_strokepoint_convertcoords(C, gps, pt, p3d_cur, subrect); + gp_strokepoint_convertcoords(C, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); if (tot > 1) { - gp_strokepoint_convertcoords(C, gps, pt + 1, p3d_next, subrect); + gp_strokepoint_convertcoords(C, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); + } + if (stitch && tot > 2) { + gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); } } + /* If needed, make the link between both strokes with two zero-radius additional points */ + if (curnu && old_nbezt) { + /* Update last point's second handle */ + if (stitch) { + float h2[3]; + bezt = nu->bezt + old_nbezt - 1; + interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + pt++; + } + + /* Create "link points" */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + else { + float h1[3], h2[3], p1[3], p2[3]; + float delta_time; + + prev_bezt = NULL; + if (old_nbezt > 1 && gps->prev && gps->prev->totpoints > 1) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bezt = nu->bezt + old_nbezt - 2; + } + bezt = nu->bezt + old_nbezt - 1; + if (prev_bezt) { + interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC); + } + else { + interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC); + } + if (tot > 1) { + interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC); + } + else { + interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC); + } + + /* Second handle of last point */ + interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + + /* First point */ + interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC); + + bezt++; + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p1); + copy_v3_v3(bezt->vec[2], h2); + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + minmax_weights[0] = bezt->radius = bezt->weight = 0.0f; + + if (do_gtd) { + if (prev_bezt) { + delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC; + } + else { + delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bezt - 1)->vec[1], p1)); + } + + /* Second point */ + interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC); + + bezt++; + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p2); + copy_v3_v3(bezt->vec[2], h2); + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + minmax_weights[0] = bezt->radius = bezt->weight = 0.0f; + + if (do_gtd) { + /* This negative delta_time marks the gap! */ + if (tot > 1) { + delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC; + } + else { + delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2)); + } + + old_nbezt += 2; + copy_v3_v3(p3d_prev, p2); + } + } + if (old_nbezt && do_gtd) { + prev_bezt = nu->bezt + old_nbezt - 1; + } + /* add points */ - for (i = 0, bezt = nu->bezt; i < tot; i++, pt++, bezt++) { + for (i = stitch ? 1 : 0, bezt = nu->bezt + old_nbezt; i < tot; i++, pt++, bezt++) { float h1[3], h2[3]; + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; - if (i) interp_v3_v3v3(h1, p3d_cur, p3d_prev, 0.3); - else interp_v3_v3v3(h1, p3d_cur, p3d_next, -0.3); + if (i || old_nbezt) { + interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC); + } - if (i < tot - 1) interp_v3_v3v3(h2, p3d_cur, p3d_next, 0.3); - else interp_v3_v3v3(h2, p3d_cur, p3d_prev, -0.3); + if (i < tot - 1) { + interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC); + } copy_v3_v3(bezt->vec[0], h1); copy_v3_v3(bezt->vec[1], p3d_cur); @@ -541,7 +1175,20 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu /* set settings */ bezt->h1 = bezt->h2 = HD_FREE; bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->radius = bezt->weight = pt->pressure * gpl->thickness * 0.1f; + bezt->radius = width * rad_fac; + bezt->weight = width; + CLAMP(bezt->weight, 0.0f, 1.0f); + if (bezt->weight < minmax_weights[0]) { + minmax_weights[0] = bezt->weight; + } + else if (bezt->weight > minmax_weights[1]) { + minmax_weights[1] = bezt->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, gps->inittime, pt->time, prev_bezt ? len_v3v3(prev_bezt->vec[1], p3d_cur) : 0.0f); + } /* shift coord vects */ copy_v3_v3(p3d_prev, p3d_cur); @@ -550,31 +1197,103 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu if (i + 2 < tot) { gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); } + + prev_bezt = bezt; } - + /* must calculate handles or else we crash */ BKE_nurb_handles_calc(nu); - /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } +} + +#undef GAP_DFAC +#undef WIDTH_CORR_FAC +#undef BEZT_HANDLE_FAC + +static void gp_stroke_finalize_curve_endpoints(Curve *cu) +{ + /* start */ + Nurb *nu = cu->nurb.first; + int i = 0; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } + + /* end */ + nu = cu->nurb.last; + i = nu->pntsu - 1; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } +} + +static void gp_stroke_norm_curve_weights(Curve *cu, float minmax_weights[2]) +{ + Nurb *nu; + const float delta = minmax_weights[0]; + const float fac = 1.0f / (minmax_weights[1] - delta); + int i; + + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + for (i = 0; i < nu->pntsu; i++, bezt++) { + bezt->weight = (bezt->weight - delta) * fac; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + for (i = 0; i < nu->pntsu; i++, bp++) { + bp->weight = (bp->weight - delta) * fac; + } + } + } } /* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ -static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short mode) +static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, int mode, + int norm_weights, float rad_fac, int link_strokes, tGpTimingData *gtd) { Scene *scene = CTX_data_scene(C); bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps; + bGPDstroke *gps, *prev_gps = NULL; Object *ob; Curve *cu; + Nurb *nu = NULL; + Base *base = BASACT, *newbase = NULL; + float minmax_weights[2] = {1.0f, 0.0f}; /* camera framing */ rctf subrect, *subrect_ptr = NULL; - + /* error checking */ if (ELEM3(NULL, gpd, gpl, gpf)) return; - + /* only convert if there are any strokes on this layer's frame to convert */ if (gpf->strokes.first == NULL) return; @@ -583,7 +1302,7 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m if (gp_camera_view_subrect(C, &subrect)) { subrect_ptr = &subrect; } - + /* init the curve object (remove rotation and get curve data from it) * - must clear transforms set on object, as those skew our results */ @@ -597,24 +1316,125 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m rename_id((ID *)ob, gpl->info); rename_id((ID *)cu, gpl->info); + gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime; + /* add points to curve */ for (gps = gpf->strokes.first; gps; gps = gps->next) { + /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, + * and stitch them to previous one. + */ + int stitch = FALSE; + + if (prev_gps) { + bGPDspoint *pt1 = prev_gps->points + prev_gps->totpoints - 1; + bGPDspoint *pt2 = gps->points; + + if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) { + stitch = TRUE; + } + } + + /* Decide whether we connect this stroke to previous one */ + if (!(stitch || link_strokes)) { + nu = NULL; + } + switch (mode) { case GP_STROKECONVERT_PATH: - gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr); + gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd); break; case GP_STROKECONVERT_CURVE: - gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr); + gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd); break; default: BLI_assert(!"invalid mode"); break; } + prev_gps = gps; + } + + /* If link_strokes, be sure first and last points have a zero weight/size! */ + if (link_strokes) + gp_stroke_finalize_curve_endpoints(cu); + + /* Update curve's weights, if needed */ + if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) + gp_stroke_norm_curve_weights(cu, minmax_weights); + + /* Create the path animation, if needed */ + gp_stroke_path_animation(C, reports, cu, gtd); + + /* Reset original object as active, else we can't edit operator's settings!!! */ + /* set layers OK */ + newbase = BASACT; + if (base) { + newbase->lay = base->lay; + ob->lay = newbase->lay; + } + + /* restore, BKE_object_add sets active */ + BASACT = base; + if (base) { + base->flag |= SELECT; } } /* --- */ +/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator. + * op may be NULL. + */ +static int gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps = gpf->strokes.first; + bGPDspoint *pt; + double base_time, cur_time, prev_time = -1.0; + int i, valid = TRUE; + + do { + base_time = cur_time = gps->inittime; + if (cur_time <= prev_time) { + valid = FALSE; + break; + } + + prev_time = cur_time; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + cur_time = base_time + (double)pt->time; + /* First point of a stroke should have the same time as stroke's inittime, + * so it's the only case where equality is allowed! + */ + if ((i && cur_time <= prev_time) || (cur_time < prev_time)) { + valid = FALSE; + break; + } + prev_time = cur_time; + } + + if (!valid) { + break; + } + } while ((gps = gps->next)); + + if (op) { + RNA_boolean_set(op->ptr, "use_timing_data", valid); + } + return valid; +} + +/* Check end_frame is always > start frame! */ +static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr) +{ + int start_frame = RNA_int_get(ptr, "start_frame"); + int end_frame = RNA_int_get(ptr, "end_frame"); + + if (end_frame <= start_frame) { + RNA_int_set(ptr, "end_frame", start_frame + 1); + } +} + static int gp_convert_poll(bContext *C) { bGPdata *gpd = gpencil_data_get_active(C); @@ -627,45 +1447,204 @@ static int gp_convert_poll(bContext *C) static int gp_convert_layer_exec(bContext *C, wmOperator *op) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); bGPdata *gpd = gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); Scene *scene = CTX_data_scene(C); int mode = RNA_enum_get(op->ptr, "type"); - + int norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights"); + float rad_fac = RNA_float_get(op->ptr, "radius_multiplier"); + int link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes"); + int valid_timing; + tGpTimingData gtd; + /* check if there's data to work with */ if (gpd == NULL) { - BKE_report(op->reports, RPT_ERROR, "No grease pencil data to work on"); + BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); return OPERATOR_CANCELLED; } - - gp_layer_to_curve(C, gpd, gpl, mode); - + + if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { + BKE_report(op->reports, RPT_WARNING, + "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!"); + } + valid_timing = RNA_property_boolean_get(op->ptr, prop); + + gtd.mode = RNA_enum_get(op->ptr, "timing_mode"); + /* Check for illegal timing mode! */ + if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) { + gtd.mode = GP_STROKECONVERT_TIMING_LINEAR; + RNA_enum_set(op->ptr, "timing_mode", gtd.mode); + } + if (!link_strokes) { + gtd.mode = GP_STROKECONVERT_TIMING_NONE; + } + + /* grab all relevant settings */ + gtd.frame_range = RNA_int_get(op->ptr, "frame_range"); + gtd.start_frame = RNA_int_get(op->ptr, "start_frame"); + gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : FALSE; + gtd.end_frame = RNA_int_get(op->ptr, "end_frame"); + gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration"); + gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness"); + gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration); + gtd.seed = RNA_int_get(op->ptr, "seed"); + gtd.num_points = gtd.cur_point = 0; + gtd.dists = gtd.times = NULL; + gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f; + gtd.inittime = 0.0; + + /* perform conversion */ + gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); + + /* free temp memory */ + if (gtd.dists) { + MEM_freeN(gtd.dists); + gtd.dists = NULL; + } + if (gtd.times) { + MEM_freeN(gtd.times); + gtd.times = NULL; + } + /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - + /* done */ return OPERATOR_FINISHED; } +static int gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + int link_strokes = RNA_boolean_get(ptr, "use_link_strokes"); + int timing_mode = RNA_enum_get(ptr, "timing_mode"); + int realtime = RNA_boolean_get(ptr, "use_realtime"); + float gap_duration = RNA_float_get(ptr, "gap_duration"); + float gap_randomness = RNA_float_get(ptr, "gap_randomness"); + int valid_timing = RNA_boolean_get(ptr, "use_timing_data"); + + /* Always show those props */ + if (strcmp(prop_id, "type") == 0 || + strcmp(prop_id, "use_normalize_weights") == 0 || + strcmp(prop_id, "radius_multiplier") == 0 || + strcmp(prop_id, "use_link_strokes") == 0) + { + return TRUE; + } + + /* Never show this prop */ + if (strcmp(prop_id, "use_timing_data") == 0) + return FALSE; + + if (link_strokes) { + /* Only show when link_stroke is TRUE */ + if (strcmp(prop_id, "timing_mode") == 0) + return TRUE; + + if (timing_mode != GP_STROKECONVERT_TIMING_NONE) { + /* Only show when link_stroke is TRUE and stroke timing is enabled */ + if (strcmp(prop_id, "frame_range") == 0 || + strcmp(prop_id, "start_frame") == 0) + { + return TRUE; + } + + /* Only show if we have valid timing data! */ + if (valid_timing && strcmp(prop_id, "use_realtime") == 0) + return TRUE; + + /* Only show if realtime or valid_timing is FALSE! */ + if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0) + return TRUE; + + if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* Only show for custom gaps! */ + if (strcmp(prop_id, "gap_duration") == 0) + return TRUE; + + /* Only show randomness for non-null custom gaps! */ + if (strcmp(prop_id, "gap_randomness") == 0 && (gap_duration > 0.0f)) + return TRUE; + + /* Only show seed for randomize action! */ + if (strcmp(prop_id, "seed") == 0 && (gap_duration > 0.0f) && (gap_randomness > 0.0f)) + return TRUE; + } + } + } + + /* Else, hidden! */ + return FALSE; +} + +static void gp_convert_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + /* Main auto-draw call */ + uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0'); +} + void GPENCIL_OT_convert(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Convert Grease Pencil"; ot->idname = "GPENCIL_OT_convert"; - ot->description = "Convert the active Grease Pencil layer to a new Object"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->description = "Convert the active Grease Pencil layer to a new Curve Object"; /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gp_convert_layer_exec; ot->poll = gp_convert_poll; + ot->ui = gp_convert_ui; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", ""); + ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to"); + + RNA_def_boolean(ot->srna, "use_normalize_weights", TRUE, "Normalize Weight", + "Normalize weight (set from stroke width)"); + RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac", + "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f); + RNA_def_boolean(ot->srna, "use_link_strokes", TRUE, "Link Strokes", + "Whether to link strokes with zero-radius sections of curves"); + + prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL, + "Timing Mode", "How to use timing data stored in strokes"); + RNA_def_enum_funcs(prop, rna_GPConvert_mode_items); + + RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range", + "The duration of evaluation of the path control curve", 1, 1000); + RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame", + "The start frame of the path control curve", 1, 100000); + RNA_def_boolean(ot->srna, "use_realtime", FALSE, "Realtime", + "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame"); + prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame", + "The end frame of the path control curve (if Realtime is not set)", 1, 100000); + RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); + + RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration", + "Custom Gap mode: (Average) length of gaps, in frames " + "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f); + RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness", + "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f); + RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed", + "Custom Gap mode: Random generator seed", 0, 100); + + /* Note: Internal use, this one will always be hidden by UI code... */ + prop = RNA_def_boolean(ot->srna, "use_timing_data", FALSE, "Has Valid Timing", + "Whether the converted Grease Pencil layer has valid timing data (internal use)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 9bfd89075af..8fdca730674 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -39,6 +39,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BKE_gpencil.h" #include "BKE_context.h" #include "BKE_global.h" @@ -98,6 +100,14 @@ typedef struct tGPsdata { short radius; /* radius of influence for eraser */ short flags; /* flags that can get set during runtime */ + + /* These need to be doubles, as (at least under unix) they are in seconds since epoch, + * float (and its 7 digits precision) is definitively not enough here! + * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least. + */ + double inittime; /* Used when converting to path */ + double curtime; /* Used when converting to path */ + double ocurtime; /* Used when converting to path */ float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space * to region space */ @@ -201,7 +211,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3]) float *fp = give_cursor(p->scene, v3d); /* the reference point used depends on the owner... */ -#if 0 // XXX: disabled for now, since we can't draw relative to the owner yet +#if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */ if (p->ownerPtr.type == &RNA_Object) { Object *ob = (Object *)p->ownerPtr.data; @@ -249,7 +259,7 @@ static short gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2]) } /* convert screen-coordinates to buffer-coordinates */ -// XXX this method needs a total overhaul! +/* XXX this method needs a total overhaul! */ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3], float *depth) { bGPdata *gpd = p->gpd; @@ -310,7 +320,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] } /* add current stroke-point to buffer (returns whether point was successfully added) */ -static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) +static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, double curtime) { bGPdata *gpd = p->gpd; tGPspoint *pt; @@ -325,6 +335,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* increment buffer size */ gpd->sbuffer_size++; @@ -338,6 +349,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* if this is just the second point we've added, increment the buffer size * so that it will be drawn properly... @@ -361,6 +373,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* increment counters */ gpd->sbuffer_size++; @@ -378,10 +391,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* if there's stroke for this poly line session add (or replace last) point * to stroke. This allows to draw lines more interactively (see new segment - * during mouse slide, i.e.) + * during mouse slide, e.g.) */ if (gp_stroke_added_check(p)) { bGPDstroke *gps = p->gpf->strokes.last; @@ -410,8 +424,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pts->pressure = pt->pressure; + pts->time = pt->time; } /* increment counters */ @@ -425,18 +440,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) return GP_STROKEADD_INVALID; } - -/* temp struct for gp_stroke_smooth() */ -typedef struct tGpSmoothCo { - int x; - int y; -} tGpSmoothCo; - /* smooth a stroke (in buffer) before storing it */ static void gp_stroke_smooth(tGPsdata *p) { bGPdata *gpd = p->gpd; - tGpSmoothCo *smoothArray, *spc; + tGPspoint *spt, tmp_spt[3]; int i = 0, cmx = gpd->sbuffer_size; /* only smooth if smoothing is enabled, and we're not doing a straight line */ @@ -447,30 +455,28 @@ static void gp_stroke_smooth(tGPsdata *p) if ((cmx <= 2) || (gpd->sbuffer == NULL)) return; - /* create a temporary smoothing coordinates buffer, use to store calculated values to prevent sequential error */ - smoothArray = MEM_callocN(sizeof(tGpSmoothCo) * cmx, "gp_stroke_smooth smoothArray"); + /* Calculate smoothing coordinates using weighted-averages + * WARNING: we do NOT smooth first and last points (to avoid shrinkage) + */ + spt = (tGPspoint *)gpd->sbuffer; - /* first pass: calculate smoothing coordinates using weighted-averages */ - for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) { - const tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i); - const tGPspoint *pb = (i - 1 > 0) ? (pc - 1) : (pc); - const tGPspoint *pa = (i - 2 > 0) ? (pc - 2) : (pb); - const tGPspoint *pd = (i + 1 < cmx) ? (pc + 1) : (pc); + /* This (tmp_spt) small array stores the last two points' original coordinates, + * as we don't want to use already averaged ones! It is used as a cyclic buffer... + */ + tmp_spt[0] = *spt; + for (i = 1, spt++; i < cmx - 1; i++, spt++) { + const tGPspoint *pc = spt; + const tGPspoint *pb = &tmp_spt[(i - 1) % 3]; + const tGPspoint *pa = (i - 1 > 0) ? (&tmp_spt[(i - 2) % 3]) : (pb); + const tGPspoint *pd = pc + 1; const tGPspoint *pe = (i + 2 < cmx) ? (pc + 2) : (pd); - spc->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x); - spc->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y); - } - - /* second pass: apply smoothed coordinates */ - for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) { - tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i); + /* Store current point's original state for the two next points! */ + tmp_spt[i % 3] = *spt; - copy_v2_v2_int(&pc->x, &spc->x); + spt->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x); + spt->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y); } - - /* free temp array */ - MEM_freeN(smoothArray); } /* simplify a stroke (in buffer) before storing it @@ -492,7 +498,7 @@ static void gp_stroke_simplify(tGPsdata *p) /* don't simplify if less than 4 points in buffer */ if ((num_points <= 4) || (old_points == NULL)) return; - + /* clear buffer (but don't free mem yet) so that we can write to it * - firstly set sbuffer to NULL, so a new one is allocated * - secondly, reset flag after, as it gets cleared auto @@ -509,17 +515,21 @@ static void gp_stroke_simplify(tGPsdata *p) co[0] += (float)(old_points[offs].x * sfac); \ co[1] += (float)(old_points[offs].y * sfac); \ pressure += old_points[offs].pressure * sfac; \ + time += old_points[offs].time * sfac; \ } (void)0 + /* XXX Here too, do not lose start and end points! */ + gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time); for (i = 0, j = 0; i < num_points; i++) { if (i - j == 3) { - float co[2], pressure; + float co[2], pressure, time; int mco[2]; /* initialize values */ - co[0] = 0; - co[1] = 0; - pressure = 0; + co[0] = 0.0f; + co[1] = 0.0f; + pressure = 0.0f; + time = 0.0f; /* using macro, calculate new point */ GP_SIMPLIFY_AVPOINT(j, -0.25f); @@ -532,11 +542,13 @@ static void gp_stroke_simplify(tGPsdata *p) mco[1] = (int)co[1]; /* ignore return values on this... assume to be ok for now */ - gp_stroke_addpoint(p, mco, pressure); + gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time); j += 2; } } + gp_stroke_addpoint(p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure, + p->inittime + (double)old_points[num_points - 1].time); /* free old buffer */ MEM_freeN(old_points); @@ -571,13 +583,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* special case for poly line -- for already added stroke during session * coordinates are getting added to stroke immediately to allow more - * interactive behavior */ + * interactive behavior + */ if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { if (gp_stroke_added_check(p)) { return; } } - + /* allocate memory for a new stroke */ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); @@ -585,13 +598,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) gps->totpoints = totelem; gps->thickness = p->gpl->thickness; gps->flag = gpd->sbuffer_sflag; + gps->inittime = p->inittime; /* allocate enough memory for a continuous array for storage points */ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - + /* set pointer to first non-initialized point */ pt = gps->points + (gps->totpoints - totelem); - + /* copy points from the buffer to the stroke */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only -> only endpoints */ @@ -602,8 +616,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; pt++; } @@ -615,8 +630,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { @@ -626,8 +642,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } else { float *depth_arr = NULL; @@ -699,14 +716,15 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } if (depth_arr) MEM_freeN(depth_arr); } - + /* add stroke to frame */ BLI_addtail(&p->gpf->strokes, gps); gp_stroke_added_enable(p); @@ -719,7 +737,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) { bGPDspoint *pt_tmp = gps->points; bGPDstroke *gsn = NULL; - + /* if stroke only had two points, get rid of stroke */ if (gps->totpoints == 2) { /* free stroke points, then stroke */ @@ -729,7 +747,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) /* nothing left in stroke, so stop */ return 1; } - + /* if last segment, just remove segment from the stroke */ else if (i == gps->totpoints - 2) { /* allocate new points array, and assign most of the old stroke there */ @@ -743,7 +761,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) /* nothing left in stroke, so stop */ return 1; } - + /* if first segment, just remove segment from the stroke */ else if (i == 0) { /* allocate new points array, and assign most of the old stroke there */ @@ -751,13 +769,32 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint) * gps->totpoints); + /* We must adjust timings! + * Each point's timing data is a delta from stroke's inittime, so as we erase the first + * point of the stroke, we have to offset this inittime and all remaining points' delta values. + * This way we get a new stroke with exactly the same timing as if user had started drawing from + * the second point... + */ + { + bGPDspoint *pts; + float delta = pt_tmp[1].time; + int j; + + gps->inittime += (double)delta; + + pts = gps->points; + for (j = 0; j < gps->totpoints; j++, pts++) { + pts->time -= delta; + } + } + /* free temp buffer */ MEM_freeN(pt_tmp); /* no break here, as there might still be stuff to remove in this stroke */ return 0; } - + /* segment occurs in 'middle' of stroke, so split */ else { /* duplicate stroke, and assign 'later' data to that stroke */ @@ -769,6 +806,25 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) gsn->points = MEM_callocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points"); memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint) * gsn->totpoints); + /* We must adjust timings of this new stroke! + * Each point's timing data is a delta from stroke's inittime, so as we erase the first + * point of the stroke, we have to offset this inittime and all remaing points' delta values. + * This way we get a new stroke with exactly the same timing as if user had started drawing from + * the second point... + */ + { + bGPDspoint *pts; + float delta = pt_tmp[i].time; + int j; + + gsn->inittime += (double)delta; + + pts = gsn->points; + for (j = 0; j < gsn->totpoints; j++, pts++) { + pts->time -= delta; + } + } + /* adjust existing stroke */ gps->totpoints = i; gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); @@ -790,7 +846,7 @@ static short gp_stroke_eraser_strokeinside(const int mval[], const int UNUSED(mv const float mval_fl[2] = {mval[0], mval[1]}; const float screen_co_a[2] = {x0, y0}; const float screen_co_b[2] = {x1, y1}; - + if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) { return TRUE; } @@ -831,7 +887,7 @@ static void gp_point_to_xy(ARegion *ar, View2D *v2d, rctf *subrect, bGPDstroke * /* eraser tool - evaluation per stroke */ -// TODO: this could really do with some optimization (KD-Tree/BVH?) +/* TODO: this could really do with some optimization (KD-Tree/BVH?) */ static void gp_stroke_eraser_dostroke(tGPsdata *p, const int mval[], const int mvalo[], short rad, const rcti *rect, bGPDframe *gpf, bGPDstroke *gps) @@ -850,7 +906,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, gps->points, &x0, &y0); /* do boundbox check first */ - if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ if (((x0 - mval[0]) * (x0 - mval[0]) + (y0 - mval[1]) * (y0 - mval[1])) <= rad * rad) { @@ -868,10 +923,10 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* get points to work with */ pt1 = gps->points + i; pt2 = gps->points + i + 1; - + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt1, &x0, &y0); gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt2, &x1, &y1); - + /* check that point segment of the boundbox of the eraser stroke */ if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) || ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) { @@ -919,11 +974,11 @@ static void gp_session_validatebuffer(tGPsdata *p) /* clear memory of buffer (or allocate it if starting a new session) */ if (gpd->sbuffer) { - //printf("\t\tGP - reset sbuffer\n"); + /* printf("\t\tGP - reset sbuffer\n"); */ memset(gpd->sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX); } else { - //printf("\t\tGP - allocate sbuffer\n"); + /* printf("\t\tGP - allocate sbuffer\n"); */ gpd->sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer"); } @@ -932,6 +987,9 @@ static void gp_session_validatebuffer(tGPsdata *p) /* reset flags */ gpd->sbuffer_sflag = 0; + + /* reset inittime */ + p->inittime = 0.0; } /* (re)init new painting data */ @@ -959,8 +1017,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) /* supported views first */ case SPACE_VIEW3D: { - // View3D *v3d = curarea->spacedata.first; - // RegionView3D *rv3d = ar->regiondata; + /* View3D *v3d = curarea->spacedata.first; */ + /* RegionView3D *rv3d = ar->regiondata; */ /* set current area * - must verify that region data is 3D-view (and not something else) @@ -976,10 +1034,10 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) } } break; - + case SPACE_NODE: { - //SpaceNode *snode = curarea->spacedata.first; + /* SpaceNode *snode = curarea->spacedata.first; */ /* set current area */ p->sa = curarea; @@ -1007,7 +1065,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) break; case SPACE_IMAGE: { - //SpaceImage *sima = curarea->spacedata.first; + /* SpaceImage *sima = curarea->spacedata.first; */ /* set the current area */ p->sa = curarea; @@ -1072,7 +1130,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) if (ED_gpencil_session_active() == 0) { /* initialize undo stack, - * also, existing undo stack would make buffer drawn */ + * also, existing undo stack would make buffer drawn + */ gpencil_undo_init(p->gpd); } @@ -1107,7 +1166,7 @@ static void gp_session_cleanup(tGPsdata *p) /* free stroke buffer */ if (gpd->sbuffer) { - //printf("\t\tGP - free sbuffer\n"); + /* printf("\t\tGP - free sbuffer\n"); */ MEM_freeN(gpd->sbuffer); gpd->sbuffer = NULL; } @@ -1115,6 +1174,7 @@ static void gp_session_cleanup(tGPsdata *p) /* clear flags */ gpd->sbuffer_size = 0; gpd->sbuffer_sflag = 0; + p->inittime = 0.0; } /* init new stroke */ @@ -1259,7 +1319,8 @@ static void gp_paint_strokeend(tGPsdata *p) static void gp_paint_cleanup(tGPsdata *p) { /* p->gpd==NULL happens when stroke failed to initialize, - * for example. when GP is hidden in current space (sergey) */ + * for example when GP is hidden in current space (sergey) + */ if (p->gpd) { /* finish off a stroke */ gp_paint_strokeend(p); @@ -1307,7 +1368,7 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en else if (enable) { /* enable cursor */ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C), - NULL, // XXX + NULL, /* XXX */ gpencil_draw_eraser, p); } } @@ -1448,16 +1509,26 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { /* try to add point */ - short ok = gp_stroke_addpoint(p, p->mval, p->pressure); + short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { /* finish off old stroke */ gp_paint_strokeend(p); + /* And start a new one!!! Else, projection errors! */ + gp_paint_initstroke(p, p->paintmode); /* start a new stroke, starting from previous point */ - gp_stroke_addpoint(p, p->mvalo, p->opressure); - gp_stroke_addpoint(p, p->mval, p->pressure); + /* XXX Must manually reset inittime... */ + /* XXX We only need to reuse previous point if overflow! */ + if (ok == GP_STROKEADD_OVERFLOW) { + p->inittime = p->ocurtime; + gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); + } + else { + p->inittime = p->curtime; + } + gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -1473,6 +1544,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->ocurtime = p->curtime; } } @@ -1483,13 +1555,14 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) PointerRNA itemptr; float mousef[2]; int tablet = 0; - + /* convert from window-space to area-space mouse coordinates - * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... + * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... */ p->mval[0] = event->mval[0] + 1; p->mval[1] = event->mval[1] + 1; - + p->curtime = PIL_check_seconds_timer(); + /* handle pressure sensitivity (which is supplied by tablets) */ if (event->custom == EVT_DATA_TABLET) { wmTabletData *wmtab = event->customdata; @@ -1497,8 +1570,8 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) tablet = (wmtab->Active != EVT_TABLET_NONE); p->pressure = wmtab->Pressure; - //if (wmtab->Active == EVT_TABLET_ERASER) - // TODO... this should get caught by the keymaps which call drawing in the first place + /* if (wmtab->Active == EVT_TABLET_ERASER) */ + /* TODO... this should get caught by the keymaps which call drawing in the first place */ } else p->pressure = 1.0f; @@ -1519,14 +1592,17 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->inittime = p->ocurtime = p->curtime; /* special exception here for too high pressure values on first touch in - * windows for some tablets, then we just skip first touch .. + * windows for some tablets, then we just skip first touch... */ if (tablet && (p->pressure >= 0.99f)) return; } + RNA_float_set(&itemptr, "time", p->curtime - p->inittime); + /* apply the current latest drawing point */ gpencil_draw_apply(op, p); @@ -1541,18 +1617,18 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) { tGPsdata *p = NULL; - //printf("GPencil - Starting Re-Drawing\n"); + /* printf("GPencil - Starting Re-Drawing\n"); */ /* try to initialize context data needed while drawing */ if (!gpencil_draw_init(C, op)) { if (op->customdata) MEM_freeN(op->customdata); - //printf("\tGP - no valid data\n"); + /* printf("\tGP - no valid data\n"); */ return OPERATOR_CANCELLED; } else p = op->customdata; - //printf("\tGP - Start redrawing stroke\n"); + /* printf("\tGP - Start redrawing stroke\n"); */ /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement), * setting the relevant values in context at each step, then applying @@ -1561,20 +1637,21 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) { float mousef[2]; - //printf("\t\tGP - stroke elem\n"); + /* printf("\t\tGP - stroke elem\n"); */ /* get relevant data for this point from stroke */ RNA_float_get_array(&itemptr, "mouse", mousef); p->mval[0] = (int)mousef[0]; p->mval[1] = (int)mousef[1]; p->pressure = RNA_float_get(&itemptr, "pressure"); + p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime; if (RNA_boolean_get(&itemptr, "is_start")) { /* if first-run flag isn't set already (i.e. not true first stroke), * then we must terminate the previous one first before continuing */ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) { - // TODO: both of these ops can set error-status, but we probably don't need to worry + /* TODO: both of these ops can set error-status, but we probably don't need to worry */ gp_paint_strokeend(p); gp_paint_initstroke(p, p->paintmode); } @@ -1587,6 +1664,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->ocurtime = p->curtime; } /* apply this data as necessary now (as per usual) */ @@ -1594,7 +1672,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) } RNA_END; - //printf("\tGP - done\n"); + /* printf("\tGP - done\n"); */ /* cleanup */ gpencil_draw_exit(C, op); @@ -1640,7 +1718,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) /* set cursor */ if (p->paintmode == GP_PAINTMODE_ERASER) - WM_cursor_modal(win, BC_CROSSCURSOR); // XXX need a better cursor + WM_cursor_modal(win, BC_CROSSCURSOR); /* XXX need a better cursor */ else WM_cursor_modal(win, BC_PAINTBRUSHCURSOR); @@ -1650,7 +1728,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) */ if (event->val == KM_PRESS) { /* hotkey invoked - start drawing */ - //printf("\tGP - set first spot\n"); + /* printf("\tGP - set first spot\n"); */ p->status = GP_STATUS_PAINTING; /* handle the initial drawing - i.e. for just doing a simple dot */ @@ -1658,7 +1736,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) } else { /* toolbar invoked - don't start drawing yet... */ - //printf("\tGP - hotkey invoked... waiting for click-drag\n"); + /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */ } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); @@ -1677,7 +1755,7 @@ static int gpencil_area_exists(bContext *C, ScrArea *sa_test) static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) { tGPsdata *p = op->customdata; - + /* we must check that we're still within the area that we're set up to work from * otherwise we could crash (see bug #20586) */ @@ -1685,20 +1763,20 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) printf("\t\t\tGP - wrong area execution abort!\n"); p->status = GP_STATUS_ERROR; } - - //printf("\t\tGP - start stroke\n"); - + + /* printf("\t\tGP - start stroke\n"); */ + /* we may need to set up paint env again if we're resuming */ /* XXX: watch it with the paintmode! in future, * it'd be nice to allow changing paint-mode when in sketching-sessions */ /* XXX: with tablet events, we may event want to check for eraser here, for nicer tablet support */ - + if (gp_session_initdata(C, p)) gp_paint_initstroke(p, p->paintmode); - + if (p->status != GP_STATUS_ERROR) p->status = GP_STATUS_PAINTING; - + return op->customdata; } @@ -1723,7 +1801,7 @@ static void gpencil_stroke_end(wmOperator *op) static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p = op->customdata; - int estate = OPERATOR_RUNNING_MODAL; /* default exit state - we don't pass on events, GP is used with key-modifiers */ + int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */ /* if (event->type == NDOF_MOTION) * return OPERATOR_PASS_THROUGH; @@ -1735,8 +1813,19 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) * the stroke is converted to 3D only after * it is finished. This approach should work * better in tools that immediately apply - * in 3D space. */ + * in 3D space. + */ + /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */ + if (ISKEYBOARD(event->type)) { + if (ELEM4(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) { + /* allow some keys - for frame changing: [#33412] */ + } + else { + estate = OPERATOR_RUNNING_MODAL; + } + } + //printf("\tGP - handle modal event...\n"); /* exit painting mode (and/or end current stroke) @@ -1744,7 +1833,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) */ if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) { /* exit() ends the current stroke before cleaning up */ - //printf("\t\tGP - end of paint op + end of stroke\n"); + /* printf("\t\tGP - end of paint op + end of stroke\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -1768,7 +1857,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) if (sketch) { /* end stroke only, and then wait to resume painting soon */ - //printf("\t\tGP - end stroke only\n"); + /* printf("\t\tGP - end stroke only\n"); */ gpencil_stroke_end(op); /* we've just entered idling state, so this event was processed (but no others yet) */ @@ -1778,7 +1867,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } else { - //printf("\t\tGP - end of stroke + op\n"); + /* printf("\t\tGP - end of stroke + op\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -1801,7 +1890,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* handle painting mouse-movements? */ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) { /* handle drawing event */ - //printf("\t\tGP - add point\n"); + /* printf("\t\tGP - add point\n"); */ gpencil_draw_apply_event(op, event); /* finish painting operation if anything went wrong just now */ @@ -1811,7 +1900,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) } else { /* event handled, so just tag as running modal */ - //printf("\t\t\t\tGP - add point handled!\n"); + /* printf("\t\t\t\tGP - add point handled!\n"); */ estate = OPERATOR_RUNNING_MODAL; } } @@ -1822,7 +1911,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* just resize the brush (local version) * TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys */ - //printf("\t\tGP - resize eraser\n"); + /* printf("\t\tGP - resize eraser\n"); */ switch (event->type) { case WHEELUPMOUSE: /* larger */ case PADPLUSKEY: diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1d461f797d6..5cc1ecade3e 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -56,6 +56,7 @@ struct wmKeyConfig; typedef struct tGPspoint { int x, y; /* x and y coordinates of cursor (in relative to area) */ float pressure; /* pressure of tablet at this point */ + float time; /* Time relative to stroke start (used when converting to path) */ } tGPspoint; @@ -96,12 +97,13 @@ void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode void ED_gplayer_frames_delete(struct bGPDlayer *gpl); void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl); +void ED_gplayer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode); + #if 0 void free_gpcopybuf(void); void copy_gpdata(void); void paste_gpdata(void); -void snap_gplayer_frames(struct bGPDlayer *gpl, short mode); void mirror_gplayer_frames(struct bGPDlayer *gpl, short mode); #endif diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index a50b33966c6..9b726cea56c 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -49,7 +49,7 @@ void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sim int ED_space_image_color_sample(struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]); struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r); -void ED_space_image_release_buffer(struct SpaceImage *sima, void *lock); +void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock); int ED_space_image_has_buffer(struct SpaceImage *sima); void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height); diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 46ed9798d32..6644f59be94 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -83,12 +83,13 @@ void ED_mask_select_frame(struct MaskLayer *masklay, int selx, short select_mod void ED_masklayer_frames_delete(struct MaskLayer *masklay); void ED_masklayer_frames_duplicate(struct MaskLayer *masklay); +void ED_masklayer_snap_frames(struct MaskLayer *masklay, struct Scene *scene, short mode); + #if 0 void free_gpcopybuf(void); void copy_gpdata(void); void paste_gpdata(void); -void snap_masklayer_frames(struct MaskLayer *masklay, short mode); void mirror_masklayer_frames(struct MaskLayer *masklay, short mode); #endif diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 5ffcfbd94f0..865da8f0e6e 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -153,6 +153,11 @@ int EDBM_select_pick(struct bContext *C, const int mval[2], short extend, short void EDBM_selectmode_set(struct BMEditMesh *em); void EDBM_selectmode_convert(struct BMEditMesh *em, const short selectmode_old, const short selectmode_new); +/* user access this */ +int EDBM_selectmode_toggle(struct bContext *C, const short selectmode_new, + const int action, const int use_extend, const int use_expand); + + void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select); void EDBM_select_toggle_all(struct BMEditMesh *em); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index bd85e93f1af..f15f2418707 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -100,11 +100,6 @@ void ED_view3d_depth_tag_update(struct RegionView3D *rv3d); /* Projection */ #define IS_CLIPPED 12000 -/* TODO, these functions work quite differently, we should make them behave in a uniform way - * otherwise we can't be sure bugs are not added when we need to move from short->float types for eg - * - Campbell */ - - /* return values for ED_view3d_project_...() */ typedef enum { V3D_PROJ_RET_OK = 0, @@ -198,7 +193,8 @@ void ED_view3d_global_to_vector(struct RegionView3D *rv3d, const float coord[3], void ED_view3d_win_to_3d(struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]); void ED_view3d_win_to_delta(struct ARegion *ar, const float mval[2], float out[3]); void ED_view3d_win_to_vector(struct ARegion *ar, const float mval[2], float out[3]); -void ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); +void ED_view3d_win_to_segment(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); +int ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); void ED_view3d_ob_project_mat_get(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z); @@ -220,6 +216,9 @@ void ED_view3d_clipping_disable(void); float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]); +float ED_view3d_radius_to_persp_dist(const float angle, const float radius); +float ED_view3d_radius_to_ortho_dist(const float lens, const float radius); + void drawcircball(int mode, const float cent[3], float rad, float tmat[][4]); /* backbuffer select and draw support */ @@ -295,7 +294,10 @@ struct BGpic *ED_view3D_background_image_new(struct View3D *v3d); void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic); void ED_view3D_background_image_clear(struct View3D *v3d); +#define VIEW3D_MARGIN 1.4f float ED_view3d_offset_distance(float mat[4][4], float ofs[3]); + +float ED_scene_grid_scale(struct Scene *scene, const char **grid_unit); float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit); /* view matrix properties utilities */ diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index e400e44e944..99f7f0856b3 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -97,7 +97,7 @@ DEF_ICON(PLUGIN) /* various ui */ DEF_ICON(HELP) DEF_ICON(GHOST_ENABLED) -DEF_ICON(COLOR) +DEF_ICON(COLOR) /* see COLOR_RED/GREEN/BLUE */ DEF_ICON(LINKED) DEF_ICON(UNLINKED) DEF_ICON(HAND) @@ -428,9 +428,11 @@ DEF_ICON(CURVE_PATH) DEF_ICON(BLANK646) DEF_ICON(BLANK647) DEF_ICON(BLANK648) - DEF_ICON(BLANK649) - DEF_ICON(BLANK650) - DEF_ICON(BLANK651) +#endif +DEF_ICON(COLOR_RED) +DEF_ICON(COLOR_GREEN) +DEF_ICON(COLOR_BLUE) +#ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK652) DEF_ICON(BLANK653) DEF_ICON(BLANK654) @@ -593,6 +595,7 @@ DEF_ICON(MOD_REMESH) DEF_ICON(MOD_OCEAN) DEF_ICON(MOD_WARP) DEF_ICON(MOD_SKIN) +DEF_ICON(MOD_TRIANGULATE) #ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK166) DEF_ICON(BLANK167) @@ -606,7 +609,6 @@ DEF_ICON(MOD_SKIN) DEF_ICON(BLANK175) DEF_ICON(BLANK176) DEF_ICON(BLANK177) - DEF_ICON(BLANK177b) #endif /* ANIMATION */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index ed4b4ae027f..2dc552d0fce 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -542,7 +542,7 @@ typedef struct uiStringInfo { /* Note: Expects pointers to uiStringInfo structs as parameters. * Will fill them with translated strings, when possible. * Strings in uiStringInfo must be MEM_freeN'ed by caller. */ -void uiButGetStrInfo(struct bContext *C, uiBut *but, int nbr, ...); +void uiButGetStrInfo(struct bContext *C, uiBut *but, ...); /* Edit i18n stuff. */ /* Name of the main py op from i18n addon. */ @@ -615,7 +615,8 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int /* bfunc gets search item *poin as arg2, or if NULL the old string */ void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc, void *active); /* height in pixels, it's using hardcoded values still */ -int uiSearchBoxhHeight(void); +int uiSearchBoxHeight(void); +int uiSearchBoxWidth(void); void uiBlockSetHandleFunc(uiBlock *block, uiBlockHandleFunc func, void *arg); void uiBlockSetButmFunc(uiBlock *block, uiMenuHandleFunc func, void *arg); @@ -807,7 +808,7 @@ void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *p void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type, int levels, int brush); -void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic); +void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic); void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *used_ptr, const char *used_propname, int active_layer); void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname, @@ -816,6 +817,7 @@ void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *pt void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C); +void uiOperatorSearch_But(uiBut *but); void uiTemplateOperatorSearch(uiLayout *layout); void uiTemplateHeader3D(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index e879a01dbfb..f4e921e2fa4 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -215,7 +215,11 @@ enum { TH_NLA_META, TH_NLA_META_SEL, TH_NLA_SOUND, - TH_NLA_SOUND_SEL + TH_NLA_SOUND_SEL, + + TH_AXIS_X, /* X/Y/Z Axis */ + TH_AXIS_Y, + TH_AXIS_Z }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index b8e4fec1259..ce82e064531 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1677,7 +1677,7 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) { if (but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { PropertyType type; - char *buf = NULL; + const char *buf = NULL; int buf_len; type = RNA_property_type(but->rnaprop); @@ -1686,11 +1686,22 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) /* RNA string */ buf = RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen, &buf_len); } + else if (type == PROP_ENUM) { + /* RNA enum */ + int value = RNA_property_enum_get(&but->rnapoin, but->rnaprop); + if (RNA_property_enum_name(but->block->evil_C, &but->rnapoin, but->rnaprop, value, &buf)) { + BLI_strncpy(str, buf, maxlen); + buf = str; + } + } else if (type == PROP_POINTER) { /* RNA pointer */ PointerRNA ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop); buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len); } + else { + BLI_assert(0); + } if (!buf) { str[0] = '\0'; @@ -1698,7 +1709,7 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) else if (buf && buf != str) { /* string was too long, we have to truncate */ memcpy(str, buf, MIN2(maxlen, (size_t)buf_len + 1)); - MEM_freeN(buf); + MEM_freeN((void *)buf); } } else if (but->type == IDPOIN) { @@ -1841,6 +1852,17 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) return 0; } + else if (type == PROP_ENUM) { + int value; + if (RNA_property_enum_value(but->block->evil_C, &but->rnapoin, but->rnaprop, str, &value)) { + RNA_property_enum_set(&but->rnapoin, but->rnaprop, value); + return 1; + } + return 0; + } + else { + BLI_assert(0); + } } } else if (but->type == IDPOIN) { @@ -1902,8 +1924,9 @@ void ui_set_but_default(bContext *C, short all) static double soft_range_round_up(double value, double max) { - /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */ - double newmax = pow(10.0, ceil(log(value) / M_LN10)); + /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. + * checking for 0.0 prevents floating point exceptions */ + double newmax = (value != 0.0) ? pow(10.0, ceil(log(value) / M_LN10)) : 0.0; if (newmax * 0.2 >= max && newmax * 0.2 >= value) return newmax * 0.2; @@ -1915,8 +1938,9 @@ static double soft_range_round_up(double value, double max) static double soft_range_round_down(double value, double max) { - /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */ - double newmax = pow(10.0, floor(log(value) / M_LN10)); + /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. + * checking for 0.0 prevents floating point exceptions */ + double newmax = (value != 0.0) ? pow(10.0, floor(log(value) / M_LN10)) : 0.0; if (newmax * 5.0 <= max && newmax * 5.0 <= value) return newmax * 5.0; @@ -2422,7 +2446,7 @@ void uiBlockEndAlign(uiBlock *block) int ui_but_can_align(uiBut *but) { - return !ELEM3(but->type, LABEL, OPTION, OPTIONN); + return !ELEM4(but->type, LABEL, OPTION, OPTIONN, SEPR); } static void ui_block_do_align_but(uiBut *first, short nr) @@ -2802,6 +2826,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s EnumPropertyItem *item; int i, totitem, free; + /* TODO, translate after getting the item, saves many lookups */ RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free); for (i = 0; i < totitem; i++) { if (item[i].identifier[0] && item[i].value == (int)max) { @@ -3772,16 +3797,16 @@ void uiButSetFocusOnEnter(wmWindow *win, uiBut *but) wm_event_add(win, &event); } -void uiButGetStrInfo(bContext *C, uiBut *but, int nbr, ...) +void uiButGetStrInfo(bContext *C, uiBut *but, ...) { va_list args; + uiStringInfo *si; EnumPropertyItem *items = NULL, *item = NULL; int totitems, free_items = FALSE; - va_start(args, nbr); - while (nbr--) { - uiStringInfo *si = (uiStringInfo *) va_arg(args, void *); + va_start(args, but); + while ((si = (uiStringInfo *) va_arg(args, void *))) { int type = si->type; char *tmp = NULL; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 469bd11215e..4d96ad810d4 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -1597,17 +1597,15 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc &scopes->undist_marker, scopes->use_track_mask, width, height, scopes->track_pos); - if (tmpibuf->rect_float) - IMB_rect_from_float(tmpibuf); + if (tmpibuf) { + if (tmpibuf->rect_float) + IMB_rect_from_float(tmpibuf); - /* XXX: for debug only - * tmpibuf->ftype = PNG; - * IMB_saveiff(tmpibuf, "sample.png", IB_rect); */ - - if (tmpibuf->rect) - scopes->track_preview = tmpibuf; - else - IMB_freeImBuf(tmpibuf); + if (tmpibuf->rect) + scopes->track_preview = tmpibuf; + else + IMB_freeImBuf(tmpibuf); + } } if (!ok && scopes->track_preview) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6d262daab12..b80025e0d77 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -279,12 +279,7 @@ static int ui_is_a_warp_but(uiBut *but) static float ui_mouse_scale_warp_factor(const short shift) { - if (U.uiflag & USER_CONTINUOUS_MOUSE) { - return shift ? 0.05f : 1.0f; - } - else { - return 1.0f; - } + return shift ? 0.05f : 1.0f; } static void ui_mouse_scale_warp(uiHandleButtonData *data, @@ -292,16 +287,11 @@ static void ui_mouse_scale_warp(uiHandleButtonData *data, float *r_mx, float *r_my, const short shift) { - if (U.uiflag & USER_CONTINUOUS_MOUSE) { - const float fac = ui_mouse_scale_warp_factor(shift); - /* slow down the mouse, this is fairly picky */ - *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac); - *r_my = (data->dragstarty * (1.0f - fac) + my * fac); - } - else { - *r_mx = mx; - *r_my = my; - } + const float fac = ui_mouse_scale_warp_factor(shift); + + /* slow down the mouse, this is fairly picky */ + *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac); + *r_my = (data->dragstarty * (1.0f - fac) + my * fac); } /* file selectors are exempt from utf-8 checks */ @@ -3306,7 +3296,7 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, ui_get_but_vectorf(but, rgb); - if (color_profile && (int)but->a1) + if (color_profile && (int)but->a1 != UI_GRAD_SV) ui_block_to_display_space_v3(but->block, rgb); rgb_to_hsv_compat_v(rgb, hsv); @@ -3352,7 +3342,7 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, hsv_to_rgb_v(hsv, rgb); - if (color_profile && (int)but->a1) + if (color_profile && ((int)but->a1 != UI_GRAD_SV)) ui_block_to_scene_linear_v3(but->block, rgb); copy_v3_v3(data->vec, rgb); @@ -3378,7 +3368,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF ui_get_but_vectorf(but, rgb); - if (color_profile && (int)but->a1) + if (color_profile && (int)but->a1 != UI_GRAD_SV) ui_block_to_display_space_v3(but->block, rgb); rgb_to_hsv_compat_v(rgb, hsv); @@ -3418,7 +3408,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF hsv_to_rgb_v(hsv, rgb); - if (color_profile && (int)but->a1) + if (color_profile && (int)but->a1 != UI_GRAD_SV) ui_block_to_scene_linear_v3(but->block, rgb); copy_v3_v3(data->vec, rgb); @@ -4643,7 +4633,7 @@ static int ui_but_menu(bContext *C, uiBut *but) uiPopupMenu *pup; uiLayout *layout; int length; - char *name; + const char *name; uiStringInfo label = {BUT_GET_LABEL, NULL}; /* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/ @@ -4651,7 +4641,7 @@ static int ui_but_menu(bContext *C, uiBut *but) button_timers_tooltip_remove(C, but); - uiButGetStrInfo(C, but, 1, &label); + uiButGetStrInfo(C, but, &label, NULL); name = label.strinfo; pup = uiPupMenuBegin(C, name, ICON_NONE); @@ -6050,38 +6040,22 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) switch (event->type) { case MOUSEMOVE: { - /* if the mouse is over the button, do nothing */ - if (ui_mouse_inside_button(data->region, but, event->x, event->y)) { - break; - } + uiBut *bt; - /* if the mouse is over the menu, also do nothing */ if (data->menu && data->menu->region) { if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) { break; } - else { - /* make a rectangle between the menu and the button that opened it, - * this avoids any space between them exiting the popup. see [#29072] - campbell */ - rctf rct_all = but->rect; - rctf rct_win; + } - ui_block_to_window_fl(ar, block, &rct_all.xmin, &rct_all.ymin); - ui_block_to_window_fl(ar, block, &rct_all.xmax, &rct_all.ymax); - - BLI_rctf_rcti_copy(&rct_win, &data->menu->region->winrct); - BLI_rctf_union(&rct_all, &rct_win); - - if (BLI_rctf_isect_pt(&rct_all, event->x, event->y)) { - break; - } + bt = ui_but_find_mouse_over(ar, event->x, event->y); + + if (bt && bt->active != data) { + if (but->type != COLOR) { /* exception */ + data->cancel = TRUE; } + button_activate_state(C, but, BUTTON_STATE_EXIT); } - - if (but->type != COLOR) { /* exception */ - data->cancel = TRUE; - } - button_activate_state(C, but, BUTTON_STATE_EXIT); break; } } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 16159e0f73a..23d3810e058 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -176,7 +176,25 @@ struct uiBut { char *poin; float hardmin, hardmax, softmin, softmax; - float a1, a2; + + /* both these values use depends on the button type + * (polymorphic struct or union would be nicer for this stuff) */ + + /* (type == COLOR), Use UI_GRAD_* values. + * (type == NUM), Use to store RNA 'step' value, for dragging and click-step. + * (type == LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!). + * (type == SCROLL) Use as scroll size. + * (type == SEARCH_MENU) Use as number or rows. + */ + float a1; + + /* (type == HSVCIRCLE ), Use to store the luminosity. + * (type == NUM), Use to store RNA 'precision' value, for dragging and click-step. + * (type == LABEL), If (a1 == 1.0f) use a2 as a blending factor. + * (type == SEARCH_MENU) Use as number or columns. + */ + float a2; + float aspect; unsigned char col[4]; @@ -340,7 +358,7 @@ struct uiBlock { char color_profile; /* color profile for correcting linear colors for display */ - char *display_device; /* display devide name used to display this block, + char *display_device; /* display device name used to display this block, * used by color widgets to transform colors from/to scene linear */ }; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 5170fc7d51b..9759c22f30e 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -68,6 +68,8 @@ #define EM_SEPR_X 6 #define EM_SEPR_Y 6 +// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. + #define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \ if (ot == NULL) { \ ui_item_disabled(layout, _opname); \ @@ -428,7 +430,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in but->type = NUMSLI; } } - else if (subtype == PROP_DIRECTION) { + else if (subtype == PROP_DIRECTION && !expand) { uiDefButR_prop(block, BUT_NORMAL, 0, name, x, y, UI_UNIT_X * 3, UI_UNIT_Y * 3, ptr, prop, 0, 0, 0, -1, -1, NULL); } else { @@ -1382,6 +1384,12 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN but->rnasearchprop = searchprop; but->flag |= UI_ICON_LEFT | UI_TEXT_LEFT; + if (RNA_property_type(prop) == PROP_ENUM) { + /* XXX, this will have a menu string, + * but in this case we just want the text */ + but->str[0] = 0; + } + uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL); } } @@ -1399,13 +1407,14 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna prop = RNA_struct_find_property(ptr, propname); if (!prop) { - RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + RNA_warning("property not found: %s.%s", + RNA_struct_identifier(ptr->type), propname); return; } type = RNA_property_type(prop); - if (!ELEM(type, PROP_POINTER, PROP_STRING)) { - RNA_warning("Property %s must be a pointer or string", propname); + if (!ELEM3(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) { + RNA_warning("Property %s must be a pointer, string or enum", propname); return; } @@ -1413,11 +1422,13 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna if (!searchprop) { - RNA_warning("search collection property not found: %s.%s", RNA_struct_identifier(ptr->type), searchpropname); + RNA_warning("search collection property not found: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); return; } else if (RNA_property_type(searchprop) != PROP_COLLECTION) { - RNA_warning("search collection property is not a collection type: %s.%s", RNA_struct_identifier(ptr->type), searchpropname); + RNA_warning("search collection property is not a collection type: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); return; } @@ -1780,7 +1791,7 @@ static void ui_litem_layout_row(uiLayout *litem) if (item->flag) { /* fixed minimum size items */ - itemw = ui_item_fit(minw, fixedx, fixedw, MIN2(w, fixedw), !item->next, litem->alignment, NULL); + itemw = ui_item_fit(minw, fixedx, fixedw, min_ii(w, fixedw), !item->next, litem->alignment, NULL); fixedx += itemw; } else { @@ -1959,9 +1970,9 @@ static void ui_litem_estimate_column_flow(uiLayout *litem) ui_item_size(item, &itemw, &itemh); y -= itemh + style->buttonspacey; - miny = MIN2(miny, y); + miny = min_ii(miny, y); emy -= itemh; - maxw = MAX2(itemw, maxw); + maxw = max_ii(itemw, maxw); /* decide to go to next one */ if (col < flow->totcol - 1 && emy <= -emh) { @@ -2840,10 +2851,12 @@ const char *uiLayoutIntrospect(uiLayout *layout) return str; } +#ifdef USE_OP_RESET_BUT static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, void *UNUSED(arg_dummy2)) { WM_operator_properties_reset((wmOperator *)op_pt); } +#endif /* this function does not initialize the layout, functions can be called on the layout before and after */ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, @@ -2911,6 +2924,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, } } +#ifdef USE_OP_RESET_BUT /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled * but this is not so important if this button is drawn in those cases * (which isn't all that likely anyway) - campbell */ @@ -2925,6 +2939,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Reset operator defaults")); uiButSetFunc(but, ui_layout_operator_buts__reset_cb, op, NULL); } +#endif /* set various special settings for buttons */ { diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e7a5f993d32..e57e52d74b6 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -960,7 +960,6 @@ static int edittranslation_exec(bContext *C, wmOperator *op) const char *root = U.i18ndir; const char *uilng = BLF_lang_get(); - const int bufs_nbr = 10; uiStringInfo but_label = {BUT_GET_LABEL, NULL}; uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL}; uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL}; @@ -990,8 +989,8 @@ static int edittranslation_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - uiButGetStrInfo(C, but, bufs_nbr, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip, - &rna_struct, &rna_prop, &rna_enum, &rna_ctxt); + uiButGetStrInfo(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip, + &rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL); WM_operator_properties_create(&ptr, EDTSRC_I18N_OP_NAME); RNA_string_set(&ptr, "lang", uilng); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 28e361ccf5a..c13aadee069 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -46,6 +46,7 @@ #include "BKE_context.h" #include "BKE_screen.h" +#include "BKE_idcode.h" #include "BKE_global.h" #include "WM_api.h" @@ -426,7 +427,6 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) rctf rect_fl; rcti rect_i; - const int nbr_info = 6; uiStringInfo but_tip = {BUT_GET_TIP, NULL}; uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL}; uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL}; @@ -440,50 +440,11 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) /* create tooltip data */ data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData"); - uiButGetStrInfo(C, but, nbr_info, &but_tip, &enum_label, &enum_tip, &op_keymap, &rna_struct, &rna_prop); + uiButGetStrInfo(C, but, &but_tip, &enum_label, &enum_tip, &op_keymap, &rna_struct, &rna_prop, NULL); /* special case, enum rna buttons only have enum item description, * use general enum description too before the specific one */ -#if 0 - if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) { - const char *descr = RNA_property_description(but->rnaprop); - if (descr && descr[0]) { - BLI_strncpy(data->lines[data->totline], descr, sizeof(data->lines[0])); - data->color_id[data->totline] = UI_TIP_LC_MAIN; - data->totline++; - } - if (ELEM(but->type, ROW, MENU)) { - EnumPropertyItem *item; - int totitem, free; - int value = (but->type == ROW) ? (int)but->hardmax : (int)ui_get_but_val(but); - - RNA_property_enum_items_gettexted(C, &but->rnapoin, but->rnaprop, &item, &totitem, &free); - - for (i = 0; i < totitem; i++) { - if (item[i].identifier[0] && item[i].value == value) { - if (item[i].description && item[i].description[0]) { - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "%s: %s", - item[i].name, item[i].description); - data->color_id[data->totline] = UI_TIP_LC_SUBMENU; - data->totline++; - } - break; - } - } - - if (free) { - MEM_freeN(item); - } - } - } - - if (but->tip && but->tip[0] != '\0') { - BLI_strncpy(data->lines[data->totline], but->tip, sizeof(data->lines[0])); - data->color_id[data->totline] = UI_TIP_LC_MAIN; - data->totline++; - } -#else /* Tip */ if (but_tip.strinfo) { BLI_strncpy(data->lines[data->totline], but_tip.strinfo, sizeof(data->lines[0])); @@ -497,29 +458,13 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) data->color_id[data->totline] = UI_TIP_LC_SUBMENU; data->totline++; } -#endif -#if 0 - if (but->optype && !(but->block->flag & UI_BLOCK_LOOP)) { - /* operator keymap (not menus, they already have it) */ - prop = (but->opptr) ? but->opptr->data : NULL; - - if (WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, TRUE, - buf, sizeof(buf))) - { - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), buf); - data->color_id[data->totline] = UI_TIP_LC_NORMAL; - data->totline++; - } - } -#else /* Op shortcut */ if (op_keymap.strinfo) { BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), op_keymap.strinfo); data->color_id[data->totline] = UI_TIP_LC_NORMAL; data->totline++; } -#endif if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { /* full string */ @@ -553,15 +498,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) data->totline++; } } -#if 0 - /* rna info */ - if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) { - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s.%s"), - RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop)); - data->color_id[data->totline] = UI_TIP_LC_PYTHON; - data->totline++; - } -#endif + if (but->rnapoin.id.data) { ID *id = but->rnapoin.id.data; if (id->lib && id->lib->name) { @@ -603,30 +540,55 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) } } } -#if 0 - else if (ELEM(but->type, MENU, PULLDOWN)) { - if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) { - MenuType *mt = uiButGetMenuType(but); - if (mt) { - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s"), mt->idname); - data->color_id[data->totline] = UI_TIP_LC_PYTHON; - data->totline++; - } - } - } -#else if ((U.flag & USER_TOOLTIPS_PYTHON) == 0 && !but->optype && rna_struct.strinfo) { - if (rna_prop.strinfo) + if (rna_prop.strinfo) { /* Struct and prop */ BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), - TIP_("Python: %s.%s"), rna_struct.strinfo, rna_prop.strinfo); - else + TIP_("Python: %s.%s"), + rna_struct.strinfo, rna_prop.strinfo); + } + else { /* Only struct (e.g. menus) */ - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s"), rna_struct.strinfo); + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), + TIP_("Python: %s"), rna_struct.strinfo); + } data->color_id[data->totline] = UI_TIP_LC_PYTHON; data->totline++; + + if (but->rnapoin.id.data) { + /* this could get its own 'BUT_GET_...' type */ + PointerRNA *ptr = &but->rnapoin; + PropertyRNA *prop = but->rnaprop; + ID *id = ptr->id.data; + + char *id_path; + char *data_path = NULL; + + /* never fails */ + id_path = RNA_path_from_ID_python(id); + + if (ptr->id.data && ptr->data && prop) { + data_path = RNA_path_from_ID_to_property(ptr, prop); + } + + if (data_path) { + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), + "%s.%s", /* no need to translate */ + id_path, data_path); + MEM_freeN(data_path); + } + else if (prop) { + /* can't find the path. be explicit in our ignorance "..." */ + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), + "%s ... %s", /* no need to translate */ + id_path, rna_prop.strinfo ? rna_prop.strinfo : RNA_property_identifier(prop)); + } + MEM_freeN(id_path); + + data->color_id[data->totline] = UI_TIP_LC_PYTHON; + data->totline++; + } } -#endif /* Free strinfo's... */ if (but_tip.strinfo) @@ -642,7 +604,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) if (rna_prop.strinfo) MEM_freeN(rna_prop.strinfo); - assert(data->totline < MAX_TOOLTIP_LINES); + BLI_assert(data->totline < MAX_TOOLTIP_LINES); if (data->totline == 0) { MEM_freeN(data); @@ -826,11 +788,17 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon return 1; } -int uiSearchBoxhHeight(void) +int uiSearchBoxHeight(void) { return SEARCH_ITEMS * UI_UNIT_Y + 2 * MENU_TOP; } +int uiSearchBoxWidth(void) +{ + /* was hardcoded at 150 */ + return 9 * UI_UNIT_X; +} + /* ar is the search box itself */ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step) { @@ -1191,10 +1159,11 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) } } else { + const int searchbox_width = uiSearchBoxWidth(); rect_fl.xmin = but->rect.xmin - 5; /* align text with button */ rect_fl.xmax = but->rect.xmax + 5; /* symmetrical */ rect_fl.ymax = but->rect.ymin; - rect_fl.ymin = rect_fl.ymax - uiSearchBoxhHeight(); + rect_fl.ymin = rect_fl.ymax - uiSearchBoxHeight(); ofsx = (but->block->panel) ? but->block->panel->ofsx : 0; ofsy = (but->block->panel) ? but->block->panel->ofsy : 0; @@ -1202,8 +1171,8 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) BLI_rctf_translate(&rect_fl, ofsx, ofsy); /* minimal width */ - if (BLI_rctf_size_x(&rect_fl) < 150) { - rect_fl.xmax = rect_fl.xmin + 150; /* XXX arbitrary */ + if (BLI_rctf_size_x(&rect_fl) < searchbox_width) { + rect_fl.xmax = rect_fl.xmin + searchbox_width; } /* copy to int, gets projected if possible too */ @@ -1409,8 +1378,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, dir1 &= (UI_TOP | UI_DOWN); } - if (dir2 == 0) if (dir1 == UI_LEFT || dir1 == UI_RIGHT) dir2 = UI_DOWN; - if (dir2 == 0) if (dir1 == UI_TOP || dir1 == UI_DOWN) dir2 = UI_LEFT; + if ((dir2 == 0) && (dir1 == UI_LEFT || dir1 == UI_RIGHT)) dir2 = UI_DOWN; + if ((dir2 == 0) && (dir1 == UI_TOP || dir1 == UI_DOWN)) dir2 = UI_LEFT; /* no space at all? don't change */ if (left || right) { @@ -2254,13 +2223,11 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0; } - uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT); - copy_v3_v3(handle->retvec, but->editvec); uiBlockPicker(block, handle->retvec, &but->rnapoin, but->rnaprop, show_picker); - block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1; + block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT; uiBoundsBlock(block, 10); block->block_event_func = ui_picker_small_wheel_cb; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 24aca0c037d..f7a53c6bab2 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -185,15 +185,18 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL); - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, template.prv_rows, template.prv_cols, ""); + but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, + template.prv_rows, template.prv_cols, ""); uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); } /* list view */ else { + const int searchbox_width = uiSearchBoxWidth(); + const int searchbox_height = uiSearchBoxHeight(); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL); - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, ""); + but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); } @@ -315,33 +318,68 @@ static const char *template_id_browse_tip(StructRNA *type) if (type) { switch (RNA_type_to_ID_code(type)) { case ID_SCE: return N_("Browse Scene to be linked"); - case ID_OB: return N_("Browse Object to be linked"); - case ID_ME: return N_("Browse Mesh Data to be linked"); - case ID_CU: return N_("Browse Curve Data to be linked"); - case ID_MB: return N_("Browse Metaball Data to be linked"); - case ID_MA: return N_("Browse Material to be linked"); - case ID_TE: return N_("Browse Texture to be linked"); - case ID_IM: return N_("Browse Image to be linked"); - case ID_LT: return N_("Browse Lattice Data to be linked"); - case ID_LA: return N_("Browse Lamp Data to be linked"); - case ID_CA: return N_("Browse Camera Data to be linked"); - case ID_WO: return N_("Browse World Settings to be linked"); + case ID_OB: return N_("Browse Object to be linked"); + case ID_ME: return N_("Browse Mesh Data to be linked"); + case ID_CU: return N_("Browse Curve Data to be linked"); + case ID_MB: return N_("Browse Metaball Data to be linked"); + case ID_MA: return N_("Browse Material to be linked"); + case ID_TE: return N_("Browse Texture to be linked"); + case ID_IM: return N_("Browse Image to be linked"); + case ID_LT: return N_("Browse Lattice Data to be linked"); + case ID_LA: return N_("Browse Lamp Data to be linked"); + case ID_CA: return N_("Browse Camera Data to be linked"); + case ID_WO: return N_("Browse World Settings to be linked"); case ID_SCR: return N_("Choose Screen lay-out"); case ID_TXT: return N_("Browse Text to be linked"); case ID_SPK: return N_("Browse Speaker Data to be linked"); - case ID_SO: return N_("Browse Sound to be linked"); - case ID_AR: return N_("Browse Armature data to be linked"); - case ID_AC: return N_("Browse Action to be linked"); - case ID_NT: return N_("Browse Node Tree to be linked"); - case ID_BR: return N_("Browse Brush to be linked"); - case ID_PA: return N_("Browse Particle System to be linked"); - case ID_GD: return N_("Browse Grease Pencil Data to be linked"); + case ID_SO: return N_("Browse Sound to be linked"); + case ID_AR: return N_("Browse Armature data to be linked"); + case ID_AC: return N_("Browse Action to be linked"); + case ID_NT: return N_("Browse Node Tree to be linked"); + case ID_BR: return N_("Browse Brush to be linked"); + case ID_PA: return N_("Browse Particle System to be linked"); + case ID_GD: return N_("Browse Grease Pencil Data to be linked"); } } return N_("Browse ID data to be linked"); } -static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, const char *newop, const char *openop, const char *unlinkop) +/* Return a type-based i18n context, needed e.g. by "New" button. + * In most languages, this adjective takes different form based on gender of type name... + */ +static const char *template_id_context(StructRNA *type) +{ + if (type) { + switch (RNA_type_to_ID_code(type)) { + case ID_SCE: return BLF_I18NCONTEXT_ID_SCENE; + case ID_OB: return BLF_I18NCONTEXT_ID_OBJECT; + case ID_ME: return BLF_I18NCONTEXT_ID_MESH; + case ID_CU: return BLF_I18NCONTEXT_ID_CURVE; + case ID_MB: return BLF_I18NCONTEXT_ID_METABALL; + case ID_MA: return BLF_I18NCONTEXT_ID_MATERIAL; + case ID_TE: return BLF_I18NCONTEXT_ID_TEXTURE; + case ID_IM: return BLF_I18NCONTEXT_ID_IMAGE; + case ID_LT: return BLF_I18NCONTEXT_ID_LATTICE; + case ID_LA: return BLF_I18NCONTEXT_ID_LAMP; + case ID_CA: return BLF_I18NCONTEXT_ID_CAMERA; + case ID_WO: return BLF_I18NCONTEXT_ID_WORLD; + case ID_SCR: return BLF_I18NCONTEXT_ID_SCREEN; + case ID_TXT: return BLF_I18NCONTEXT_ID_TEXT; + case ID_SPK: return BLF_I18NCONTEXT_ID_SPEAKER; + case ID_SO: return BLF_I18NCONTEXT_ID_SOUND; + case ID_AR: return BLF_I18NCONTEXT_ID_ARMATURE; + case ID_AC: return BLF_I18NCONTEXT_ID_ACTION; + case ID_NT: return BLF_I18NCONTEXT_ID_NODETREE; + case ID_BR: return BLF_I18NCONTEXT_ID_BRUSH; + case ID_PA: return BLF_I18NCONTEXT_ID_PARTICLESETTINGS; + case ID_GD: return BLF_I18NCONTEXT_ID_GPENCIL; + } + } + return BLF_I18NCONTEXT_DEFAULT; +} + +static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, + const char *newop, const char *openop, const char *unlinkop) { uiBut *but; uiBlock *block; @@ -349,6 +387,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str // ListBase *lb; // UNUSED ID *id, *idfrom; int editable = RNA_property_editable(&template->ptr, template->prop); + const char *i18n_ctxt = template_id_context(type); idptr = RNA_property_pointer_get(&template->ptr, template->prop); id = idptr.data; @@ -400,19 +439,20 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str //text_idbutton(id, name); name[0] = '\0'; - but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); + but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, + &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT); if (id->lib) { if (id->flag & LIB_INDIRECT) { - but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Indirect library datablock, cannot change")); + but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Indirect library datablock, cannot change")); uiButSetFlag(but, UI_BUT_DISABLED); } else { - but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Direct linked library datablock, click to make local")); + but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local")); if (!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib)) uiButSetFlag(but, UI_BUT_DISABLED); } @@ -425,7 +465,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str BLI_snprintf(numstr, sizeof(numstr), "%d", id->us); - but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y, NULL, 0, 0, 0, 0, + but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Display number of users of this data (click to make a single-user copy)")); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE)); @@ -450,12 +491,39 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str if (flag & UI_ID_ADD_NEW) { int w = id ? UI_UNIT_X : (flag & UI_ID_OPEN) ? UI_UNIT_X * 3 : UI_UNIT_X * 6; + /* i18n markup, does nothing! */ + BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_DEFAULT, + BLF_I18NCONTEXT_ID_SCENE, + BLF_I18NCONTEXT_ID_OBJECT, + BLF_I18NCONTEXT_ID_MESH, + BLF_I18NCONTEXT_ID_CURVE, + BLF_I18NCONTEXT_ID_METABALL, + BLF_I18NCONTEXT_ID_MATERIAL, + BLF_I18NCONTEXT_ID_TEXTURE, + BLF_I18NCONTEXT_ID_IMAGE, + BLF_I18NCONTEXT_ID_LATTICE, + BLF_I18NCONTEXT_ID_LAMP, + BLF_I18NCONTEXT_ID_CAMERA, + BLF_I18NCONTEXT_ID_WORLD, + BLF_I18NCONTEXT_ID_SCREEN, + BLF_I18NCONTEXT_ID_TEXT); + BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_ID_SPEAKER, + BLF_I18NCONTEXT_ID_SOUND, + BLF_I18NCONTEXT_ID_ARMATURE, + BLF_I18NCONTEXT_ID_ACTION, + BLF_I18NCONTEXT_ID_NODETREE, + BLF_I18NCONTEXT_ID_BRUSH, + BLF_I18NCONTEXT_ID_PARTICLESETTINGS, + BLF_I18NCONTEXT_ID_GPENCIL); + if (newop) { - but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id) ? "" : IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL); + but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, + (id) ? "" : CTX_IFACE_(i18n_ctxt, "New"), 0, 0, w, UI_UNIT_Y, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); } else { - but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(i18n_ctxt, "New"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); } @@ -467,11 +535,13 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6; if (openop) { - but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL); + but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"), + 0, 0, w, UI_UNIT_Y, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN)); } else { - but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, + NULL, 0, 0, 0, 0, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN)); } @@ -488,7 +558,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str } else { but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Unlink datablock. Shift + Click to set users to zero, data will then not be saved")); + TIP_("Unlink datablock " + "(Shift + Click to set users to zero, data will then not be saved)")); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE)); if (RNA_property_flag(template->prop) & PROP_NEVER_NULL) @@ -505,7 +576,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str uiBlockEndAlign(block); } -static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) +static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) { TemplateID *template; PropertyRNA *prop; @@ -545,19 +617,24 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const MEM_freeN(template); } -void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop) +void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { - ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); + ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, + UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); } -void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop) +void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0); } -void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols) +void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int rows, int cols) { - ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); + ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, + UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); } /************************ ID Chooser Template ***************************/ @@ -567,7 +644,8 @@ void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const c * - propname: property identifier for property that ID-pointer gets stored to * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used */ -void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text) +void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, + const char *text) { PropertyRNA *propID, *propType; uiLayout *row; @@ -614,7 +692,8 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co * - propname: property identifier for property that path gets stored to * - root_ptr: struct that path gets built from */ -void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text) +void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), + const char *text) { PropertyRNA *propPath; uiLayout *row; @@ -707,7 +786,7 @@ static int modifier_can_delete(ModifierData *md) return 1; } -/* Check wheter Modifier is a simulation or not, this is used for switching to the physics/particles context tab */ +/* Check whether Modifier is a simulation or not, this is used for switching to the physics/particles context tab */ static int modifier_is_simulation(ModifierData *md) { /* Physic Tab */ @@ -779,7 +858,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, uiBlockBeginAlign(block); /* Softbody not allowed in this situation, enforce! */ if (((md->type != eModifierType_Softbody && md->type != eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && - (md->type != eModifierType_Surface) ) + (md->type != eModifierType_Surface) ) { uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE); uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE); @@ -791,7 +870,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, if (ob->type == OB_MESH) { if (modifier_couldBeCage(scene, md) && (index <= lastCageIndex)) { /* -- convert to rna ? */ - but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, + but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, + UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, TIP_("Apply modifier to editing cage during Edit mode")); if (index < cageIndex) uiButSetFlag(but, UI_BUT_DISABLED); @@ -802,7 +882,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, /* place holder button */ uiBlockSetEmboss(block, UI_EMBOSSN); - but = uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, NULL); + but = uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, NULL); uiButSetFlag(but, UI_BUT_DISABLED); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -812,7 +893,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { /* add disabled pre-tessellated button, so users could have * message for this modifiers */ - but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, + but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, + UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, TIP_("This modifier could be applied on splines' points only")); uiButSetFlag(but, UI_BUT_DISABLED); } @@ -866,15 +948,20 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA); - if (modifier_sameTopology(md) && !modifier_nonGeometrical(md)) - uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape Key"), 0, "apply_as", MODIFIER_APPLY_SHAPE); + if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) { + uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape Key"), 0, + "apply_as", MODIFIER_APPLY_SHAPE); + } } uiBlockClearButLock(block); uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); - if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke)) + if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, + eModifierType_Cloth, eModifierType_Smoke)) + { uiItemO(row, IFACE_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy"); + } } /* result is the layout block inside the box, that we return so that modifier settings can be drawn */ @@ -1046,8 +1133,10 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) uiBlockSetEmboss(block, UI_EMBOSSN); /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */ - uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco + 244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); - uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco + 262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); + uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco + 244, yco, 19, 19, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); + uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco + 262, yco, 19, 19, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -1076,7 +1165,8 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* enabled */ uiBlockSetEmboss(block, UI_EMBOSSN); - uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); + uiItemR(row, &ptr, "mute", 0, "", + (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); uiBlockSetEmboss(block, UI_EMBOSS); uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); @@ -1233,14 +1323,22 @@ void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, M RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr); uiLayoutRow(layout, TRUE); - uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, ""); - if (GS(parent->name) == ID_MA) - uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - else if (GS(parent->name) == ID_LA) - uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - else if (GS(parent->name) == ID_WO) - uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, ""); + uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_TEXTURE, 0, 0, ""); + if (GS(parent->name) == ID_MA) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + else if (GS(parent->name) == ID_LA) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + else if (GS(parent->name) == ID_WO) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_BOTH, 0, 0, ""); /* Alpha button for texture preview */ if (*pr_texture != TEX_PR_OTHER) { @@ -1330,7 +1428,8 @@ static void colorband_update_cb(bContext *UNUSED(C), void *bt_v, void *coba_v) } /* offset aligns from bottom, standard width 300, height 115 */ -static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb) +static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, + int xoffs, int yoffs, RNAUpdateCb *cb) { uiBut *bt; uiLayout *row; @@ -1349,13 +1448,16 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand /* XXX, todo for later - convert to operator - campbell */ - bt = uiDefBut(block, BUT, 0, "F", 95 + xoffs, line1_y, 20, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip colorband")); + bt = uiDefBut(block, BUT, 0, "F", 95 + xoffs, line1_y, 20, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Flip colorband")); uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); - uiDefButS(block, NUM, 0, "", 120 + xoffs, line1_y, 80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)), 0, 0, TIP_("Choose active color stop")); + uiDefButS(block, NUM, 0, "", 120 + xoffs, line1_y, 80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)), + 0, 0, TIP_("Choose active color stop")); - bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), - 210 + xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops")); + bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), + 210 + xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, + TIP_("Set interpolation between color stops")); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); uiBlockEndAlign(block); @@ -1391,10 +1493,11 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand bt = uiDefBut(block, BUT, 0, IFACE_("Add"), xs, butr->ymin + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Add a new color stop to the colorband")); uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); - bt = uiDefBut(block, BUT, 0, IFACE_("Delete"), xs + 2.0f * unit, butr->ymin + UI_UNIT_Y, 1.5f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Delete the active position")); + bt = uiDefBut(block, BUT, 0, IFACE_("Delete"), xs + 2.0f * unit, butr->ymin + UI_UNIT_Y, 1.5f * unit, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Delete the active position")); uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); - bt = uiDefBut(block, BUT, 0, "F", xs + 3.5f * unit, butr->ymin + UI_UNIT_Y, 0.5f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip the color ramp")); + bt = uiDefBut(block, BUT, 0, "F", xs + 3.5f * unit, butr->ymin + UI_UNIT_Y, 0.5f * unit, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Flip the color ramp")); uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); uiBlockEndAlign(block); @@ -1406,7 +1509,7 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand } bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), - xs + 10.0f * unit, butr->ymin + UI_UNIT_Y, unit * 4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, + xs + 10.0f * unit, butr->ymin + UI_UNIT_Y, unit * 4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops")); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); @@ -1416,7 +1519,8 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand uiBlockEndAlign(block); } -static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb) +static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, + int small, RNAUpdateCb *cb) { if (small) colorband_buttons_small(layout, block, coba, butr, cb); @@ -1485,7 +1589,8 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname hist->height = (hist->height <= UI_UNIT_Y) ? UI_UNIT_Y : hist->height; - bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist, 0, 0, 0, 0, ""); + bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist, + 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); @@ -1522,7 +1627,8 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname) scopes->wavefrm_height = (scopes->wavefrm_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->wavefrm_height; - bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); + bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes, + 0, 0, 0, 0, ""); (void)bt; /* UNUSED */ MEM_freeN(cb); @@ -1559,7 +1665,8 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna scopes->vecscope_height = (scopes->vecscope_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->vecscope_height; - bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); + bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), + scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); @@ -1658,10 +1765,14 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL); uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); uiBlockSetDirection(block, UI_RIGHT); @@ -1710,12 +1821,18 @@ static uiBlock *curvemap_tools_func(bContext *C, ARegion *ar, void *cumap_v) block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 50); @@ -1732,10 +1849,14 @@ static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_ block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 50); @@ -1775,7 +1896,8 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) } /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ -static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb) +static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, + int brush, RNAUpdateCb *cb) { CurveMapping *cumap = ptr->data; CurveMap *cm = &cumap->cm[cumap->cur]; @@ -1899,10 +2021,16 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe } if (cmp) { + const float range_clamp[2] = {0.0f, 1.0f}; + const float range_unclamp[2] = {-1000.0f, 1000.0f}; /* arbitrary limits here */ + const float *range = (cumap->flag & CUMA_DO_CLIP) ? range_clamp : range_unclamp; + uiLayoutRow(layout, TRUE); uiBlockSetNFunc(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap); - bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->x, 0.0f, 1.0f, 1, 5, ""); - bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->y, 0.0f, 1.0f, 1, 5, ""); + bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, + &cmp->x, range[0], range[1], 1, 5, ""); + bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, + &cmp->y, range[0], range[1], 1, 5, ""); } /* black/white levels */ @@ -1951,29 +2079,48 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn MEM_freeN(cb); } -/********************* ColorWheel Template ************************/ +/********************* ColorPicker Template ************************/ #define WHEEL_SIZE 100 -void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic) +/* This template now follows User Preference for type - name is not correct anymore... */ +void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, + int lock, int lock_luminosity, int cubic) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); uiBlock *block = uiLayoutGetBlock(layout); uiLayout *col, *row; - uiBut *but; + uiBut *but = NULL; float softmin, softmax, step, precision; - + if (!prop) { RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); return; } RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision); - - col = uiLayoutColumn(layout, FALSE); + + col = uiLayoutColumn(layout, TRUE); row = uiLayoutRow(col, TRUE); - - but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, ""); + + switch (U.color_picker_type) { + case USER_CP_CIRCLE: + but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, 0, 0, ""); + break; + case USER_CP_SQUARE_SV: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_SV, 0, ""); + break; + case USER_CP_SQUARE_HS: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_HS, 0, ""); + break; + case USER_CP_SQUARE_HV: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_HV, 0, ""); + break; + } if (lock) { but->flag |= UI_BUT_COLOR_LOCK; @@ -1989,10 +2136,31 @@ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propnam if (cubic) but->flag |= UI_BUT_COLOR_CUBIC; - uiItemS(row); - if (value_slider) - uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); + if (value_slider) { + switch (U.color_picker_type) { + case USER_CP_CIRCLE: + uiItemS(row); + uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, + -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); + break; + case USER_CP_SQUARE_SV: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_SV + 3, 0, ""); + break; + case USER_CP_SQUARE_HS: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_HS + 3, 0, ""); + break; + case USER_CP_SQUARE_HV: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_HV + 3, 0, ""); + break; + } + } } /********************* Layer Buttons Template ************************/ @@ -2150,7 +2318,8 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, state)) icon = ICON_LAYER_USED; - but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop, state, 0, 0, -1, -1, sca_state_name_get(ob, state)); + but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop, + state, 0, 0, -1, -1, sca_state_name_get(ob, state)); uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(state)); but->type = TOG; } @@ -2198,7 +2367,8 @@ static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int return rnaicon; } -static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id) +static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, + int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id) { uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; @@ -2212,7 +2382,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe /* list item behind label & other buttons */ sub = uiLayoutRow(overlap, FALSE); - but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); + but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, + 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); sub = uiLayoutRow(overlap, FALSE); @@ -2229,7 +2400,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe if (itemptr->type == &RNA_MeshTexturePolyLayer || itemptr->type == &RNA_MeshLoopColorLayer) { uiItemL(sub, name, icon); uiBlockSetEmboss(block, UI_EMBOSSN); - uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL); + uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", + 0, 0, 0, 0, 0, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) { @@ -2322,7 +2494,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiItemL(sub, name_final, icon); if (dynamicPaint_surfaceHasColorPreview(surface)) { uiBlockSetEmboss(block, UI_EMBOSSN); - uiDefIconButR(block, OPTION, 0, (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON, + uiDefIconButR(block, OPTION, 0, + (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -2411,7 +2584,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe } } -void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype) +void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, + const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype) { PropertyRNA *prop = NULL, *activeprop; PropertyType type, activetype; @@ -2487,7 +2661,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * row = uiLayoutRow(col, FALSE); icon = list_item_icon_get(C, &itemptr, rnaicon, 1); - but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); + but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, + activeprop, 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); @@ -2529,7 +2704,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* next/prev button */ BLI_snprintf(numstr, sizeof(numstr), "%d :", i); - but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, ""); + but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr, + activeprop, 0, 0, 0, 0, 0, ""); if (i == 0) uiButSetFlag(but, UI_BUT_DISABLED); } @@ -2586,7 +2762,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* add scrollbar */ if (len > items) { col = uiLayoutColumn(row, FALSE); - uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll, 0, len - items, items, 0, ""); + uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll, + 0, len - items, items, 0, ""); } } } @@ -2608,6 +2785,9 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { wmOperatorType *ot = BLI_ghashIterator_getValue(iter); + if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) + continue; + if (BLI_strcasestr(ot->name, str)) { if (WM_operator_poll((bContext *)C, ot)) { char name[256]; @@ -2633,6 +2813,11 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char BLI_ghashIterator_free(iter); } +void uiOperatorSearch_But(uiBut *but) +{ + uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); +} + void uiTemplateOperatorSearch(uiLayout *layout) { uiBlock *block; @@ -2643,7 +2828,7 @@ void uiTemplateOperatorSearch(uiLayout *layout) uiBlockSetCurLayout(block, layout); but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); - uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); + uiOperatorSearch_But(but); } /************************* Running Jobs Template **************************/ @@ -2733,19 +2918,19 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C) ui_abs = uiLayoutAbsolute(layout, FALSE); (void)ui_abs; /* UNUSED */ - uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, - 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8, NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job")); + uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job")); uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner), UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress")); uiLayoutRow(layout, FALSE); } if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST)) - uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, 85, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, - TIP_("Stop screencast")); + uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, 85, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop screencast")); if (screen->animtimer) - uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, - TIP_("Stop animation playback")); + uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, 100, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop animation playback")); } /************************* Reports for Last Operator Template **************************/ @@ -2784,7 +2969,8 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) rgb_float_to_uchar(but->col, rti->col); but->col[3] = 255; - but = uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); + but = uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, ""); but->col[0] = but->col[1] = but->col[2] = FTOCHAR(rti->grayscale); but->col[3] = 255; @@ -2805,14 +2991,15 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) uiBlockSetEmboss(block, UI_EMBOSSN); if (reports->list.first != reports->list.last) - uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, - UI_UNIT_X, UI_UNIT_Y, TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); + uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, + UI_UNIT_Y, TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); else uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); uiBlockSetEmboss(block, UI_EMBOSS); - uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); + uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, ""); } /********************************* Keymap *************************************/ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f41abce947e..c4b80f0a42f 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -651,8 +651,8 @@ static void widget_verts_to_quad_strip_open(uiWidgetBase *wtb, const int totvert for (a = 0; a < totvert; a++) { quad_strip[a * 2][0] = wtb->outer_v[a][0]; quad_strip[a * 2][1] = wtb->outer_v[a][1]; - quad_strip[a * 2 + 1][0] = wtb->outer_v[a][0]; - quad_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f; + quad_strip[a * 2 + 1][0] = wtb->inner_v[a][0]; + quad_strip[a * 2 + 1][1] = wtb->inner_v[a][1]; } } @@ -1044,6 +1044,8 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect) ui_text_clip_give_prev_off(but); len = strlen(but->drawstr); bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len)); + if (bytes < 0) + bytes = 1; but->drawstr[len - bytes] = 0; } @@ -2057,7 +2059,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa /* old below */ - for (dx = 0.0f; dx < 1.0f; dx += color_step) { + for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */ /* previous color */ copy_v3_v3(col0[0], col1[0]); copy_v3_v3(col0[1], col1[1]); @@ -2112,7 +2114,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa sx1 = rect->xmin + dx * BLI_rcti_size_x(rect); sx2 = rect->xmin + (dx + color_step) * BLI_rcti_size_x(rect); sy = rect->ymin; - dy = BLI_rcti_size_y(rect) / 3.0; + dy = (float)BLI_rcti_size_y(rect) / 3.0f; glBegin(GL_QUADS); for (a = 0; a < 3; a++, sy += dy) { @@ -2621,6 +2623,11 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat } +static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign)) +{ + 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)) { if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) { @@ -3028,6 +3035,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) break; case UI_WTYPE_NORMAL: + wt.custom = widget_normal; break; case UI_WTYPE_SCROLL: @@ -3267,7 +3275,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct break; case BUT_NORMAL: - ui_draw_but_NORMAL(but, &tui->wcol_regular, rect); + wt = widget_type(UI_WTYPE_NORMAL); break; case BUT_IMAGE: diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index e03a2887866..fa5d5806bb8 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -236,7 +236,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->shade2; break; case TH_HILITE: cp = ts->hilite; break; - + case TH_GRID: cp = ts->grid; break; case TH_WIRE: @@ -510,6 +510,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case TH_NLA_SOUND_SEL: cp = ts->nla_sound_sel; break; + + case TH_AXIS_X: + cp = btheme->tui.xaxis; break; + case TH_AXIS_Y: + cp = btheme->tui.yaxis; break; + case TH_AXIS_Z: + cp = btheme->tui.zaxis; break; } } } @@ -655,9 +662,14 @@ void ui_theme_init_default(void) /* UI buttons */ ui_widget_color_init(&btheme->tui); + btheme->tui.iconfile[0] = 0; btheme->tui.panel.show_header = FALSE; rgba_char_args_set(btheme->tui.panel.header, 0, 0, 0, 25); + + rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255); + rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255); + rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255); /* Bone Color Sets */ ui_theme_init_boneColorSets(btheme); @@ -1072,7 +1084,6 @@ float UI_GetThemeValuef(int colorid) cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); return ((float)cp[0]); - } /* get individual values, not scaled */ @@ -1082,7 +1093,6 @@ int UI_GetThemeValue(int colorid) cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); return ((int) cp[0]); - } @@ -1244,21 +1254,20 @@ void UI_ThemeClearColor(int colorid) void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3], const char axis) { + unsigned char col[3]; + switch (axis) { case 'X': - dst_col[0] = src_col[0] > 219 ? 255 : src_col[0] + 36; - dst_col[1] = src_col[1] < 26 ? 0 : src_col[1] - 26; - dst_col[2] = src_col[2] < 26 ? 0 : src_col[2] - 26; + UI_GetThemeColor3ubv(TH_AXIS_X, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; case 'Y': - dst_col[0] = src_col[0] < 46 ? 0 : src_col[0] - 36; - dst_col[1] = src_col[1] > 189 ? 255 : src_col[1] + 66; - dst_col[2] = src_col[2] < 46 ? 0 : src_col[2] - 36; + UI_GetThemeColor3ubv(TH_AXIS_Y, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; case 'Z': - dst_col[0] = src_col[0] < 26 ? 0 : src_col[0] - 26; - dst_col[1] = src_col[1] < 26 ? 0 : src_col[1] - 26; - dst_col[2] = src_col[2] > 209 ? 255 : src_col[2] + 46; + UI_GetThemeColor3ubv(TH_AXIS_Z, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; default: BLI_assert(!"invalid axis arg"); @@ -1946,6 +1955,16 @@ void init_userdef_do_versions(void) rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255); } } + + if (bmain->versionfile < 264 || (bmain->versionfile == 264 && bmain->subversionfile < 9)) { + bTheme *btheme; + + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255); + rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255); + rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255); + } + } /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c index 561ad004a1d..707622fa841 100644 --- a/source/blender/editors/mask/mask_editaction.c +++ b/source/blender/editors/mask/mask_editaction.c @@ -18,13 +18,13 @@ * The Original Code is Copyright (C) 2008, Blender Foundation * This is a new part of Blender * - * Contributor(s): Joshua Leung + * Contributor(s): Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ /** \file blender/editors/mask/mask_editaction.c - * \ingroup edgpencil + * \ingroup edmask */ #include @@ -49,17 +49,18 @@ #include "ED_anim_api.h" #include "ED_keyframes_edit.h" #include "ED_mask.h" /* own include */ +#include "ED_markers.h" /* ***************************************** */ /* NOTE ABOUT THIS FILE: - * This file contains code for editing Grease Pencil data in the Action Editor - * as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings. - * Therefore, this file mostly contains functions for selecting Grease-Pencil frames. + * This file contains code for editing Mask data in the Action Editor + * as a 'keyframes', so that a user can adjust the timing of Mask shapekeys. + * Therefore, this file mostly contains functions for selecting Mask frames (shapekeys). */ /* ***************************************** */ /* Generics - Loopers */ -/* Loops over the gp-frames for a gp-layer, and applies the given callback */ +/* Loops over the mask-frames for a mask-layer, and applies the given callback */ short ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *)) { MaskLayerShape *masklay_shape; @@ -82,7 +83,7 @@ short ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*maskl /* ****************************************** */ /* Data Conversion Tools */ -/* make a listing all the gp-frames in a layer as cfraelems */ +/* make a listing all the mask-frames in a layer as cfraelems */ void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel) { MaskLayerShape *masklay_shape; @@ -92,7 +93,7 @@ void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short only if (ELEM(NULL, masklay, elems)) return; - /* loop through gp-frames, adding */ + /* loop through mask-frames, adding */ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { if ((onlysel == 0) || (masklay_shape->flag & MASK_SHAPE_SELECT)) { ce = MEM_callocN(sizeof(CfraElem), "CfraElem"); @@ -127,7 +128,7 @@ short ED_masklayer_frame_select_check(MaskLayer *masklay) return 0; } -/* helper function - select gp-frame based on SELECT_* mode */ +/* helper function - select mask-frame based on SELECT_* mode */ static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode) { if (masklay_shape == NULL) @@ -223,7 +224,7 @@ void ED_masklayer_frames_delete(MaskLayer *masklay) } } -/* Duplicate selected frames from given gp-layer */ +/* Duplicate selected frames from given mask-layer */ void ED_masklayer_frames_duplicate(MaskLayer *masklay) { MaskLayerShape *masklay_shape, *gpfn; @@ -249,3 +250,57 @@ void ED_masklayer_frames_duplicate(MaskLayer *masklay) } } } + +/* -------------------------------------- */ +/* Snap Tools */ + +static short snap_masklayer_nearest(MaskLayerShape *masklay_shape, Scene *UNUSED(scene)) +{ + if (masklay_shape->flag & MASK_SHAPE_SELECT) + masklay_shape->frame = (int)(floor(masklay_shape->frame + 0.5)); + return 0; +} + +static short snap_masklayer_nearestsec(MaskLayerShape *masklay_shape, Scene *scene) +{ + float secf = (float)FPS; + if (masklay_shape->flag & MASK_SHAPE_SELECT) + masklay_shape->frame = (int)(floorf(masklay_shape->frame / secf + 0.5f) * secf); + return 0; +} + +static short snap_masklayer_cframe(MaskLayerShape *masklay_shape, Scene *scene) +{ + if (masklay_shape->flag & MASK_SHAPE_SELECT) + masklay_shape->frame = (int)CFRA; + return 0; +} + +static short snap_masklayer_nearmarker(MaskLayerShape *masklay_shape, Scene *scene) +{ + if (masklay_shape->flag & MASK_SHAPE_SELECT) + masklay_shape->frame = (int)ED_markers_find_nearest_marker_time(&scene->markers, (float)masklay_shape->frame); + return 0; +} + +/* snap selected frames to ... */ +void ED_masklayer_snap_frames(MaskLayer *masklay, Scene *scene, short mode) +{ + switch (mode) { + case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */ + ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearest); + break; + case SNAP_KEYS_CURFRAME: /* snap to current frame */ + ED_masklayer_frames_looper(masklay, scene, snap_masklayer_cframe); + break; + case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */ + ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearmarker); + break; + case SNAP_KEYS_NEARSEC: /* snap to nearest second */ + ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearestsec); + break; + default: /* just in case */ + break; + } +} + diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 70b359d3e28..4a425c83d86 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -55,6 +55,8 @@ /* ********* add primitive operators ************* */ +/* BMESH_TODO: 'state' is not a good name, should be flipped and called 'was_editmode', + * or at least something more descriptive */ static Object *make_prim_init(bContext *C, const char *idname, float *dia, float mat[][4], int *state, const float loc[3], const float rot[3], const unsigned int layer) @@ -81,15 +83,17 @@ static Object *make_prim_init(bContext *C, const char *idname, static void make_prim_finish(bContext *C, Object *obedit, int *state, int enter_editmode) { BMEditMesh *em = BMEdit_FromObject(obedit); + const int exit_editmode = (*state && !enter_editmode); /* Primitive has all verts selected, use vert select flush * to push this up to edges & faces. */ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); - EDBM_update_generic(C, em, TRUE); + /* only recalc editmode tessface if we are staying in editmode */ + EDBM_update_generic(C, em, !exit_editmode); /* userdef */ - if (*state && !enter_editmode) { + if (exit_editmode) { ED_object_exit_editmode(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */ } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); @@ -108,8 +112,8 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", 1, 1, dia, mat)) + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4", 1, 1, dia, mat)) { return OPERATOR_CANCELLED; } @@ -149,7 +153,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_cube mat=%m4 size=%f", mat, dia * 2.0f)) { + if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_cube matrix=%m4 size=%f", mat, dia * 2.0f)) { return OPERATOR_CANCELLED; } @@ -198,9 +202,9 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b mat=%m4", - RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius") * dia, + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b matrix=%m4", + RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius"), cap_end, cap_tri, mat)) { return OPERATOR_CANCELLED; @@ -221,6 +225,7 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_circle_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_circle_exec; ot->poll = ED_operator_scene_editable; @@ -253,13 +258,13 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", - "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", + em, op, "verts.out", + "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4", RNA_int_get(op->ptr, "vertices"), - RNA_float_get(op->ptr, "radius") * dia, - RNA_float_get(op->ptr, "radius") * dia, + RNA_float_get(op->ptr, "radius"), + RNA_float_get(op->ptr, "radius"), cap_end, cap_tri, - RNA_float_get(op->ptr, "depth") * dia, mat)) + RNA_float_get(op->ptr, "depth"), mat)) { return OPERATOR_CANCELLED; } @@ -279,6 +284,7 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_cylinder_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_cylinder_exec; ot->poll = ED_operator_scene_editable; @@ -313,10 +319,10 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", - "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", - RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1") * dia, - RNA_float_get(op->ptr, "radius2") * dia, cap_end, cap_tri, RNA_float_get(op->ptr, "depth") * dia, mat)) + em, op, "verts.out", + "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4", + RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1"), + RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"), mat)) { return OPERATOR_CANCELLED; } @@ -336,6 +342,7 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_cone_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_cone_exec; ot->poll = ED_operator_scene_editable; @@ -368,11 +375,11 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4", RNA_int_get(op->ptr, "x_subdivisions"), RNA_int_get(op->ptr, "y_subdivisions"), - RNA_float_get(op->ptr, "size") * dia, mat)) + RNA_float_get(op->ptr, "size"), mat)) { return OPERATOR_CANCELLED; } @@ -392,6 +399,7 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_grid_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_grid_exec; ot->poll = ED_operator_scene_editable; @@ -420,14 +428,14 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op) if (!view_aligned) rot[0] += (float)M_PI / 2.0f; - obedit = make_prim_init(C, "Monkey", &dia, mat, &state, loc, rot, layer); + obedit = make_prim_init(C, "Suzanne", &dia, mat, &state, loc, rot, layer); mat[0][0] *= dia; mat[1][1] *= dia; mat[2][2] *= dia; em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_monkey mat=%m4", mat)) { + if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_monkey matrix=%m4", mat)) { return OPERATOR_CANCELLED; } @@ -466,10 +474,10 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_uvsphere segments=%i revolutions=%i diameter=%f mat=%m4", + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_uvsphere u_segments=%i v_segments=%i diameter=%f matrix=%m4", RNA_int_get(op->ptr, "segments"), RNA_int_get(op->ptr, "ring_count"), - RNA_float_get(op->ptr, "size") * dia, mat)) + RNA_float_get(op->ptr, "size"), mat)) { return OPERATOR_CANCELLED; } @@ -489,6 +497,7 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_uv_sphere_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_uvsphere_exec; ot->poll = ED_operator_scene_editable; @@ -518,10 +527,10 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", - "create_icosphere subdivisions=%i diameter=%f mat=%m4", + em, op, "verts.out", + "create_icosphere subdivisions=%i diameter=%f matrix=%m4", RNA_int_get(op->ptr, "subdivisions"), - RNA_float_get(op->ptr, "size") * dia, mat)) + RNA_float_get(op->ptr, "size"), mat)) { return OPERATOR_CANCELLED; } @@ -541,6 +550,7 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_ico_sphere_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_icosphere_exec; ot->poll = ED_operator_scene_editable; diff --git a/source/blender/editors/mesh/editmesh_bvh.c b/source/blender/editors/mesh/editmesh_bvh.c index 468d0d8d8c6..8e397797dd9 100644 --- a/source/blender/editors/mesh/editmesh_bvh.c +++ b/source/blender/editors/mesh/editmesh_bvh.c @@ -157,13 +157,13 @@ BMBVHTree *BMBVH_NewBVH(BMEditMesh *em, int flag, Scene *scene, Object *obedit) if (flag & BMBVH_RESPECT_SELECT) { - /* note, the arrays wont allign now! take care */ + /* note, the arrays wont align now! take care */ if (!BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_SELECT)) { continue; } } else if (flag & BMBVH_RESPECT_HIDDEN) { - /* note, the arrays wont allign now! take care */ + /* note, the arrays wont align now! take care */ if (BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_HIDDEN)) { continue; } @@ -399,7 +399,7 @@ int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v3d, Obje const float mval_f[2] = {ar->winx / 2.0f, ar->winy / 2.0f}; - ED_view3d_win_to_segment_clip(ar, v3d, mval_f, origin, end); + ED_view3d_win_to_segment(ar, v3d, mval_f, origin, end); invert_m4_m4(invmat, obedit->obmat); mul_m4_v3(invmat, origin); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 82447cc0168..a59c491fe13 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -207,8 +207,12 @@ typedef struct KnifeTool_OpData { static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f); +#if 0 static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], float r_origin[3], float r_ray[3]); +#endif +static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs, + float r_origin[3], float r_dest[3]); static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) { @@ -379,14 +383,13 @@ static void knife_start_cut(KnifeTool_OpData *kcd) if (kcd->prev.vert == NULL && kcd->prev.edge == NULL && is_zero_v3(kcd->prev.cage)) { /* Make prevcage a point on the view ray to mouse closest to a point on model: choose vertex 0 */ - float origin[3], ray[3], co[3]; + float origin[3], origin_ofs[3]; BMVert *v0; - knife_input_ray_cast(kcd, kcd->curr.mval, origin, ray); - add_v3_v3v3(co, origin, ray); + knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs); v0 = BM_vert_at_index(kcd->em->bm, 0); if (v0) { - closest_to_line_v3(kcd->prev.cage, v0->co, co, origin); + closest_to_line_v3(kcd->prev.cage, v0->co, origin_ofs, origin); copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */ copy_v3_v3(kcd->curr.cage, kcd->prev.cage); copy_v3_v3(kcd->curr.co, kcd->prev.co); @@ -1178,7 +1181,6 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, result = results = BLI_bvhtree_overlap(tree, tree2, &tot); for (i = 0; i < tot; i++, result++) { - float p[3]; BMLoop *l1; BMFace *hitf; ListBase *lst; @@ -1197,7 +1199,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, } if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) { - float no[3], view[3], sp[3]; + float p[3], no[3], view[3], sp[3]; interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda); @@ -1212,6 +1214,11 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, { continue; } + if ((kcd->vc.rv3d->rflag & RV3D_CLIPPING) && + ED_view3d_clipping_test(kcd->vc.rv3d, p, TRUE)) + { + continue; + } knife_project_v3(kcd, p, sp); ED_view3d_unproject(mats, view, sp[0], sp[1], 0.0f); @@ -1403,6 +1410,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) BLI_smallhash_release(ehash); } +/* this works but gives numeric problems [#33400] */ +#if 0 static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], float r_origin[3], float r_ray[3]) { @@ -1433,17 +1442,41 @@ static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], mul_m4_v3(kcd->ob->imat, r_origin); mul_m3_v3(imat, r_ray); } +#endif + +static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs, + float r_origin[3], float r_origin_ofs[3]) +{ + bglMats mats; + float mval[2]; + + knife_bgl_get_mats(kcd, &mats); + + mval[0] = (float)mval_i[0]; + mval[1] = (float)mval_i[1]; + + /* unproject to find view ray */ + ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); + ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs); + + /* transform into object space */ + invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); + + mul_m4_v3(kcd->ob->imat, r_origin); + mul_m4_v3(kcd->ob->imat, r_origin_ofs); +} static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], int *is_space) { BMFace *f; float dist = KMAXDIST; float origin[3]; + float origin_ofs[3]; float ray[3]; /* unproject to find view ray */ - knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray); - add_v3_v3v3(co, origin, ray); + knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs); + sub_v3_v3v3(ray, origin_ofs, origin); f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco); @@ -1494,12 +1527,7 @@ static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius) dis = len_v2v2(kfv->sco, sco); if (dis < radius) { if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { - float vec[3]; - - copy_v3_v3(vec, kfv->cageco); - mul_m4_v3(kcd->vc.obedit->obmat, vec); - - if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { + if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) { c++; } } @@ -1566,13 +1594,10 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo dis = dist_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco); if (dis < curdis && dis < maxdist) { if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { - float labda = labda_PdistVL2Dfl(sco, kfe->v1->sco, kfe->v2->sco); + float labda = line_point_factor_v2(sco, kfe->v1->sco, kfe->v2->sco); float vec[3]; - vec[0] = kfe->v1->cageco[0] + labda * (kfe->v2->cageco[0] - kfe->v1->cageco[0]); - vec[1] = kfe->v1->cageco[1] + labda * (kfe->v2->cageco[1] - kfe->v1->cageco[1]); - vec[2] = kfe->v1->cageco[2] + labda * (kfe->v2->cageco[2] - kfe->v1->cageco[2]); - mul_m4_v3(kcd->vc.obedit->obmat, vec); + interp_v3_v3v3(vec, kfe->v1->cageco, kfe->v2->cageco, labda); if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { cure = kfe; @@ -1664,12 +1689,7 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo dis = len_v2v2(kfv->sco, sco); if (dis < curdis && dis < maxdist) { if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { - float vec[3]; - - copy_v3_v3(vec, kfv->cageco); - mul_m4_v3(kcd->vc.obedit->obmat, vec); - - if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { + if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) { curv = kfv; curdis = dis; } @@ -1768,12 +1788,12 @@ static int knife_update_active(KnifeTool_OpData *kcd) * Note that drawing lines in `free-space` isn't properly supported * but theres no guarantee (0, 0, 0) has any geometry either - campbell */ if (kcd->curr.vert == NULL && kcd->curr.edge == NULL) { - float origin[3], ray[3], co[3]; + float origin[3]; + float origin_ofs[3]; - knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray); - add_v3_v3v3(co, origin, ray); + knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs); - closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, co, origin); + closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, origin_ofs, origin); } if (kcd->mode == MODE_DRAGGING) { @@ -1823,7 +1843,7 @@ static void remerge_faces(KnifeTool_OpData *kcd) BMO_op_initf(bm, &bmop, "beautify_fill faces=%ff constrain_edges=%fe", FACE_NEW, BOUNDARY); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_FACE, FACE_NEW); + BMO_slot_buffer_flag_enable(bm, &bmop, "geom.out", BM_FACE, FACE_NEW); BMO_op_finish(bm, &bmop); @@ -1965,7 +1985,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) kfe->e = NULL; } - kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, TRUE); + kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, kfe->e, BOUNDARY); for (ref = kfe->faces.first; ref; ref = ref->next) { @@ -2067,7 +2087,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) } } - BLI_scanfill_calc(&sf_ctx, FALSE); + BLI_scanfill_calc(&sf_ctx, 0); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { BMVert *v1 = sf_tri->v3->tmp.p, *v2 = sf_tri->v2->tmp.p, *v3 = sf_tri->v1->tmp.p; @@ -2573,8 +2593,8 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha int nco = BLI_countlist(chain) - 1; float (*cos)[3] = NULL; KnifeVert **kverts; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, nco, __func__); - BLI_array_fixedstack_declare(kverts, BM_NGON_STACK_SIZE, nco, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, nco, __func__); + BLI_array_fixedstack_declare(kverts, BM_DEFAULT_NGON_STACK_SIZE, nco, __func__); kfe = ((Ref *)chain->first)->ref; v1 = kfe->v1->v ? kfe->v1->v : kfe->v2->v; @@ -3085,6 +3105,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) { Object *obedit = CTX_data_edit_object(C); KnifeTool_OpData *kcd = op->customdata; + int do_refresh = FALSE; if (!obedit || obedit->type != OB_MESH || BMEdit_FromObject(obedit) != kcd->em) { knifetool_exit(C, op); @@ -3093,6 +3114,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) } view3d_operator_needs_opengl(C); + ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */ if (kcd->mode == MODE_PANNING) kcd->mode = kcd->prevmode; @@ -3124,6 +3146,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) knife_update_active(kcd); knife_update_header(C, kcd); ED_region_tag_redraw(kcd->ar); + do_refresh = TRUE; break; case KNF_MODAL_MIDPOINT_OFF: kcd->snap_midpoints = 0; @@ -3132,25 +3155,29 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) knife_update_active(kcd); knife_update_header(C, kcd); ED_region_tag_redraw(kcd->ar); + do_refresh = TRUE; break; case KNF_MODEL_IGNORE_SNAP_ON: ED_region_tag_redraw(kcd->ar); kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 1; knife_update_header(C, kcd); + do_refresh = TRUE; break; case KNF_MODEL_IGNORE_SNAP_OFF: ED_region_tag_redraw(kcd->ar); kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 0; knife_update_header(C, kcd); + do_refresh = TRUE; break; case KNF_MODAL_ANGLE_SNAP_TOGGLE: kcd->angle_snapping = !kcd->angle_snapping; knife_update_header(C, kcd); + do_refresh = TRUE; break; case KNF_MODAL_CUT_THROUGH_TOGGLE: kcd->cut_through = !kcd->cut_through; - knifetool_update_mval(kcd, event->mval); /* refresh knife path */ knife_update_header(C, kcd); + do_refresh = TRUE; break; case KNF_MODAL_NEW_CUT: ED_region_tag_redraw(kcd->ar); @@ -3203,6 +3230,12 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) } } + if (do_refresh) { + /* we don't really need to update mval, + * but this happens to be the best way to refresh at the moment */ + knifetool_update_mval(kcd, event->mval); + } + /* keep going until the user confirms */ return OPERATOR_RUNNING_MODAL; } diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 8e5c89adfca..dec45b7f326 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -261,7 +261,11 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) lasteed = eed; } - if (lasteed != startedge && BM_edge_share_face_count(lasteed, startedge)) { +#ifdef BMW_EDGERING_NGON + if (lasteed != startedge && BM_edge_share_face_check(lasteed, startedge)) { +#else + if (lasteed != startedge && BM_edge_share_quad_check(lasteed, startedge)) { +#endif v[1][0] = v[0][0]; v[1][1] = v[0][1]; @@ -307,7 +311,13 @@ static void ringsel_find_edge(RingSelOpData *lcd, int cuts) static void ringsel_finish(bContext *C, wmOperator *op) { RingSelOpData *lcd = op->customdata; - int cuts = RNA_int_get(op->ptr, "number_cuts"); + const int cuts = RNA_int_get(op->ptr, "number_cuts"); + const float smoothness = 0.292f * RNA_float_get(op->ptr, "smoothness"); +#ifdef BMW_EDGERING_NGON + const int use_only_quads = FALSE; +#else + const int use_only_quads = TRUE; +#endif if (lcd->eed) { BMEditMesh *em = lcd->em; @@ -319,9 +329,10 @@ static void ringsel_finish(bContext *C, wmOperator *op) * Note though that it will break edgeslide in this specific case. * See [#31939]. */ BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, - 0.0f, 0.0f, 0.0f, + smoothness, 0.0f, 0.0f, cuts, - SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, TRUE, 0); + SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, TRUE, + use_only_quads, 0); /* force edge slide to edge select mode in in face select mode */ if (em->selectmode & SCE_SELECT_FACE) { @@ -413,6 +424,7 @@ static int ringcut_cancel(bContext *C, wmOperator *op) static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) { + ScrArea *sa = CTX_wm_area(C); Object *obedit = CTX_data_edit_object(C); RingSelOpData *lcd; BMEdge *edge; @@ -438,13 +450,17 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) lcd->eed = edge; ringsel_find_edge(lcd, 1); } - ED_area_headerprint(CTX_wm_area(C), "Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts"); + ED_area_headerprint(sa, + "Select a ring to be cut, " + "use mouse-wheel or page-up/down for number of cuts, " + "Hold Alt for smooth"); return OPERATOR_RUNNING_MODAL; } static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) { + float smoothness = RNA_float_get(op->ptr, "smoothness"); int cuts = RNA_int_get(op->ptr, "number_cuts"); RingSelOpData *lcd = op->customdata; int show_cuts = 0; @@ -491,11 +507,17 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) case WHEELUPMOUSE: /* change number of cuts */ if (event->val == KM_RELEASE) break; - - cuts++; - RNA_int_set(op->ptr, "number_cuts", cuts); - ringsel_find_edge(lcd, cuts); - show_cuts = TRUE; + if (event->alt == 0) { + cuts++; + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = TRUE; + } + else { + smoothness = min_ff(smoothness + 0.05f, 4.0f); + RNA_float_set(op->ptr, "smoothness", smoothness); + show_cuts = TRUE; + } ED_region_tag_redraw(lcd->ar); break; @@ -505,10 +527,17 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) if (event->val == KM_RELEASE) break; - cuts = max_ii(cuts - 1, 0); - RNA_int_set(op->ptr, "number_cuts", cuts); - ringsel_find_edge(lcd, cuts); - show_cuts = TRUE; + if (event->alt == 0) { + cuts = max_ii(cuts - 1, 0); + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = TRUE; + } + else { + smoothness = max_ff(smoothness - 0.05f, 0.0f); + RNA_float_set(op->ptr, "smoothness", smoothness); + show_cuts = TRUE; + } ED_region_tag_redraw(lcd->ar); break; @@ -533,9 +562,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) /* using the keyboard to input the number of cuts */ if (event->val == KM_PRESS) { /* init as zero so backspace clears */ - float value = 0.0f; if (handleNumInput(&lcd->num, event)) { + float value = RNA_int_get(op->ptr, "number_cuts"); applyNumInput(&lcd->num, &value); /* allow zero so you can backspace and type in a value @@ -552,7 +581,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) if (show_cuts) { char buf[64]; - BLI_snprintf(buf, sizeof(buf), "Number of Cuts: %d", cuts); + BLI_snprintf(buf, sizeof(buf), "Number of Cuts: %d, Smooth: %.2f (Alt)", cuts, smoothness); ED_area_headerprint(CTX_wm_area(C), buf); } @@ -604,4 +633,7 @@ void MESH_OT_loopcut(wmOperatorType *ot) prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10); /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */ RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, FLT_MAX, "Smoothness", "Smoothness factor", 0.0f, 4.0f); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 6379bdbc0ca..2ecc20b2ddb 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -60,7 +60,7 @@ * * \param inset is used so we get some useful distance * when comparing multiple edges that meet at the same - * point and would result in teh same distance. + * point and would result in the same distance. */ #define INSET_DEFAULT 0.00001f static float edbm_rip_edgedist(ARegion *ar, float mat[][4], @@ -489,7 +489,7 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u } /* face should never exist */ - BLI_assert(BM_face_exists(bm, f_verts, f_verts[3] ? 4 : 3, &f) == FALSE); + BLI_assert(BM_face_exists(f_verts, f_verts[3] ? 4 : 3, &f) == FALSE); f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, FALSE); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 0379068afd9..3335f03ac17 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -56,6 +56,7 @@ #include "ED_mesh.h" #include "ED_screen.h" +#include "ED_util.h" #include "ED_uvedit.h" #include "ED_object.h" #include "ED_view3d.h" @@ -68,6 +69,7 @@ #include "mesh_intern.h" +#include "UI_resources.h" /* ****************************** MIRROR **************** */ @@ -448,20 +450,6 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const short sel, } } -/* returns labda for closest distance v1 to line-piece v2 - v3 */ -float labda_PdistVL2Dfl(const float v1[2], const float v2[2], const float v3[2]) -{ - float rc[2], len; - - rc[0] = v3[0] - v2[0]; - rc[1] = v3[1] - v2[1]; - len = rc[0] * rc[0] + rc[1] * rc[1]; - if (len == 0.0f) - return 0.0f; - - return (rc[0] * (v1[0] - v2[0]) + rc[1] * (v1[1] - v2[1])) / len; -} - /* note; uses v3d, so needs active 3d window */ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) { @@ -476,7 +464,7 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float if (distance < data->dist) { if (data->vc.rv3d->rflag & RV3D_CLIPPING) { - float labda = labda_PdistVL2Dfl(data->mval_fl, screen_co_a, screen_co_b); + float labda = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); float vec[3]; vec[0] = eed->v1->co[0] + labda * (eed->v2->co[0] - eed->v1->co[0]); @@ -730,7 +718,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -771,7 +759,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); EDBM_selectmode_flush(em); /* finish the operator */ @@ -815,7 +803,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -915,6 +903,74 @@ void MESH_OT_select_similar(wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.0, 1.0); } + +/* **************** Mode Select *************** */ + +static int edbm_select_mode_exec(bContext *C, wmOperator *op) +{ + const int type = RNA_enum_get(op->ptr, "type"); + const int action = RNA_enum_get(op->ptr, "action"); + const int use_extend = RNA_boolean_get(op->ptr, "use_extend"); + const int use_expand = RNA_boolean_get(op->ptr, "use_expand"); + + if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +static int edbm_select_mode_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + // RNA_enum_set(op->ptr, "type"); /* type must be set already */ + RNA_boolean_set(op->ptr, "use_extend", event->shift); + RNA_boolean_set(op->ptr, "use_expand", event->ctrl); + return edbm_select_mode_exec(C, op); +} + +void MESH_OT_select_mode(wmOperatorType *ot) +{ + PropertyRNA *prop; + + static EnumPropertyItem elem_items[] = { + {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""}, + {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edges", ""}, + {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Faces", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + static EnumPropertyItem actions_items[] = { + {0, "DISABLE", 0, "Disable", "Disable selected markers"}, + {1, "ENABLE", 0, "Enable", "Enable selected markers"}, + {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Select Mode"; + ot->idname = "MESH_OT_select_mode"; + ot->description = "Change selection mode"; + + /* api callbacks */ + ot->invoke = edbm_select_mode_invoke; + ot->exec = edbm_select_mode_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_boolean(ot->srna, "use_extend", FALSE, "Extend", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_expand", FALSE, "Expand", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute"); +} + /* ***************************************************** */ /* **************** LOOP SELECTS *************** */ @@ -1013,7 +1069,7 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot) /* ***************** loop select (non modal) ************** */ -static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) +static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short deselect, short toggle, short ring) { ViewContext vc; BMEditMesh *em; @@ -1032,14 +1088,20 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) eed = EDBM_edge_find_nearest(&vc, &dist); if (eed) { - if (extend == 0) { + if (extend == 0 && deselect == 0 && toggle == 0) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); } - if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) { + if (extend) { select = TRUE; } - else if (extend) { + else if (deselect) { + select = FALSE; + } + else if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) { + select = TRUE; + } + else if (toggle) { select = FALSE; } @@ -1132,6 +1194,8 @@ static int edbm_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) view3d_operator_needs_opengl(C); mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"), + RNA_boolean_get(op->ptr, "deselect"), + RNA_boolean_get(op->ptr, "toggle"), RNA_boolean_get(op->ptr, "ring")); /* cannot do tweaks for as long this keymap is after transform map */ @@ -1154,6 +1218,8 @@ void MESH_OT_loop_select(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection"); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring"); } @@ -1172,64 +1238,74 @@ void MESH_OT_edgering_select(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection"); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring"); } -/* ******************* edgetag_shortest_path and helpers ****************** */ +/* ******************* generic tag_shortest_path and helpers ****************** */ -static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BMVert *v) +static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3[3]) { - BMVert *v1 = (e1->v1 == v) ? e1->v2 : e1->v1; - BMVert *v2 = (e2->v1 == v) ? e2->v2 : e2->v1; float cost, d1[3], d2[3]; + /* The cost is based on the simple sum of the length of the two edgees... */ - sub_v3_v3v3(d1, v->co, v1->co); - sub_v3_v3v3(d2, v2->co, v->co); - cost = len_v3(d1); - cost += len_v3(d2); + sub_v3_v3v3(d1, v2, v1); + sub_v3_v3v3(d2, v3, v2); + cost = normalize_v3(d1) + normalize_v3(d2); /* but is biased to give higher values to sharp turns, so that it will take * paths with fewer "turns" when selecting between equal-weighted paths between * the two edges */ - cost = cost + 0.5f * cost * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2)))); + cost = cost * (1.0f + 0.5f * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2))))); return cost; } -static void edgetag_add_adjacent(BMEditMesh *em, SmallHash *visithash, Heap *heap, int mednum, int vertnum, - int *nedges, int *edges, int *prevedge, float *cost) +/* ******************* edgetag_shortest_path and helpers ****************** */ + +static float edgetag_cut_cost(BMEdge *e1, BMEdge *e2, BMVert *v) { - BMEdge *e1 = EDBM_edge_at_index(em, mednum); - BMVert *v = EDBM_vert_at_index(em, vertnum); - int startadj, endadj = nedges[vertnum + 1]; + BMVert *v1 = BM_edge_other_vert(e1, v); + BMVert *v2 = BM_edge_other_vert(e2, v); + return step_cost_3_v3(v1->co, v->co, v2->co); +} - for (startadj = nedges[vertnum]; startadj < endadj; startadj++) { - int adjnum = edges[startadj]; - BMEdge *e2 = EDBM_edge_at_index(em, adjnum); - float newcost; - float cutcost; +static void edgetag_add_adjacent(Heap *heap, BMEdge *e1, BMEdge **edges_prev, float *cost) +{ + BMIter viter; + BMVert *v; - if (BLI_smallhash_haskey(visithash, (uintptr_t)e2)) - continue; + BMIter eiter; + BMEdge *e2; - cutcost = edgetag_cut_cost(em, e1, e2, v); - newcost = cost[mednum] + cutcost; + const int e1_index = BM_elem_index_get(e1); - if (cost[adjnum] > newcost) { - cost[adjnum] = newcost; - prevedge[adjnum] = mednum; - BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum)); + BM_ITER_ELEM (v, &viter, e1, BM_VERTS_OF_EDGE) { + BM_ITER_ELEM (e2, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e2, BM_ELEM_TAG)) { + /* we know 'e2' is not visited, check it out! */ + const int e2_index = BM_elem_index_get(e2); + const float cost_cut = edgetag_cut_cost(e1, e2, v); + const float cost_new = cost[e1_index] + cost_cut; + + if (cost[e2_index] > cost_new) { + cost[e2_index] = cost_new; + edges_prev[e2_index] = e1; + BLI_heap_insert(heap, cost_new, e2); + } + } } } } -static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val) +static void edgetag_context_set(BMesh *bm, Scene *scene, BMEdge *e, int val) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - BM_edge_select_set(em->bm, e, val); + BM_edge_select_set(bm, e, val); break; case EDGE_MODE_TAG_SEAM: BM_elem_flag_set(e, BM_ELEM_SEAM, val); @@ -1238,98 +1314,66 @@ static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val BM_elem_flag_set(e, BM_ELEM_SMOOTH, !val); break; case EDGE_MODE_TAG_CREASE: - { - float *crease = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_CREASE); - *crease = (val) ? 1.0f : 0.0f; + BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (val) ? 1.0f : 0.0f); break; - } case EDGE_MODE_TAG_BEVEL: - { - float *bweight = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_BWEIGHT); - *bweight = (val) ? 1.0f : 0.0f; + BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f); break; - } } } -static int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *e) +static int edgetag_context_check(Scene *scene, BMesh *bm, BMEdge *e) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - return BM_elem_flag_test(e, BM_ELEM_SELECT) ? 1 : 0; + return BM_elem_flag_test(e, BM_ELEM_SELECT) ? TRUE : FALSE; case EDGE_MODE_TAG_SEAM: return BM_elem_flag_test(e, BM_ELEM_SEAM); case EDGE_MODE_TAG_SHARP: return !BM_elem_flag_test(e, BM_ELEM_SMOOTH); case EDGE_MODE_TAG_CREASE: - return BM_elem_float_data_get(&em->bm->edata, e, CD_CREASE) ? 1 : 0; + return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? TRUE : FALSE; case EDGE_MODE_TAG_BEVEL: - return BM_elem_float_data_get(&em->bm->edata, e, CD_BWEIGHT) ? 1 : 0; + return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? TRUE : FALSE; } return 0; } -static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, BMEdge *target) +static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge *e_dst) { + /* BM_ELEM_TAG flag is used to store visited edges */ BMEdge *e; - BMIter iter; + BMIter eiter; Heap *heap; - SmallHash visithash; float *cost; - int i, totvert = 0, totedge = 0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; - int targetnum; - - BLI_smallhash_init(&visithash); + BMEdge **edges_prev; + int i, totedge; /* note, would pass BM_EDGE except we are looping over all edges anyway */ - BM_mesh_elem_index_ensure(em->bm, BM_VERT /* | BM_EDGE */); + BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL); + BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE) { + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(e, BM_ELEM_TAG); } - BM_elem_index_set(e, totedge); /* set_inline */ - totedge++; + BM_elem_index_set(e, i); /* set_inline */ } - em->bm->elem_index_dirty &= ~BM_EDGE; + bm->elem_index_dirty &= ~BM_EDGE; /* alloc */ - totvert = em->bm->totvert; - nedges = MEM_callocN(sizeof(*nedges) * totvert + 1, "SeamPathNEdges"); - edges = MEM_mallocN(sizeof(*edges) * totedge * 2, "SeamPathEdges"); - prevedge = MEM_mallocN(sizeof(*prevedge) * totedge, "SeamPathPrevious"); + totedge = bm->totedge; + edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, "SeamPathPrevious"); cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost"); - /* count edges, compute adjacent edges offsets and fill adjacent */ - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - nedges[BM_elem_index_get(e->v1) + 1]++; - nedges[BM_elem_index_get(e->v2) + 1]++; - } - - for (i = 1; i < totvert; i++) { - int newswap = nedges[i + 1]; - nedges[i + 1] = nedgeswap + nedges[i]; - nedgeswap = newswap; - } - nedges[0] = nedges[1] = 0; - - i = 0; - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - edges[nedges[BM_elem_index_get(e->v1) + 1]++] = i; - edges[nedges[BM_elem_index_get(e->v2) + 1]++] = i; - - cost[i] = 1e20f; - prevedge[i] = -1; - i++; - } + fill_vn_fl(cost, totedge, 1e20f); /* * Arrays are now filled as follows: * - * nedges[n] = sum of the # of edges incident to all vertices numbered 0 through n - 1 - * edges[edges[n]..edges[n - 1]] = the indices of of the edges incident to vertex n - * * As the search continues, prevedge[n] will be the previous edge on the shortest * path found so far to edge n. The visitedhash will of course contain entries * for edges that have been visited, cost[n] will contain the length of the shortest @@ -1340,61 +1384,46 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, B /* regular dijkstra shortest path, but over edges instead of vertices */ heap = BLI_heap_new(); - BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(BM_elem_index_get(source))); - cost[BM_elem_index_get(source)] = 0.0f; - EDBM_index_arrays_init(em, 1, 1, 0); - targetnum = BM_elem_index_get(target); + BLI_heap_insert(heap, 0.0f, e_src); + cost[BM_elem_index_get(e_src)] = 0.0f; + + e = NULL; while (!BLI_heap_is_empty(heap)) { - mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); - e = EDBM_edge_at_index(em, mednum); + e = BLI_heap_popmin(heap); - if (mednum == targetnum) + if (e == e_dst) break; - if (BLI_smallhash_haskey(&visithash, (uintptr_t)e)) - continue; - - BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL); - - edgetag_add_adjacent(em, &visithash, heap, mednum, BM_elem_index_get(e->v1), nedges, edges, prevedge, cost); - edgetag_add_adjacent(em, &visithash, heap, mednum, BM_elem_index_get(e->v2), nedges, edges, prevedge, cost); + if (!BM_elem_flag_test(e, BM_ELEM_TAG)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + edgetag_add_adjacent(heap, e, edges_prev, cost); + } } - if (mednum == targetnum) { - short allseams = 1; + if (e == e_dst) { + short all_set = TRUE; /* Check whether the path is already completely tagged. * if it is, the tags will be cleared instead of set. */ - mednum = targetnum; + e = e_dst; do { - e = EDBM_edge_at_index(em, mednum); - if (!edgetag_context_check(scene, em, e)) { - allseams = 0; + if (!edgetag_context_check(scene, bm, e)) { + all_set = FALSE; break; } - mednum = prevedge[mednum]; - } while (mednum != BM_elem_index_get(source)); + } while ((e = edges_prev[BM_elem_index_get(e)])); /* Follow path back and source and add or remove tags */ - mednum = targetnum; + e = e_dst; do { - e = EDBM_edge_at_index(em, mednum); - if (allseams) - edgetag_context_set(em, scene, e, 0); - else - edgetag_context_set(em, scene, e, 1); - mednum = prevedge[mednum]; - } while (mednum != -1); + edgetag_context_set(bm, scene, e, !all_set); + } while ((e = edges_prev[BM_elem_index_get(e)])); } - EDBM_index_arrays_free(em); - MEM_freeN(nedges); - MEM_freeN(edges); - MEM_freeN(prevedge); + MEM_freeN(edges_prev); MEM_freeN(cost); BLI_heap_free(heap, NULL); - BLI_smallhash_release(&visithash); return 1; } @@ -1402,21 +1431,15 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, B /* ******************* mesh shortest path select, uses prev-selected edge ****************** */ /* since you want to create paths with multiple selects, it doesn't have extend option */ -static int mouse_mesh_shortest_path(bContext *C, int mval[2]) +static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) { - ViewContext vc; - BMEditMesh *em; - BMEdge *e; + BMEditMesh *em = vc->em; + BMEdge *e_dst; float dist = 75.0f; - em_setup_viewcontext(C, &vc); - vc.mval[0] = mval[0]; - vc.mval[1] = mval[1]; - em = vc.em; - - e = EDBM_edge_find_nearest(&vc, &dist); - if (e) { - Mesh *me = vc.obedit->data; + e_dst = EDBM_edge_find_nearest(vc, &dist); + if (e_dst) { + Mesh *me = vc->obedit->data; int path = 0; if (em->bm->selected.last) { @@ -1425,8 +1448,8 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) if (ese && ese->htype == BM_EDGE) { BMEdge *e_act; e_act = (BMEdge *)ese->ele; - if (e_act != e) { - if (edgetag_shortest_path(vc.scene, em, e_act, e)) { + if (e_act != e_dst) { + if (edgetag_shortest_path(vc->scene, em->bm, e_act, e_dst)) { BM_select_history_remove(em->bm, e_act); path = 1; } @@ -1434,24 +1457,24 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) } } if (path == 0) { - int act = (edgetag_context_check(vc.scene, em, e) == 0); - edgetag_context_set(em, vc.scene, e, act); /* switch the edge option */ + int act = (edgetag_context_check(vc->scene, em->bm, e_dst) == 0); + edgetag_context_set(em->bm, vc->scene, e_dst, act); /* switch the edge option */ } EDBM_selectmode_flush(em); /* even if this is selected it may not be in the selection list */ - if (edgetag_context_check(vc.scene, em, e) == 0) - BM_select_history_remove(em->bm, e); + if (edgetag_context_check(vc->scene, em->bm, e_dst) == 0) + BM_select_history_remove(em->bm, e_dst); else - BM_select_history_store(em->bm, e); + BM_select_history_store(em->bm, e_dst); /* force drawmode for mesh */ switch (CTX_data_tool_settings(C)->edge_mode) { case EDGE_MODE_TAG_SEAM: me->drawflag |= ME_DRAWSEAMS; - ED_uvedit_live_unwrap(vc.scene, vc.obedit); + ED_uvedit_live_unwrap(vc->scene, vc->obedit); break; case EDGE_MODE_TAG_SHARP: me->drawflag |= ME_DRAWSHARP; @@ -1474,25 +1497,237 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) } -static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) -{ - - view3d_operator_needs_opengl(C); +/* ******************* facetag_shortest_path and helpers ****************** */ - if (mouse_mesh_shortest_path(C, event->mval)) { - return OPERATOR_FINISHED; + +static float facetag_cut_cost(BMFace *f1, BMFace *f2, BMEdge *e) +{ + float f1_cent[3]; + float f2_cent[3]; + float e_cent[3]; + + BM_face_calc_center_mean(f1, f1_cent); + BM_face_calc_center_mean(f2, f2_cent); + mid_v3_v3v3(e_cent, e->v1->co, e->v2->co); + + return step_cost_3_v3(f1_cent, e_cent, f2_cent); +} + +static void facetag_add_adjacent(Heap *heap, BMFace *f1, BMFace **faces_prev, float *cost) +{ + BMIter liter; + BMLoop *l2; + BMFace *f2; + + const int f1_index = BM_elem_index_get(f1); + + /* loop over faces of face, but do so by first looping over loops */ + BM_ITER_ELEM (l2, &liter, f1, BM_LOOPS_OF_FACE) { + BMLoop *l_first; + BMLoop *l_iter; + + l_iter = l_first = l2; + do { + f2 = l_iter->f; + if (!BM_elem_flag_test(f2, BM_ELEM_TAG)) { + /* we know 'f2' is not visited, check it out! */ + const int f2_index = BM_elem_index_get(f2); + const float cost_cut = facetag_cut_cost(f1, f2, l_iter->e); + const float cost_new = cost[f1_index] + cost_cut; + + if (cost[f2_index] > cost_new) { + cost[f2_index] = cost_new; + faces_prev[f2_index] = f1; + BLI_heap_insert(heap, cost_new, f2); + } + } + } while ((l_iter = l_iter->radial_next) != l_first); + } +} + +static void facetag_context_set(BMesh *bm, Scene *UNUSED(scene), BMFace *f, int val) +{ + BM_face_select_set(bm, f, val); +} + +static int facetag_context_check(Scene *UNUSED(scene), BMesh *UNUSED(bm), BMFace *f) +{ + return BM_elem_flag_test(f, BM_ELEM_SELECT) ? 1 : 0; +} + +static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace *f_dst) +{ + /* BM_ELEM_TAG flag is used to store visited edges */ + BMFace *f; + BMIter fiter; + Heap *heap; + float *cost; + BMFace **faces_prev; + int i, totface; + + /* note, would pass BM_EDGE except we are looping over all faces anyway */ + // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG + + BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { + if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == FALSE) { + BM_elem_flag_disable(f, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + + BM_elem_index_set(f, i); /* set_inline */ + } + bm->elem_index_dirty &= ~BM_FACE; + + /* alloc */ + totface = bm->totface; + faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, "SeamPathPrevious"); + cost = MEM_mallocN(sizeof(*cost) * totface, "SeamPathCost"); + + fill_vn_fl(cost, totface, 1e20f); + + /* + * Arrays are now filled as follows: + * + * As the search continues, faces_prev[n] will be the previous face on the shortest + * path found so far to face n. The visitedhash will of course contain entries + * for faces that have been visited, cost[n] will contain the length of the shortest + * path to face n found so far, Finally, heap is a priority heap which is built on the + * the same data as the cost array, but inverted: it is a worklist of faces prioritized + * by the shortest path found so far to the face. + */ + + /* regular dijkstra shortest path, but over faces instead of vertices */ + heap = BLI_heap_new(); + BLI_heap_insert(heap, 0.0f, f_src); + cost[BM_elem_index_get(f_src)] = 0.0f; + + f = NULL; + + while (!BLI_heap_is_empty(heap)) { + f = BLI_heap_popmin(heap); + + if (f == f_dst) + break; + + if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + facetag_add_adjacent(heap, f, faces_prev, cost); + } + } + + if (f == f_dst) { + short all_set = TRUE; + + /* Check whether the path is already completely tagged. + * if it is, the tags will be cleared instead of set. */ + f = f_dst; + do { + if (!facetag_context_check(scene, bm, f)) { + all_set = FALSE; + break; + } + } while ((f = faces_prev[BM_elem_index_get(f)])); + + /* Follow path back and source and add or remove tags */ + f = f_dst; + do { + facetag_context_set(bm, scene, f, !all_set); + } while ((f = faces_prev[BM_elem_index_get(f)])); + } + + MEM_freeN(faces_prev); + MEM_freeN(cost); + BLI_heap_free(heap, NULL); + + return 1; +} + +static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc) +{ + BMEditMesh *em = vc->em; + BMFace *f_dst; + float dist = 75.0f; + + f_dst = EDBM_face_find_nearest(vc, &dist); + if (f_dst) { + int path = 0; + BMFace *f_act = BM_active_face_get(em->bm, FALSE, TRUE); + + if (f_act) { + if (f_act != f_dst) { + if (facetag_shortest_path(vc->scene, em->bm, f_act, f_dst)) { + BM_select_history_remove(em->bm, f_act); + path = 1; + } + } + } + if (path == 0) { + int act = (facetag_context_check(vc->scene, em->bm, f_dst) == 0); + facetag_context_set(em->bm, vc->scene, f_dst, act); /* switch the face option */ + } + + EDBM_selectmode_flush(em); + + /* even if this is selected it may not be in the selection list */ + if (facetag_context_check(vc->scene, em->bm, f_dst) == 0) + BM_select_history_remove(em->bm, f_dst); + else + BM_select_history_store(em->bm, f_dst); + + BM_active_face_set(em->bm, f_dst); + + EDBM_update_generic(C, em, FALSE); + + return TRUE; } else { - return OPERATOR_PASS_THROUGH; + return FALSE; } } + +/* ******************* operator for edge and face tag ****************** */ + +static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +{ + ViewContext vc; + BMEditMesh *em; + + view3d_operator_needs_opengl(C); + + em_setup_viewcontext(C, &vc); + vc.mval[0] = event->mval[0]; + vc.mval[1] = event->mval[1]; + em = vc.em; + + if (em->selectmode & SCE_SELECT_EDGE) { + if (mouse_mesh_shortest_path_edge(C, &vc)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_PASS_THROUGH; + } + } + else if (em->selectmode & SCE_SELECT_FACE) { + if (mouse_mesh_shortest_path_face(C, &vc)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_PASS_THROUGH; + } + } + + return OPERATOR_PASS_THROUGH; +} + static int edbm_shortest_path_select_poll(bContext *C) { if (ED_operator_editmesh_region_view3d(C)) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); - return (em->selectmode & SCE_SELECT_EDGE) != 0; + return (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE)) != 0; } return 0; } @@ -1622,7 +1857,7 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec vc.obedit->actcol = efa->mat_nr + 1; vc.em->mat_nr = efa->mat_nr; - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, NULL); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); } @@ -1714,56 +1949,146 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s BMFace *efa; BMIter iter; + /* first tag-to-select, then select --- this avoids a feedback loop */ + /* have to find out what the selectionmode was previously */ if (selectmode_old == SCE_SELECT_VERTEX) { if (selectmode_new == SCE_SELECT_EDGE) { - /* select all edges associated with every selected vertex */ - eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL); - for (; eed; eed = BM_iter_step(&iter)) { - if ((BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || - BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) - { + /* select all edges associated with every selected vert */ + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT)); + } + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(eed, BM_ELEM_TAG)) { BM_edge_select_set(em->bm, eed, TRUE); } } } else if (selectmode_new == SCE_SELECT_FACE) { - BMIter liter; - BMLoop *l; + /* select all faces associated with every selected vert */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT)); + } - /* select all faces associated with every selected vertex */ - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&liter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); - break; - } + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_face_select_set(em->bm, efa, TRUE); } } } } else if (selectmode_old == SCE_SELECT_EDGE) { if (selectmode_new == SCE_SELECT_FACE) { - BMIter liter; - BMLoop *l; + /* select all faces associated with every selected edge */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT)); + } - /* select all faces associated with every selected vertex */ - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&liter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); - break; - } + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_face_select_set(em->bm, efa, TRUE); } } } } } +/* user facing function, does notification and undo push */ +int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, + const int action, const int use_extend, const int use_expand) +{ + ToolSettings *ts = CTX_data_tool_settings(C); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = NULL; + int ret = FALSE; + + if (obedit && obedit->type == OB_MESH) { + em = BMEdit_FromObject(obedit); + } + + if (em == NULL) { + return ret; + } + + switch (action) { + case -1: + /* already set */ + break; + case 0: /* disable */ + /* check we have something to do */ + if ((em->selectmode & selectmode_new) == 0) { + return FALSE; + } + em->selectmode &= ~selectmode_new; + break; + case 1: /* enable */ + /* check we have something to do */ + if ((em->selectmode & selectmode_new) != 0) { + return FALSE; + } + em->selectmode |= selectmode_new; + break; + case 2: /* toggle */ + /* can't disable this flag if its the only one set */ + if (em->selectmode == selectmode_new) { + return FALSE; + } + em->selectmode ^= selectmode_new; + break; + default: + BLI_assert(0); + } + + switch (selectmode_new) { + case SCE_SELECT_VERTEX: + if (use_extend == 0 || em->selectmode == 0) + em->selectmode = SCE_SELECT_VERTEX; + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + case SCE_SELECT_EDGE: + if (use_extend == 0 || em->selectmode == 0) { + if (use_expand) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (selmode_max == SCE_SELECT_VERTEX) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_EDGE); + } + } + em->selectmode = SCE_SELECT_EDGE; + } + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + case SCE_SELECT_FACE: + if (use_extend == 0 || em->selectmode == 0) { + if (use_expand) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (ELEM(selmode_max, SCE_SELECT_VERTEX, SCE_SELECT_EDGE)) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_FACE); + } + } + + em->selectmode = SCE_SELECT_FACE; + } + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + default: + BLI_assert(0); + break; + } + + if (ret == TRUE) { + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); + } + + return ret; +} void EDBM_deselect_by_material(BMEditMesh *em, const short index, const short select) { @@ -1911,6 +2236,8 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * return OPERATOR_CANCELLED; if (limit) { + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); /* hflag no-seam --> bmo-tag */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* BMESH_TODO, don't use 'BM_ELEM_SELECT' here, its a HFLAG only! */ @@ -2003,6 +2330,8 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } if (limit) { + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* BMESH_TODO, don't use 'BM_ELEM_SELECT' here, its a HFLAG only! */ BMO_elem_flag_set(bm, e, BM_ELEM_SELECT, !BM_elem_flag_test(e, BM_ELEM_SEAM)); @@ -2023,6 +2352,10 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } } BMW_end(&walker); + + if (limit) { + BM_mesh_elem_toolflags_clear(bm); + } } else { BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -2168,6 +2501,9 @@ static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h break; } + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); + /* Walker restrictions uses BMO flags, not header flags, * so transfer BM_ELEM_SELECT from HFlags onto a BMO flag layer. */ BMO_push(bm, NULL); diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c index d370b5a881e..4fbe9c2534f 100644 --- a/source/blender/editors/mesh/editmesh_slide.c +++ b/source/blender/editors/mesh/editmesh_slide.c @@ -695,7 +695,7 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u BMOperator bmop; BMEditSelection *ese = (BMEditSelection *)em->bm->selected.last; - float distance_t = 0.0f; + float factor = 0.0f; /* Invoked modally? */ if (op->type->modal == edbm_vertex_slide_modal && op->customdata) { @@ -711,12 +711,12 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u BM_select_history_store(em->bm, vso->start_vtx); ese = (BMEditSelection *)em->bm->selected.last; } - distance_t = vso->distance; - RNA_float_set(op->ptr, "distance_t", distance_t); + factor = vso->distance; + RNA_float_set(op->ptr, "factor", factor); } else { /* Get Properties */ - distance_t = RNA_float_get(op->ptr, "distance_t"); + factor = RNA_float_get(op->ptr, "factor"); } /* Is there a starting vertex ? */ @@ -729,8 +729,8 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u /* Prepare operator */ if (!EDBM_op_init(em, &bmop, op, - "slide_vert vert=%e edge=%hev distance_t=%f", - start_vert, BM_ELEM_SELECT, distance_t)) + "slide_vert vert=%e edges=%he factor=%f", + start_vert, BM_ELEM_SELECT, factor)) { return OPERATOR_CANCELLED; } @@ -738,10 +738,10 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u BMO_op_exec(bm, &bmop); /* Deselect the input edges */ - BMO_slot_buffer_hflag_disable(bm, &bmop, "edge", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); /* Select the output vert */ - BMO_slot_buffer_hflag_enable(bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); /* Flush the select buffers */ EDBM_selectmode_flush(em); @@ -787,7 +787,7 @@ void MESH_OT_vert_slide(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* Properties for vertex slide */ - prop = RNA_def_float(ot->srna, "distance_t", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "Distance", -5.0f, 5.0f); + prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "Distance", -5.0f, 5.0f); RNA_def_property_ui_range(prop, -5.0f, 5.0f, 0.1, 4); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index f10faddc169..ad1077156ba 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -72,6 +72,7 @@ #include "RE_render_ext.h" #include "UI_interface.h" +#include "UI_resources.h" #include "mesh_intern.h" @@ -108,7 +109,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) smooth, fractal, along_normal, cuts, SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), - RNA_boolean_get(op->ptr, "quadtri"), TRUE, + RNA_boolean_get(op->ptr, "quadtri"), TRUE, FALSE, RNA_int_get(op->ptr, "seed")); EDBM_update_generic(C, em, TRUE); @@ -242,7 +243,7 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c BMO_op_exec(em->bm, &bmop); - BMO_ITER (f, &siter, em->bm, &bmop, "faceout", BM_FACE) { + BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) { BM_face_select_set(em->bm, f, TRUE); /* set face vertex normals to face normal */ @@ -269,7 +270,7 @@ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char EDBM_flag_disable_all(em, BM_ELEM_SELECT); BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_VERT | BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return 0; @@ -286,10 +287,10 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char EDBM_op_init(em, &bmop, op, "extrude_vert_indiv verts=%hv", hflag); /* deselect original verts */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "verts", BM_VERT, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, TRUE); BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_VERT, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return 0; @@ -308,9 +309,12 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, BMFace *f; ModifierData *md; BMElem *ele; + BMOpSlot *slot_edges_exclude; BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region"); - BMO_slot_buffer_from_enabled_hflag(bm, &extop, "edgefacein", BM_VERT | BM_EDGE | BM_FACE, hflag); + BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE, hflag); + + slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude"); /* If a mirror modifier with clipping is on, we need to adjust some * of the cases above to handle edges on the line of symmetry. @@ -350,21 +354,21 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, if ((fabsf(co1[0]) < mmd->tolerance) && (fabsf(co2[0]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); } } if (mmd->flag & MOD_MIR_AXIS_Y) { if ((fabsf(co1[1]) < mmd->tolerance) && (fabsf(co2[1]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); } } if (mmd->flag & MOD_MIR_AXIS_Z) { if ((fabsf(co1[2]) < mmd->tolerance) && (fabsf(co2[2]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); } } } @@ -379,7 +383,7 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, zero_v3(nor); - BMO_ITER (ele, &siter, bm, &extop, "geomout", BM_ALL) { + BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL) { BM_elem_select_set(bm, ele, TRUE); if (ele->head.htype == BM_FACE) { @@ -449,7 +453,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) for (a = 0; a < steps; a++) { edbm_extrude_edge(obedit, em, BM_ELEM_SELECT, nor); - //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region edgefacein=%hef", BM_ELEM_SELECT); + //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region geom=%hef", BM_ELEM_SELECT); BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", (float *)dvec, BM_ELEM_SELECT); @@ -887,7 +891,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent } if (rot_src) { - EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3", + EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, cent, mat); /* also project the source, for retopo workflow */ @@ -896,7 +900,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent } edbm_extrude_edge(vc.obedit, vc.em, BM_ELEM_SELECT, nor); - EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3", + EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, cent, mat); EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, min); @@ -915,7 +919,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent EDBM_op_init(vc.em, &bmop, op, "create_vert co=%v", min); BMO_op_exec(vc.em->bm, &bmop); - BMO_ITER (v1, &oiter, vc.em->bm, &bmop, "newvertout", BM_VERT) { + BMO_ITER (v1, &oiter, bmop.slots_out, "vert.out", BM_VERT) { BM_vert_select_set(vc.em->bm, v1, TRUE); } @@ -1110,8 +1114,8 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) } BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -1261,7 +1265,7 @@ static int edbm_vert_connect(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } BMO_op_exec(bm, &bmop); - len = BMO_slot_get(&bmop, "edgeout")->len; + len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -1301,7 +1305,7 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } BMO_op_exec(bm, &bmop); - len = BMO_slot_get(&bmop, "edgeout")->len; + len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -1339,7 +1343,7 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "newout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -1405,8 +1409,8 @@ void MESH_OT_flip_normals(wmOperatorType *ot) } static const EnumPropertyItem direction_items[] = { - {DIRECTION_CW, "CW", 0, "Clockwise", ""}, - {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""}, + {FALSE, "CW", 0, "Clockwise", ""}, + {TRUE, "CCW", 0, "Counter Clockwise", ""}, {0, NULL, 0, NULL, NULL} }; @@ -1418,7 +1422,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BMOperator bmop; BMEdge *eed; BMIter iter; - const int do_ccw = RNA_enum_get(op->ptr, "direction") == 1; + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); int tot = 0; if (em->bm->totedgesel == 0) { @@ -1448,17 +1452,17 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Could not find any selected edges that can be rotated"); return OPERATOR_CANCELLED; } - - EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he ccw=%b", BM_ELEM_TAG, do_ccw); + + EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he use_ccw=%b", BM_ELEM_TAG, use_ccw); /* avoids leaving old verts selected which can be a problem running multiple times, * since this means the edges become selected around the face which then attempt to rotate */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); BMO_op_exec(em->bm, &bmop); /* edges may rotate into hidden vertices, if this does _not_ run we get an ilogical state */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_HIDDEN, TRUE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); EDBM_selectmode_flush(em); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -1485,7 +1489,7 @@ void MESH_OT_edge_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } @@ -1553,7 +1557,7 @@ static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op) /* doflip has to do with bmesh_rationalize_normals, it's an internal * thing */ - if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf do_flip=%b", BM_ELEM_SELECT, TRUE)) + if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf use_flip=%b", BM_ELEM_SELECT, TRUE)) return OPERATOR_CANCELLED; if (RNA_boolean_get(op->ptr, "inside")) @@ -1590,7 +1594,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) ModifierData *md; int mirrx = FALSE, mirry = FALSE, mirrz = FALSE; int i, repeat; - float clipdist = 0.0f; + float clip_dist = 0.0f; int xaxis = RNA_boolean_get(op->ptr, "xaxis"); int yaxis = RNA_boolean_get(op->ptr, "yaxis"); @@ -1616,7 +1620,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) if (mmd->flag & MOD_MIR_AXIS_Z) mirrz = TRUE; - clipdist = mmd->tolerance; + clip_dist = mmd->tolerance; } } } @@ -1627,9 +1631,9 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) for (i = 0; i < repeat; i++) { if (!EDBM_op_callf(em, op, - "smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clipdist=%f " + "smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clip_dist=%f " "use_axis_x=%b use_axis_y=%b use_axis_z=%b", - BM_ELEM_SELECT, mirrx, mirry, mirrz, clipdist, xaxis, yaxis, zaxis)) + BM_ELEM_SELECT, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis)) { return OPERATOR_CANCELLED; } @@ -1670,7 +1674,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); - int usex = TRUE, usey = TRUE, usez = TRUE, volume_preservation = TRUE; + int usex = TRUE, usey = TRUE, usez = TRUE, preserve_volume = TRUE; int i, repeat; float lambda; float lambda_border; @@ -1698,14 +1702,14 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) usex = RNA_boolean_get(op->ptr, "use_x"); usey = RNA_boolean_get(op->ptr, "use_y"); usez = RNA_boolean_get(op->ptr, "use_z"); - volume_preservation = RNA_boolean_get(op->ptr, "volume_preservation"); + preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume"); if (!repeat) repeat = 1; for (i = 0; i < repeat; i++) { if (!EDBM_op_callf(em, op, - "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b volume_preservation=%b", - BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, volume_preservation)) + "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b", + BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, preserve_volume)) { return OPERATOR_CANCELLED; } @@ -1736,16 +1740,16 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "repeat", 1, 1, 200, - "Number of iterations to smooth the mesh", "", 1, 200); - RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f, - "Lambda factor", "", 0.0000001f, 1000.0f); - RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f, - "Lambda factor in border", "", 0.0000001f, 1000.0f); + RNA_def_int(ot->srna, "repeat", 1, 1, 200, + "Number of iterations to smooth the mesh", "", 1, 200); + RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f, + "Lambda factor", "", 0.0000001f, 1000.0f); + RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f, + "Lambda factor in border", "", 0.0000001f, 1000.0f); RNA_def_boolean(ot->srna, "use_x", 1, "Smooth X Axis", "Smooth object along X axis"); RNA_def_boolean(ot->srna, "use_y", 1, "Smooth Y Axis", "Smooth object along Y axis"); RNA_def_boolean(ot->srna, "use_z", 1, "Smooth Z Axis", "Smooth object along Z axis"); - RNA_def_boolean(ot->srna, "volume_preservation", 1, "Preserve Volume", "Apply volume preservation after smooth"); + RNA_def_boolean(ot->srna, "preserve_volume", 1, "Preserve Volume", "Apply volume preservation after smooth"); } /********************** Smooth/Solid Operators *************************/ @@ -1828,10 +1832,10 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the direction from RNA */ - int dir = RNA_enum_get(op->ptr, "direction"); + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf dir=%i", BM_ELEM_SELECT, dir); + EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -1877,10 +1881,10 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the direction from RNA */ - int dir = RNA_enum_get(op->ptr, "direction"); + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf dir=%i", BM_ELEM_SELECT, dir); + EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -1936,7 +1940,7 @@ void MESH_OT_uvs_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } //void MESH_OT_uvs_mirror(wmOperatorType *ot) @@ -1973,7 +1977,7 @@ void MESH_OT_colors_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CCW, "Direction", "Direction to rotate edge around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } void MESH_OT_colors_reverse(wmOperatorType *ot) @@ -2014,7 +2018,7 @@ static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *w return OPERATOR_CANCELLED; if (uvmerge) { - if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv snapv=%e", BM_ELEM_SELECT, mergevert)) + if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert)) return OPERATOR_CANCELLED; } @@ -2174,7 +2178,7 @@ void MESH_OT_merge(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use"); RNA_def_enum_funcs(ot->prop, merge_type_itemf); - RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Move UVs according to merge"); + RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge"); } @@ -2183,7 +2187,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); BMOperator bmop; - const float mergedist = RNA_float_get(op->ptr, "mergedist"); + const float threshold = RNA_float_get(op->ptr, "threshold"); int use_unselected = RNA_boolean_get(op->ptr, "use_unselected"); int totvert_orig = em->bm->totvert; int count; @@ -2191,7 +2195,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) if (use_unselected) { EDBM_op_init(em, &bmop, op, "automerge verts=%hv dist=%f", - BM_ELEM_SELECT, mergedist); + BM_ELEM_SELECT, threshold); BMO_op_exec(em->bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -2201,10 +2205,10 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) else { EDBM_op_init(em, &bmop, op, "find_doubles verts=%hv dist=%f", - BM_ELEM_SELECT, mergedist); + BM_ELEM_SELECT, threshold); BMO_op_exec(em->bm, &bmop); - if (!EDBM_op_callf(em, op, "weld_verts targetmap=%s", &bmop, "targetmapout")) { + if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) { BMO_op_finish(em->bm, &bmop); return OPERATOR_CANCELLED; } @@ -2236,8 +2240,7 @@ void MESH_OT_remove_doubles(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_float(ot->srna, "mergedist", 0.0001f, 0.000001f, 50.0f, - "Merge Distance", + RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Merge Distance", "Minimum distance between elements to merge", 0.00001, 10.0); RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices"); } @@ -2305,7 +2308,9 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) } /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "shortest_path startv=%e endv=%e type=%i", svert, evert, type); + EDBM_op_init(em, &bmop, op, + "shortest_path vert_start=%e vert_end=%e type=%i", + svert, evert, type); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -2314,7 +2319,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -2439,7 +2444,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY); if (totshape == 0 || shape < 0 || shape >= totshape) return OPERATOR_CANCELLED; - + /* get shape key - needed for finding reference shape (for add mode only) */ if (key) { kb = BLI_findlink(&key->block, shape); @@ -2506,6 +2511,22 @@ static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), Prop return item; } +static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + PointerRNA ptr; + Object *obedit = CTX_data_edit_object(C); + Mesh *me = obedit->data; + PointerRNA ptr_key; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + RNA_id_pointer_create((ID *)me->key, &ptr_key); + + uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA); + uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE); +} + void MESH_OT_blend_from_shape(wmOperatorType *ot) { PropertyRNA *prop; @@ -2518,7 +2539,8 @@ void MESH_OT_blend_from_shape(wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_blend_from_shape_exec; - ot->invoke = WM_operator_props_popup; +// ot->invoke = WM_operator_props_popup_call; /* disable because search popup closes too easily */ + ot->ui = edbm_blend_from_shape_ui; ot->poll = ED_operator_editmesh; /* flags */ @@ -2631,13 +2653,13 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op) /* deselect only the faces in the region to be solidified (leave wire * edges and loose verts selected, as there will be no corresponding * geometry selected below) */ - BMO_slot_buffer_hflag_disable(bm, &bmop, "geom", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, TRUE); /* run the solidify operator */ BMO_op_exec(bm, &bmop); /* select the newly generated faces */ - BMO_slot_buffer_hflag_enable(bm, &bmop, "geomout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -2869,6 +2891,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) float isect = 0.0f; int len = 0, isected, i; short numcuts = 1, mode = RNA_int_get(op->ptr, "type"); + BMOpSlot *slot_edge_percents; /* allocd vars */ float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2]; @@ -2923,6 +2946,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) } /* store percentage of edge cut for KNIFE_EXACT here.*/ + slot_edge_percents = BMO_slot_get(bmop.slots_in, "edge_percents"); for (be = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be = BM_iter_step(&iter)) { int is_cut = FALSE; if (BM_elem_flag_test(be, BM_ELEM_SELECT)) { @@ -2935,9 +2959,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) if (isect != 0.0f) { if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) { - BMO_slot_map_float_insert(bm, &bmop, - "edgepercents", - be, isect); + BMO_slot_map_float_insert(&bmop, slot_edge_percents, be, isect); } } } @@ -2952,16 +2974,16 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) MEM_freeN(mouse_path); - BMO_slot_buffer_from_enabled_flag(bm, &bmop, "edges", BM_EDGE, ELE_EDGE_CUT); + BMO_slot_buffer_from_enabled_flag(bm, &bmop, bmop.slots_in, "edges", BM_EDGE, ELE_EDGE_CUT); if (mode == KNIFE_MIDPOINT) numcuts = 1; - BMO_slot_int_set(&bmop, "numcuts", numcuts); + BMO_slot_int_set(bmop.slots_in, "cuts", numcuts); - BMO_slot_int_set(&bmop, "quadcornertype", SUBD_STRAIGHT_CUT); - BMO_slot_bool_set(&bmop, "use_singleedge", FALSE); - BMO_slot_bool_set(&bmop, "use_gridfill", FALSE); + BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_STRAIGHT_CUT); + BMO_slot_bool_set(bmop.slots_in, "use_single_edge", FALSE); + BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", FALSE); - BMO_slot_float_set(&bmop, "radius", 0); + BMO_slot_float_set(bmop.slots_in, "radius", 0); BMO_op_exec(bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -3007,6 +3029,8 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh BMesh *bm_new; bm_new = BM_mesh_create(&bm_mesh_allocsize_default); + BM_mesh_elem_toolflags_ensure(bm_new); /* needed for 'duplicate' bmo */ + CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH, CD_CALLOC, 0); @@ -3302,7 +3326,7 @@ static int edbm_fill_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); /* select new geometry */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_FACE | BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -3574,7 +3598,7 @@ static int edbm_split_exec(bContext *C, wmOperator *op) EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, FALSE); BMO_op_exec(em->bm, &bmop); BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -3612,14 +3636,14 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) float cent[3], axis[3], imat[3][3]; float d[3] = {0.0f, 0.0f, 0.0f}; int steps, dupli; - float degr; + float angle; RNA_float_get_array(op->ptr, "center", cent); RNA_float_get_array(op->ptr, "axis", axis); steps = RNA_int_get(op->ptr, "steps"); - degr = RNA_float_get(op->ptr, "degrees"); + angle = RNA_float_get(op->ptr, "angle"); //if (ts->editbutflag & B_CLOCKWISE) - degr = -degr; + angle = -angle; dupli = RNA_boolean_get(op->ptr, "dupli"); /* undo object transformation */ @@ -3629,14 +3653,14 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) mul_m3_v3(imat, axis); if (!EDBM_op_init(em, &spinop, op, - "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i ang=%f do_dupli=%b", - BM_ELEM_SELECT, cent, axis, d, steps, degr, dupli)) + "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b", + BM_ELEM_SELECT, cent, axis, d, steps, angle, dupli)) { return OPERATOR_CANCELLED; } BMO_op_exec(bm, &spinop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(bm, &spinop, "lastout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &spinop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -3661,6 +3685,8 @@ static int edbm_spin_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) void MESH_OT_spin(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Spin"; ot->description = "Extrude selected vertices in a circle around the cursor in indicated viewport"; @@ -3677,7 +3703,8 @@ void MESH_OT_spin(wmOperatorType *ot) /* props */ RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX); RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates"); - RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f); + prop = RNA_def_float(ot->srna, "angle", DEG2RADF(90.0f), -FLT_MAX, FLT_MAX, "Angle", "Angle", DEG2RADF(-360.0f), DEG2RADF(360.0f)); + RNA_def_property_subtype(prop, PROP_ANGLE); RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f); @@ -3715,15 +3742,11 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) v1 = NULL; v2 = NULL; for (eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); eve; eve = BM_iter_step(&iter)) { - valence = 0; - for (eed = BM_iter_new(&eiter, em->bm, BM_EDGES_OF_VERT, eve); eed; eed = BM_iter_step(&eiter)) { - if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { valence++; } - } if (valence == 1) { @@ -3753,14 +3776,14 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) negate_v3(dvec); if (!EDBM_op_init(em, &spinop, op, - "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i ang=%f do_dupli=%b", + "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b", BM_ELEM_SELECT, cent, axis, dvec, turns * steps, 360.0f * turns, FALSE)) { return OPERATOR_CANCELLED; } BMO_op_exec(bm, &spinop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(bm, &spinop, "lastout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &spinop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -4602,11 +4625,15 @@ void MESH_OT_noise(wmOperatorType *ot) RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f); } +#define NEW_BEVEL 1 + typedef struct { BMEditMesh *em; BMBackup mesh_backup; +#ifndef NEW_BEVEL float *weights; int li; +#endif int mcenter[2]; float initial_length; float pixel_size; /* use when mouse input is interpreted as spatial distance */ @@ -4619,13 +4646,25 @@ typedef struct { static void edbm_bevel_update_header(wmOperator *op, bContext *C) { +#ifdef NEW_BEVEL + static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), offset: %s, segments: %d"; +#else static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), factor: %s, Use Dist (D): %s: Use Even (E): %s"; + BevelData *opdata = op->customdata; +#endif char msg[HEADER_LENGTH]; ScrArea *sa = CTX_wm_area(C); - BevelData *opdata = op->customdata; if (sa) { +#ifdef NEW_BEVEL + char offset_str[NUM_STR_REP_LEN]; + BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset")); + BLI_snprintf(msg, HEADER_LENGTH, str, + offset_str, + RNA_int_get(op->ptr, "segments") + ); +#else char factor_str[NUM_STR_REP_LEN]; if (hasNumInput(&opdata->num_input)) outputNumInput(&opdata->num_input, factor_str); @@ -4636,11 +4675,13 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C) RNA_boolean_get(op->ptr, "use_dist") ? "On" : "Off", RNA_boolean_get(op->ptr, "use_even") ? "On" : "Off" ); +#endif ED_area_headerprint(sa, msg); } } +#ifndef NEW_BEVEL static void edbm_bevel_recalc_weights(wmOperator *op) { float df, s, ftot; @@ -4668,15 +4709,20 @@ static void edbm_bevel_recalc_weights(wmOperator *op) mul_vn_fl(opdata->weights, recursion, 1.0f / (float)ftot); } +#endif static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); +#ifdef NEW_BEVEL + BevelData *opdata; +#else BMIter iter; BMEdge *eed; BevelData *opdata; int li; +#endif if (em == NULL) { return 0; @@ -4684,6 +4730,7 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator"); +#ifndef NEW_BEVEL BM_data_layer_add(em->bm, &em->bm->edata, CD_PROP_FLT); li = CustomData_number_of_layers(&em->bm->edata, CD_PROP_FLT) - 1; @@ -4693,10 +4740,12 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) *dv = d; } - - opdata->em = em; + opdata->li = li; opdata->weights = NULL; +#endif + + opdata->em = em; opdata->is_modal = is_modal; opdata->shift_factor = -1.0f; @@ -4706,7 +4755,9 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) /* avoid the cost of allocating a bm copy */ if (is_modal) opdata->mesh_backup = EDBM_redo_state_store(em); +#ifndef NEW_BEVEL edbm_bevel_recalc_weights(op); +#endif return 1; } @@ -4716,6 +4767,35 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op) BevelData *opdata = op->customdata; BMEditMesh *em = opdata->em; BMOperator bmop; +#ifdef NEW_BEVEL + float offset = RNA_float_get(op->ptr, "offset"); + int segments = RNA_int_get(op->ptr, "segments"); + + /* revert to original mesh */ + if (opdata->is_modal) { + EDBM_redo_state_restore(opdata->mesh_backup, em, FALSE); + } + + if (!EDBM_op_init(em, &bmop, op, + "bevel geom=%hev offset=%f segments=%i", + BM_ELEM_SELECT, offset, segments)) + { + return 0; + } + + BMO_op_exec(em->bm, &bmop); + + if (offset != 0.0f) { + /* not essential, but we may have some loose geometry that + * won't get bevel'd and better not leave it selected */ + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); + } + + /* no need to de-select existing geometry */ + if (!EDBM_op_finish(em, &bmop, op, TRUE)) + return 0; +#else int i; float factor = RNA_float_get(op->ptr, "percent") /*, dfac */ /* UNUSED */; @@ -4743,6 +4823,7 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op) if (!EDBM_op_finish(em, &bmop, op, TRUE)) return 0; } +#endif EDBM_mesh_normals_update(opdata->em); @@ -4760,10 +4841,12 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op) if (sa) { ED_area_headerprint(sa, NULL); } +#ifndef NEW_BEVEL BM_data_layer_free_n(opdata->em->bm, &opdata->em->bm->edata, CD_PROP_FLT, opdata->li); if (opdata->weights) MEM_freeN(opdata->weights); +#endif if (opdata->is_modal) { EDBM_redo_state_free(&opdata->mesh_backup, NULL, FALSE); } @@ -4844,7 +4927,11 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) { BevelData *opdata = op->customdata; +#ifdef NEW_BEVEL + int use_dist = TRUE; +#else int use_dist = RNA_boolean_get(op->ptr, "use_dist"); +#endif float mdiff[2]; float factor; @@ -4861,8 +4948,13 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) /* Fake shift-transform... */ if (event->shift) { - if (opdata->shift_factor < 0.0f) + if (opdata->shift_factor < 0.0f) { +#ifdef NEW_BEVEL + opdata->shift_factor = RNA_float_get(op->ptr, "factor"); +#else opdata->shift_factor = RNA_float_get(op->ptr, "percent"); +#endif + } factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor; } else if (opdata->shift_factor >= 0.0f) @@ -4882,12 +4974,23 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) { BevelData *opdata = op->customdata; + int segments = RNA_int_get(op->ptr, "segments"); if (event->val == KM_PRESS) { /* Try to handle numeric inputs... */ - float factor; +#ifdef NEW_BEVEL if (handleNumInput(&opdata->num_input, event)) { + float value = RNA_float_get(op->ptr, "offset"); + applyNumInput(&opdata->num_input, &value); + RNA_float_set(op->ptr, "offset", value); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + return OPERATOR_RUNNING_MODAL; + } +#else + if (handleNumInput(&opdata->num_input, event)) { + float factor = RNA_float_get(op->ptr, "percent"); applyNumInput(&opdata->num_input, &factor); CLAMP(factor, 0.0f, 1.0f); RNA_float_set(op->ptr, "percent", factor); @@ -4896,6 +4999,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_update_header(op, C); return OPERATOR_RUNNING_MODAL; } +#endif } switch (event->type) { @@ -4907,7 +5011,11 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) case MOUSEMOVE: if (!hasNumInput(&opdata->num_input)) { const float factor = edbm_bevel_mval_factor(op, event); +#ifdef NEW_BEVEL + RNA_float_set(op->ptr, "offset", factor); +#else RNA_float_set(op->ptr, "percent", factor); +#endif edbm_bevel_calc(C, op); edbm_bevel_update_header(op, C); @@ -4921,6 +5029,30 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_exit(C, op); return OPERATOR_FINISHED; +#ifdef NEW_BEVEL + case WHEELUPMOUSE: /* change number of segments */ + case PAGEUPKEY: + if (event->val == KM_RELEASE) + break; + + segments++; + RNA_int_set(op->ptr, "segments", segments); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + break; + + case WHEELDOWNMOUSE: /* change number of segments */ + case PAGEDOWNKEY: + if (event->val == KM_RELEASE) + break; + + segments = max_ii(segments - 1, 1); + RNA_int_set(op->ptr, "segments", segments); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + break; + +#else case EKEY: if (event->val == KM_PRESS) { int use_even = RNA_boolean_get(op->ptr, "use_even"); @@ -4945,6 +5077,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_update_header(op, C); } break; +#endif } return OPERATOR_RUNNING_MODAL; @@ -4967,6 +5100,10 @@ void MESH_OT_bevel(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; +#ifdef NEW_BEVEL + RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Offset", "", 0.0f, 1.0f); + RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8); +#else /* take note, used as a factor _and_ a distance depending on 'use_dist' */ RNA_def_float(ot->srna, "percent", 0.0f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f); /* XXX, disabled for 2.63 release, needs to work much better without overlap before we can give to users. */ @@ -4974,6 +5111,7 @@ void MESH_OT_bevel(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_even", FALSE, "Even", "Calculate evenly spaced bevel"); RNA_def_boolean(ot->srna, "use_dist", FALSE, "Distance", "Interpret the percent in blender units"); +#endif } @@ -4994,7 +5132,7 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op) /* when merge is used the edges are joined and remain selected */ if (use_merge == FALSE) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); } if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -5167,11 +5305,11 @@ static int edbm_inset_calc(bContext *C, wmOperator *op) if (use_select_inset) { /* deselect original faces/verts */ EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); } else { BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, FALSE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, FALSE); /* re-select faces so the verts and edges get selected too */ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, TRUE, BM_ELEM_SELECT); } @@ -5234,9 +5372,10 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event) if (event->val == KM_PRESS) { /* Try to handle numeric inputs... */ - float amounts[2]; if (handleNumInput(&opdata->num_input, event)) { + float amounts[2] = {RNA_float_get(op->ptr, "thickness"), + RNA_float_get(op->ptr, "depth")}; applyNumInput(&opdata->num_input, amounts); amounts[0] = max_ff(amounts[0], 0.0f); RNA_float_set(op->ptr, "thickness", amounts[0]); @@ -5428,7 +5567,7 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) if (use_replace) { BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "delete geom=%hvef context=%i", @@ -5436,7 +5575,7 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) } BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -5499,8 +5638,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Delete unused vertices, edges, and faces */ if (RNA_boolean_get(op->ptr, "delete_unused")) { - if (!EDBM_op_callf(em, op, "delete geom=%s context=%i", - &bmop, "unused_geom", DEL_ONLYTAGGED)) + if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", + &bmop, "geom_unused.out", DEL_ONLYTAGGED)) { EDBM_op_finish(em, &bmop, op, TRUE); return OPERATOR_CANCELLED; @@ -5509,8 +5648,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Delete hole edges/faces */ if (RNA_boolean_get(op->ptr, "make_holes")) { - if (!EDBM_op_callf(em, op, "delete geom=%s context=%i", - &bmop, "holes_geom", DEL_ONLYTAGGED)) + if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", + &bmop, "geom_holes.out", DEL_ONLYTAGGED)) { EDBM_op_finish(em, &bmop, op, TRUE); return OPERATOR_CANCELLED; @@ -5519,8 +5658,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Merge adjacent triangles */ if (RNA_boolean_get(op->ptr, "join_triangles")) { - if (!EDBM_op_callf(em, op, "join_triangles faces=%s limit=%f", - &bmop, "geomout", + if (!EDBM_op_callf(em, op, "join_triangles faces=%S limit=%f", + &bmop, "geom.out", RNA_float_get(op->ptr, "limit"))) { EDBM_op_finish(em, &bmop, op, TRUE); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index ef3d8db4156..2cf63586142 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -263,11 +263,13 @@ int EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) return EDBM_op_finish(em, &bmop, op, TRUE); } -int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *selectslot, const char *fmt, ...) +int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_slot_out, const char *fmt, ...) { + BMOpSlot *slot_select_out; BMesh *bm = em->bm; BMOperator bmop; va_list list; + char hflag; va_start(list, fmt); @@ -283,9 +285,12 @@ int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *selects BMO_op_exec(bm, &bmop); + slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out); + hflag = slot_select_out->slot_subtype.elem & BM_ALL_NOLOOP; + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, selectslot, BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, select_slot_out, hflag, BM_ELEM_SELECT, TRUE); va_end(list); return EDBM_op_finish(em, &bmop, op, TRUE); @@ -494,11 +499,11 @@ void EDBM_select_more(BMEditMesh *em) int use_faces = em->selectmode == SCE_SELECT_FACE; BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS, - "region_extend geom=%hvef constrict=%b use_faces=%b", + "region_extend geom=%hvef use_constrict=%b use_faces=%b", BM_ELEM_SELECT, FALSE, use_faces); BMO_op_exec(em->bm, &bmop); /* don't flush selection in edge/vertex mode */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); BMO_op_finish(em->bm, &bmop); EDBM_select_flush(em); @@ -510,11 +515,11 @@ void EDBM_select_less(BMEditMesh *em) int use_faces = em->selectmode == SCE_SELECT_FACE; BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS, - "region_extend geom=%hvef constrict=%b use_faces=%b", + "region_extend geom=%hvef use_constrict=%b use_faces=%b", BM_ELEM_SELECT, TRUE, use_faces); BMO_op_exec(em->bm, &bmop); /* don't flush selection in edge/vertex mode */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); BMO_op_finish(em->bm, &bmop); EDBM_selectmode_flush(em); diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 82b785e5785..e335c909e8e 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -80,9 +80,6 @@ int EDBM_op_finish(struct BMEditMesh *em, struct BMOperator *bmop, void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag); void EDBM_stats_update(struct BMEditMesh *em); -/* TODO, move to math_geometry.c */ -float labda_PdistVL2Dfl(const float v1[3], const float v2[3], const float v3[3]); - /* ******************** editface.c */ void MESH_OT_separate(struct wmOperatorType *ot); @@ -129,6 +126,7 @@ void MESH_OT_faces_select_linked_flat(struct wmOperatorType *ot); void MESH_OT_edges_select_sharp(struct wmOperatorType *ot); void MESH_OT_select_shortest_path(struct wmOperatorType *ot); void MESH_OT_select_similar(struct wmOperatorType *ot); +void MESH_OT_select_mode(struct wmOperatorType *ot); void MESH_OT_select_random(struct wmOperatorType *ot); void MESH_OT_loop_multi_select(struct wmOperatorType *ot); void MESH_OT_mark_seam(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index f6f8eee0a69..83a1261e981 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -341,7 +341,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, co[1] = bmin[1] + v[1] * ch; co[2] = bmin[2] + v[2] * cs; SWAP(float, co[1], co[2]); - BM_vert_create(em->bm, co, NULL); + BM_vert_create(em->bm, co, NULL, 0); } /* create custom data layer to save polygon idx */ @@ -372,7 +372,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, for (j = nv; j < ndv; j++) { copy_v3_v3(co, &dverts[3 * (vbase + j)]); SWAP(float, co[1], co[2]); - BM_vert_create(em->bm, co, NULL); + BM_vert_create(em->bm, co, NULL, 0); } EDBM_index_arrays_init(em, 1, 0, 0); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index d319fdcca26..a413a60412c 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -129,6 +129,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_edge_face_add); WM_operatortype_append(MESH_OT_select_shortest_path); WM_operatortype_append(MESH_OT_select_similar); + WM_operatortype_append(MESH_OT_select_mode); WM_operatortype_append(MESH_OT_loop_multi_select); WM_operatortype_append(MESH_OT_mark_seam); WM_operatortype_append(MESH_OT_mark_sharp); @@ -277,13 +278,21 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) /* standard mouse selection goes via space_view3d */ kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); kmi = WM_keymap_add_item(keymap, "MESH_OT_edgering_select", SELECTMOUSE, KM_PRESS, KM_ALT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); kmi = WM_keymap_add_item(keymap, "MESH_OT_edgering_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT | KM_CTRL, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); WM_keymap_add_item(keymap, "MESH_OT_select_shortest_path", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 9fc4e0a906d..7c4a547debc 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -210,8 +210,8 @@ float ED_object_new_primitive_matrix(bContext *C, Object *obedit, invert_m3_m3(imat, mat); mul_m3_v3(imat, primmat[3]); - if (v3d) { - float dia = ED_view3d_grid_scale(scene, v3d, NULL); + { + const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL); if (apply_diameter) { primmat[0][0] *= dia; @@ -271,7 +271,7 @@ int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], fl if (RNA_struct_property_is_set(op->ptr, "enter_editmode") && enter_editmode) *enter_editmode = RNA_boolean_get(op->ptr, "enter_editmode"); else { - *enter_editmode = U.flag & USER_ADD_EDITMODE; + *enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0; RNA_boolean_set(op->ptr, "enter_editmode", *enter_editmode); } } @@ -1136,7 +1136,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (dupli_gh) BLI_ghash_insert(dupli_gh, dob, ob); if (parent_gh) - BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->index)), ob); + BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->persistent_id[0])), ob); } if (use_hierarchy) { @@ -1150,7 +1150,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, /* find parent that was also made real */ if (ob_src_par) { - GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->index)); + GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->persistent_id[0])); ob_dst_par = BLI_ghash_lookup(parent_gh, pair); BLI_ghashutil_pairfree(pair); } diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index ee3c66b6eac..e144c38a350 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -114,7 +114,7 @@ typedef struct { } MultiresBakeRender; typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - const int face_index, const int lvl, const float st[2], + ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y); typedef void * (*MInitBakeData)(MultiresBakeRender *bkr, Image *ima); @@ -133,6 +133,7 @@ typedef struct { DerivedMesh *lores_dm, *hires_dm; int lvl; void *bake_data; + ImBuf *ibuf; MPassKnownData pass_data; } MResolvePixelData; @@ -257,7 +258,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) /* sequence end */ data->pass_data(data->lores_dm, data->hires_dm, data->bake_data, - data->face_index, data->lvl, st, to_tang, x, y); + data->ibuf, data->face_index, data->lvl, st, to_tang, x, y); } static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y) @@ -368,7 +369,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) { DerivedMesh *dm = bkr->lores_dm; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); const int lvl = bkr->lvl; const int tot_face = dm->getNumTessFaces(dm); MVert *mvert = dm->getVertArray(dm); @@ -414,6 +415,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData continue; data.face_index = f; + data.ibuf = ibuf; /* might support other forms of diagonal splits later on such as * split by shortest diagonal.*/ @@ -449,32 +451,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData if (freeBakeData) freeBakeData(data.bake_data); } -} -static void interp_bilinear_quad_data(float data[4][3], float u, float v, float res[3]) -{ - float vec[3]; - - copy_v3_v3(res, data[0]); - mul_v3_fl(res, (1 - u) * (1 - v)); - copy_v3_v3(vec, data[1]); - mul_v3_fl(vec, u * (1 - v)); add_v3_v3(res, vec); - copy_v3_v3(vec, data[2]); - mul_v3_fl(vec, u * v); add_v3_v3(res, vec); - copy_v3_v3(vec, data[3]); - mul_v3_fl(vec, (1 - u) * v); add_v3_v3(res, vec); -} - -static void interp_barycentric_tri_data(float data[3][3], float u, float v, float res[3]) -{ - float vec[3]; - - copy_v3_v3(res, data[0]); - mul_v3_fl(res, u); - copy_v3_v3(vec, data[1]); - mul_v3_fl(vec, v); add_v3_v3(res, vec); - copy_v3_v3(vec, data[2]); - mul_v3_fl(vec, 1.0f - u - v); add_v3_v3(res, vec); + BKE_image_release_ibuf(ima, ibuf, NULL); } /* mode = 0: interpolate normals, @@ -507,7 +485,7 @@ static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1)); } - interp_bilinear_quad_data(data, u, v, res); + interp_bilinear_quad_v3(data, u, v, res); } static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, @@ -579,7 +557,7 @@ static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, const float u, dm->getVertCo(dm, mface->v4, data[3]); } - interp_bilinear_quad_data(data, u, v, res); + interp_bilinear_quad_v3(data, u, v, res); } /* mode = 0: interpolate normals, @@ -599,13 +577,13 @@ static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float dm->getVertCo(dm, mface->v3, data[2]); } - interp_barycentric_tri_data(data, u, v, res); + interp_barycentric_tri_v3(data, u, v, res); } static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) { MHeightBakeData *height_data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); DerivedMesh *lodm = bkr->lores_dm; height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData"); @@ -635,6 +613,8 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); + BKE_image_release_ibuf(ima, ibuf, NULL); + return (void *)height_data; } @@ -661,7 +641,7 @@ static void free_normal_data(void *bake_data) static void apply_heights_data(void *bake_data) { MHeightBakeData *height_data = (MHeightBakeData *)bake_data; - ImBuf *ibuf = BKE_image_get_ibuf(height_data->ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(height_data->ima, NULL, NULL); int x, y, i; float height, *heights = height_data->heights; float min = height_data->height_min, max = height_data->height_max; @@ -693,6 +673,8 @@ static void apply_heights_data(void *bake_data) } ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(height_data->ima, ibuf, NULL); } static void free_heights_data(void *bake_data) @@ -713,13 +695,11 @@ static void free_heights_data(void *bake_data) * mesh to make texture smoother) let's call this point p0 and n. * - height wound be dot(n, p1-p0) */ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - const int face_index, const int lvl, const float st[2], + ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y) { MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; - Image *ima = mtface[face_index].tpage; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); MHeightBakeData *height_data = (MHeightBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; @@ -790,13 +770,11 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, * - multiply it by tangmat * - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - const int face_index, const int lvl, const float st[2], + ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y) { MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; - Image *ima = mtface[face_index].tpage; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; @@ -879,7 +857,7 @@ static void bake_images(MultiresBakeRender *bkr) for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf->x > 0 && ibuf->y > 0) { ibuf->userdata = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask"); @@ -895,6 +873,8 @@ static void bake_images(MultiresBakeRender *bkr) } } + BKE_image_release_ibuf(ima, ibuf, NULL); + ima->id.flag |= LIB_DOIT; } } @@ -905,7 +885,7 @@ static void finish_images(MultiresBakeRender *bkr) for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf->x <= 0 || ibuf->y <= 0) continue; @@ -926,6 +906,8 @@ static void finish_images(MultiresBakeRender *bkr) MEM_freeN(ibuf->userdata); ibuf->userdata = NULL; } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } @@ -1000,7 +982,7 @@ static int multiresbake_check(bContext *C, wmOperator *op) ok = 0; } else { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (!ibuf) { BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer"); @@ -1017,6 +999,8 @@ static int multiresbake_check(bContext *C, wmOperator *op) if (!ok) BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type"); } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } @@ -1087,10 +1071,12 @@ static void clear_images(MTFace *mtface, int totface) Image *ima = mtface[a].tpage; if ((ima->id.flag & LIB_DOIT) == 0) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); ima->id.flag |= LIB_DOIT; + + BKE_image_release_ibuf(ima, ibuf, NULL); } } @@ -1384,7 +1370,7 @@ static void finish_bake_internal(BakeRender *bkr) /* force OpenGL reload and mipmap recalc */ for (ima = G.main->image.first; ima; ima = ima->id.next) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); /* some of the images could have been changed during bake, * so recreate mipmaps regardless bake result status @@ -1409,6 +1395,8 @@ static void finish_bake_internal(BakeRender *bkr) ibuf->userdata = NULL; } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index c0c2195592b..d39e34824b9 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -550,7 +550,8 @@ static int editmode_toggle_poll(bContext *C) if (ELEM(NULL, ob, ob->data) || ((ID *)ob->data)->lib) return 0; - if (ob->restrictflag & OB_RESTRICT_VIEW) + /* if hidden but in edit mode, we still display */ + if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) return 0; return (ob->type == OB_MESH || ob->type == OB_ARMATURE || @@ -1380,7 +1381,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d) if (ma->mtex[b] && ma->mtex[b]->tex) { tex = ma->mtex[b]->tex; if (tex->type == TEX_IMAGE && tex->ima) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, NULL, NULL); /* texturespace */ space = 1.0; @@ -1402,6 +1403,8 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d) done = TRUE; DAG_id_tag_update(&ob->id, OB_RECALC_OB); + + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } } if (done) break; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 3d2c4f95624..7d3d6861418 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -555,7 +555,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M Key *key = me->key; KeyBlock *kb; - if (!modifier_sameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { + if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); return 0; } @@ -688,6 +688,13 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data"); return 0; } + else if ((ob->mode & OB_MODE_SCULPT) && + (find_multires_modifier_before(scene, md)) && + (modifier_isSameTopology(md) == FALSE)) + { + BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); + return 0; + } if (md != ob->modifiers.first) BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected"); @@ -1000,7 +1007,7 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - + if (!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 58c6959d6f0..0988a196fb1 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -643,8 +643,8 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object /* apply transformation of previous parenting */ if (keep_transform) { - /* was removed because of bug [#23577], - * but this can be handy in some cases too [#32616], so make optional */ + /* was removed because of bug [#23577], + * but this can be handy in some cases too [#32616], so make optional */ BKE_object_apply_mat4(ob, ob->obmat, FALSE, FALSE); } @@ -2148,7 +2148,7 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, wmEvent *even DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, ma); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 2b6d69ca694..6a511d4d924 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -137,9 +137,11 @@ static int ED_object_shape_key_remove(bContext *C, Object *ob) } if (key->totkey == 0) { - if (GS(key->from->name) == ID_ME) ((Mesh *)key->from)->key = NULL; - else if (GS(key->from->name) == ID_CU) ((Curve *)key->from)->key = NULL; - else if (GS(key->from->name) == ID_LT) ((Lattice *)key->from)->key = NULL; + switch (GS(key->from->name)) { + case ID_ME: ((Mesh *)key->from)->key = NULL; break; + case ID_CU: ((Curve *)key->from)->key = NULL; break; + case ID_LT: ((Lattice *)key->from)->key = NULL; break; + } BKE_libblock_free_us(&(bmain->key), key); } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 05524af34f0..1b135c0686e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -400,22 +400,22 @@ typedef enum WT_ReplaceMode { } WT_ReplaceMode; static EnumPropertyItem WT_vertex_group_mode_item[] = { - {WT_REPLACE_ACTIVE_VERTEX_GROUP, "WT_REPLACE_ACTIVE_VERTEX_GROUP", 1, "Active", "Transfer active vertex group from selected to active mesh"}, - {WT_REPLACE_ALL_VERTEX_GROUPS, "WT_REPLACE_ALL_VERTEX_GROUPS", 1, "All", "Transfer all vertex groups from selected to active mesh"}, + {WT_REPLACE_ACTIVE_VERTEX_GROUP, "WT_REPLACE_ACTIVE_VERTEX_GROUP", 0, "Active", "Transfer active vertex group from selected to active mesh"}, + {WT_REPLACE_ALL_VERTEX_GROUPS, "WT_REPLACE_ALL_VERTEX_GROUPS", 0, "All", "Transfer all vertex groups from selected to active mesh"}, {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem WT_method_item[] = { - {WT_BY_INDEX, "WT_BY_INDEX", 1, "Vertex index", "Copy for identical meshes"}, - {WT_BY_NEAREST_VERTEX, "WT_BY_NEAREST_VERTEX", 1, "Nearest vertex", "Copy weight from closest vertex"}, - {WT_BY_NEAREST_FACE, "WT_BY_NEAREST_FACE", 1, "Nearest face", "Barycentric interpolation from nearest face"}, - {WT_BY_NEAREST_VERTEX_IN_FACE, "WT_BY_NEAREST_VERTEX_IN_FACE", 1, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"}, + {WT_BY_INDEX, "WT_BY_INDEX", 0, "Vertex index", "Copy for identical meshes"}, + {WT_BY_NEAREST_VERTEX, "WT_BY_NEAREST_VERTEX", 0, "Nearest vertex", "Copy weight from closest vertex"}, + {WT_BY_NEAREST_FACE, "WT_BY_NEAREST_FACE", 0, "Nearest face", "Barycentric interpolation from nearest face"}, + {WT_BY_NEAREST_VERTEX_IN_FACE, "WT_BY_NEAREST_VERTEX_IN_FACE", 0, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"}, {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem WT_replace_mode_item[] = { - {WT_REPLACE_ALL_WEIGHTS, "WT_REPLACE_ALL_WEIGHTS", 1, "All", "Overwrite all weights"}, - {WT_REPLACE_EMPTY_WEIGHTS, "WT_REPLACE_EMPTY_WEIGHTS", 1, "Empty", "Add weights to vertices with no weight"}, + {WT_REPLACE_ALL_WEIGHTS, "WT_REPLACE_ALL_WEIGHTS", 0, "All", "Overwrite all weights"}, + {WT_REPLACE_EMPTY_WEIGHTS, "WT_REPLACE_EMPTY_WEIGHTS", 0, "Empty", "Add weights to vertices with no weight"}, {0, NULL, 0, NULL, NULL} }; @@ -845,25 +845,26 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) { MDeformVert *dv = NULL; - BMVert *eve; - Mesh *me; /* get the deform vertices corresponding to the vertnum */ if (ob->type == OB_MESH) { - me = ob->data; + Mesh *me = ob->data; if (me->edit_btmesh) { - eve = BM_vert_at_index(me->edit_btmesh->bm, vertnum); + /* warning, this lookup is _not_ fast */ + BMVert *eve = BM_vert_at_index(me->edit_btmesh->bm, vertnum); if (!eve) { return 0.0f; } dv = CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT); } else { - if (vertnum >= me->totvert) { - return 0.0f; + if (me->dvert) { + if (vertnum >= me->totvert) { + return 0.0f; + } + dv = &me->dvert[vertnum]; } - dv = &me->dvert[vertnum]; } } else if (ob->type == OB_LATTICE) { @@ -2573,7 +2574,7 @@ static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op)) ED_vgroup_add(ob); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -2604,7 +2605,7 @@ static int vertex_group_remove_exec(bContext *C, wmOperator *op) vgroup_delete(ob); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -2770,7 +2771,7 @@ static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) vgroup_duplicate(ob); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); return OPERATOR_FINISHED; } @@ -3198,7 +3199,7 @@ static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, base->object); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, base->object->data); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, base->object->data); retval = OPERATOR_FINISHED; } @@ -3355,7 +3356,7 @@ static int set_active_group_exec(bContext *C, wmOperator *op) ob->actdef = nr + 1; DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); return OPERATOR_FINISHED; } @@ -3519,7 +3520,7 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op) if (ret != OPERATOR_CANCELLED) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); } if (name_array) MEM_freeN(name_array); @@ -3574,7 +3575,7 @@ static int vgroup_move_exec(bContext *C, wmOperator *op) if (ret != OPERATOR_CANCELLED) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); } return ret; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index f8ec51c7a7c..f5754297e9f 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -401,6 +401,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data) static int key_test_depth(PEData *data, const float co[3], const int screen_co[2]) { View3D *v3d= data->vc.v3d; + ViewDepths *vd = data->vc.rv3d->depths; double ux, uy, uz; float depth; @@ -428,12 +429,15 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2 /* view3d_validate_backbuf(&data->vc); */ glReadPixels(screen_co[0], screen_co[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); #else /* faster to use depths, these are calculated in PE_set_view3d_data */ - { - ViewDepths *vd = data->vc.rv3d->depths; - assert(vd && vd->depths); + + /* check if screen_co is within bounds because brush_cut uses out of screen coords */ + if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) { + BLI_assert(vd && vd->depths); /* we know its not clipped */ depth = vd->depths[screen_co[1] * vd->w + screen_co[0]]; } + else + return 0; #endif if ((float)uz - 0.00001f > depth) @@ -2437,7 +2441,8 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, "Threshold", "Threshold distance withing which particles are removed", 0.00001f, 0.1f); + RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, + "Merge Distance", "Threshold distance withing which particles are removed", 0.00001f, 0.1f); } diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 218af8f0f33..5304c64c2a9 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -446,7 +446,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid for (fobj=fobjects->first; fobj; fobj=fobj->next) { Object *ob = fobj->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); - float active= (float)(fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE); + float active= (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) > 0 ? 1 : 0); float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f}; if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) @@ -467,6 +467,8 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid set_channel(fobj->Scale, timeAtFrame, ob->size, i, CHANNEL_VEC); set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT); set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC); + + // printf("Active: %f, Frame: %f\n", active, timeAtFrame); if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) { set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT); @@ -574,7 +576,8 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) fsmesh.channelScale = NULL; /* Override user settings, only noslip is supported here! */ - fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; + if (fsmesh.type != OB_FLUIDSIM_CONTROL) + fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; } elbeemAddMesh(&fsmesh); @@ -961,8 +964,8 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* ******** prepare output file paths ******** */ outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer); - channels->length = scene->r.efra; - channels->aniFrameTime = (double)(domainSettings->animEnd - domainSettings->animStart) / (double)noFrames; + channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra) + channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames; /* ******** initialize and allocate animation channels ******** */ fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 4b177629f72..f8154f4abda 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -375,7 +375,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec /* make jobs timer to send notifier */ *(rj->do_update) = TRUE; } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void render_startjob(void *rjv, short *stop, short *do_update, float *progress) @@ -553,13 +553,20 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) rj->win = CTX_wm_window(C); rj->srl = srl; rj->camera_override = camera_override; - rj->lay = (v3d) ? v3d->lay : scene->lay; + rj->lay = scene->lay; rj->anim = is_animation; rj->write_still = is_write_still && !is_animation; rj->iuser.scene = scene; rj->iuser.ok = 1; rj->reports = op->reports; + if (v3d) { + rj->lay = v3d->lay; + + if (v3d->localvd) + rj->lay |= v3d->localvd->lay; + } + /* setup job */ if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render"; else name = "Render"; @@ -611,6 +618,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) /* contextual render, using current scene, view3d? */ void RENDER_OT_render(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Render"; ot->description = "Render active scene"; @@ -625,7 +634,9 @@ void RENDER_OT_render(wmOperatorType *ot) RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene"); RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)"); - RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render (used only when animation is disabled)"); - RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME - 2, "Scene", "Scene to render, current scene if not specified"); + prop = RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render (used only when animation is disabled)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME - 2, "Scene", "Scene to render, current scene if not specified"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index e4592a4f77e..73f8abdf15f 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -288,7 +288,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } } - BKE_image_release_ibuf(oglrender->ima, lock); + BKE_image_release_ibuf(oglrender->ima, ibuf, lock); } static int screen_opengl_render_init(bContext *C, wmOperator *op) @@ -481,7 +481,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); OGLRender *oglrender = op->customdata; Scene *scene = oglrender->scene; - ImBuf *ibuf; + ImBuf *ibuf, *ibuf_save = NULL; void *lock; char name[FILE_MAX]; int ok = 0; @@ -549,47 +549,46 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) if (ibuf) { int needs_free = FALSE; + ibuf_save = ibuf; + if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) { - ImBuf *colormanage_ibuf; + ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); - colormanage_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings, - &scene->display_settings, &scene->r.im_format); - - // IMB_freeImBuf(ibuf); /* owned by the image */ - ibuf = colormanage_ibuf; needs_free = TRUE; } /* color -> grayscale */ /* editing directly would alter the render view */ if (scene->r.im_format.planes == R_IMF_PLANES_BW) { - ImBuf *ibuf_bw = IMB_dupImBuf(ibuf); + ImBuf *ibuf_bw = IMB_dupImBuf(ibuf_save); IMB_color_to_bw(ibuf_bw); if (needs_free) - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf_save); - ibuf = ibuf_bw; + ibuf_save = ibuf_bw; } else { /* this is lightweight & doesnt re-alloc the buffers, only do this * to save the correct bit depth since the image is always RGBA */ - ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf->x, ibuf->y, scene->r.im_format.planes, 0); - ibuf_cpy->rect = ibuf->rect; - ibuf_cpy->rect_float = ibuf->rect_float; - ibuf_cpy->zbuf_float = ibuf->zbuf_float; + ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf_save->x, ibuf_save->y, scene->r.im_format.planes, 0); + + ibuf_cpy->rect = ibuf_save->rect; + ibuf_cpy->rect_float = ibuf_save->rect_float; + ibuf_cpy->zbuf_float = ibuf_save->zbuf_float; if (needs_free) { - ibuf_cpy->mall = ibuf->mall; - ibuf->mall = 0; - IMB_freeImBuf(ibuf); + ibuf_cpy->mall = ibuf_save->mall; + ibuf_save->mall = 0; + IMB_freeImBuf(ibuf_save); } - ibuf = ibuf_cpy; + ibuf_save = ibuf_cpy; } if (is_movie) { - ok = oglrender->mh->append_movie(&scene->r, SFRA, CFRA, (int *)ibuf->rect, + ok = oglrender->mh->append_movie(&scene->r, SFRA, CFRA, (int *)ibuf_save->rect, oglrender->sizex, oglrender->sizey, oglrender->reports); if (ok) { printf("Append frame %d", scene->r.cfra); @@ -597,7 +596,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) } } else { - ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format); + ok = BKE_imbuf_write_stamp(scene, camera, ibuf_save, name, &scene->r.im_format); if (ok == 0) { printf("Write error: cannot save %s\n", name); @@ -609,11 +608,11 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) } } - /* imbuf knows which rects are not part of ibuf */ - IMB_freeImBuf(ibuf); + if (needs_free) + IMB_freeImBuf(ibuf_save); } - BKE_image_release_ibuf(oglrender->ima, lock); + BKE_image_release_ibuf(oglrender->ima, ibuf, lock); /* movie stats prints have no line break */ printf("\n"); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 53cb5340940..a864fe306b3 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -237,6 +237,14 @@ static int preview_mat_has_sss(Material *mat, bNodeTree *ntree) return 0; } +static Scene *preview_get_scene(void) +{ + if (pr_main == NULL) return NULL; + + return pr_main->scene.first; +} + + /* call this with a pointer to initialize preview scene */ /* call this with NULL to restore assigned ID pointers in preview scene */ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPreview *sp) @@ -244,9 +252,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre Scene *sce; Base *base; - if (pr_main == NULL) return NULL; - - sce = pr_main->scene.first; + sce = preview_get_scene(); if (sce) { /* this flag tells render to not execute depsgraph or ipos etc */ @@ -665,8 +671,23 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs char name[32]; int sizex; + /* in case of split preview, use border render */ + if (split) { + if (first) sizex = sp->sizex / 2; + else sizex = sp->sizex - sp->sizex / 2; + } + else sizex = sp->sizex; + + /* we have to set preview variables first */ + sce = preview_get_scene(); + if (sce) { + sce->r.xsch = sizex; + sce->r.ysch = sp->sizey; + sce->r.size = 100; + } + /* get the stuff from the builtin preview dbase */ - sce = preview_prepare_scene(sp->scene, id, idtype, sp); // XXX sizex + sce = preview_prepare_scene(sp->scene, id, idtype, sp); if (sce == NULL) return; if (!split || first) sprintf(name, "Preview %p", sp->owner); @@ -694,17 +715,6 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs sce->r.mode |= R_OSA; } - /* in case of split preview, use border render */ - if (split) { - if (first) sizex = sp->sizex / 2; - else sizex = sp->sizex - sp->sizex / 2; - } - else sizex = sp->sizex; - - /* allocates or re-uses render result */ - sce->r.xsch = sizex; - sce->r.ysch = sp->sizey; - sce->r.size = 100; /* callbacs are cleared on GetRender() */ if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) { @@ -924,13 +934,15 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat /* elubie: this needs to be changed: here image is always loaded if not * already there. Very expensive for large images. Need to find a way to * only get existing ibuf */ - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (ibuf == NULL || ibuf->rect == NULL) return; icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = TRUE; + + BKE_image_release_ibuf(ima, ibuf, NULL); } else if (idtype == ID_BR) { Brush *br = (Brush *)id; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 25a01d38dd5..eef5e705ce7 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -865,7 +865,7 @@ static int paste_material_exec(bContext *C, wmOperator *UNUSED(op)) paste_matcopybuf(ma); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_DRAW, ma); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); return OPERATOR_FINISHED; } @@ -1027,7 +1027,7 @@ static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op)) paste_mtex_copybuf(id); - WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_DRAW, NULL); + WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index c5320fde0ff..1ed1cbb2c6b 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -58,12 +58,15 @@ #include "GPU_material.h" #include "RE_engine.h" +#include "RE_pipeline.h" #include "ED_node.h" #include "ED_render.h" #include "render_intern.h" // own include +extern Material defmaterial; + /***************************** Render Engines ********************************/ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) @@ -153,10 +156,16 @@ void ED_render_engine_changed(Main *bmain) /* on changing the render engine type, clear all running render engines */ bScreen *sc; ScrArea *sa; + Scene *scene; for (sc = bmain->screen.first; sc; sc = sc->id.next) for (sa = sc->areabase.first; sa; sa = sa->next) ED_render_engine_area_exit(sa); + + RE_FreePersistentData(); + + for (scene = bmain->scene.first; scene; scene = scene->id.next) + ED_render_id_flush_update(bmain, &scene->id); } /***************************** Updates *********************************** @@ -247,6 +256,27 @@ static void material_changed(Main *bmain, Material *ma) } } +static void lamp_changed(Main *bmain, Lamp *la) +{ + Object *ob; + Material *ma; + + /* icons */ + BKE_icon_changed(BKE_icon_getid(&la->id)); + + /* glsl */ + for (ob = bmain->object.first; ob; ob = ob->id.next) + if (ob->data == la && ob->gpulamp.first) + GPU_lamp_free(ob); + + for (ma = bmain->mat.first; ma; ma = ma->id.next) + if (ma->gpumaterial.first) + GPU_material_free(ma); + + if (defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial); +} + static void texture_changed(Main *bmain, Tex *tex) { Material *ma; @@ -279,16 +309,14 @@ static void texture_changed(Main *bmain, Tex *tex) /* find lamps */ for (la = bmain->lamp.first; la; la = la->id.next) { if (mtex_use_tex(la->mtex, MAX_MTEX, tex)) { - /* pass */ + lamp_changed(bmain, la); } else if (la->nodetree && nodes_use_tex(la->nodetree, tex)) { - /* pass */ + lamp_changed(bmain, la); } else { continue; } - - BKE_icon_changed(BKE_icon_getid(&la->id)); } /* find worlds */ @@ -317,24 +345,6 @@ static void texture_changed(Main *bmain, Tex *tex) } } -static void lamp_changed(Main *bmain, Lamp *la) -{ - Object *ob; - Material *ma; - - /* icons */ - BKE_icon_changed(BKE_icon_getid(&la->id)); - - /* glsl */ - for (ob = bmain->object.first; ob; ob = ob->id.next) - if (ob->data == la && ob->gpulamp.first) - GPU_lamp_free(ob); - - for (ma = bmain->mat.first; ma; ma = ma->id.next) - if (ma->gpumaterial.first) - GPU_material_free(ma); -} - static void world_changed(Main *bmain, World *wo) { Material *ma; @@ -346,6 +356,9 @@ static void world_changed(Main *bmain, World *wo) for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->gpumaterial.first) GPU_material_free(ma); + + if (defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial); } static void image_changed(Main *bmain, Image *ima) @@ -374,10 +387,19 @@ static void scene_changed(Main *bmain, Scene *UNUSED(scene)) for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->gpumaterial.first) GPU_material_free(ma); + + if (defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial); } void ED_render_id_flush_update(Main *bmain, ID *id) { + /* this can be called from render or baking thread when a python script makes + * changes, in that case we don't want to do any editor updates, and making + * GPU changes is not possible because OpenGL only works in the main thread */ + if (!BLI_thread_is_main()) + return; + switch (GS(id->name)) { case ID_MA: material_changed(bmain, (Material *)id); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6a9c24d2913..67d4af916aa 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -293,29 +293,35 @@ int ED_operator_console_active(bContext *C) return ed_spacetype_test(C, SPACE_CONSOLE); } +static int ed_object_hidden(Object *ob) +{ + /* if hidden but in edit mode, we still display, can happen with animation */ + return ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)); +} + int ED_operator_object_active(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->restrictflag & OB_RESTRICT_VIEW)); + return ((ob != NULL) && !ed_object_hidden(ob)); } int ED_operator_object_active_editable(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW)); + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob)); } int ED_operator_object_active_editable_mesh(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob) && (ob->type == OB_MESH) && !(((ID *)ob->data)->lib)); } int ED_operator_object_active_editable_font(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob) && (ob->type == OB_FONT)); } diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 0ecac5fc497..ca85daadf3b 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -35,6 +35,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -52,6 +53,7 @@ #include "BKE_writeavi.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "RNA_access.h" #include "RNA_define.h" @@ -278,6 +280,7 @@ void SCREEN_OT_screenshot(wmOperatorType *ot) typedef struct ScreenshotJob { Main *bmain; Scene *scene; + wmWindowManager *wm; unsigned int *dumprect; int x, y, dumpsx, dumpsy; short *stop; @@ -395,6 +398,54 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped"); } +/* Helper callback for drawing the cursor itself */ +static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr)) +{ + + glPushMatrix(); + + glTranslatef((float)x, (float)y, 0.0f); + + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, 32); + glutil_draw_filled_arc(0.0, M_PI * 2.0, 20, 40); + + glColor4ub(255, 255, 255, 128); + glutil_draw_lined_arc(0.0, M_PI * 2.0, 20, 40); + + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + + glPopMatrix(); +} + +/* Turn brush cursor in 3D view on/off */ +static void screencast_cursor_toggle(wmWindowManager *wm, short enable) +{ + static void *cursor = NULL; + + if (cursor && !enable) { + /* clear cursor */ + WM_paint_cursor_end(wm, cursor); + cursor = NULL; + } + else if (enable) { + /* enable cursor */ + cursor = WM_paint_cursor_activate(wm, NULL, screencast_draw_cursor, NULL); + } +} + +static void screenshot_endjob(void *sjv) +{ + ScreenshotJob *sj = sjv; + + screencast_cursor_toggle(sj->wm, 0); +} + + static int screencast_exec(bContext *C, wmOperator *op) { bScreen *screen = CTX_wm_screen(C); @@ -418,15 +469,18 @@ static int screencast_exec(bContext *C, wmOperator *op) } sj->bmain = CTX_data_main(C); sj->scene = CTX_data_scene(C); - + sj->wm = CTX_wm_manager(C); + BKE_reports_init(&sj->reports, RPT_PRINT); /* setup job */ WM_jobs_customdata_set(wm_job, sj, screenshot_freejob); WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST); - WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, NULL); + WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob); - WM_jobs_start(CTX_wm_manager(C), wm_job); + WM_jobs_start(sj->wm, wm_job); + + screencast_cursor_toggle(sj->wm, 1); WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index e00a8776bea..b704414c321 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -109,19 +109,25 @@ #include "paint_intern.h" /* Defines and Structs */ +/* FTOCHAR as inline function */ +BLI_INLINE unsigned char f_to_char(const float val) +{ + return FTOCHAR(val); +} + #define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f) #define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \ - (c)[0] = FTOCHAR((f)[0]); \ - (c)[1] = FTOCHAR((f)[1]); \ - (c)[2] = FTOCHAR((f)[2]); \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ } (void)0 #define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \ - (c)[0] = FTOCHAR((f)[0]); \ - (c)[1] = FTOCHAR((f)[1]); \ - (c)[2] = FTOCHAR((f)[2]); \ - (c)[3] = FTOCHAR((f)[3]); \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ + (c)[3] = f_to_char((f)[3]); \ } (void)0 #define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \ (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ @@ -288,9 +294,11 @@ typedef struct ProjPaintState { char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */ int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */ int buckets_y; - + ProjPaintImage *projImages; + int pixel_sizeof; /* result of project_paint_pixel_sizeof(), constant per stroke */ + int image_tot; /* size of projectImages array */ float (*screenCoords)[4]; /* verts projected into floating point screen space */ @@ -379,6 +387,18 @@ typedef struct ProjPixelClone { PixelStore clonepx; } ProjPixelClone; +/* blur, store surrounding colors */ +#define PROJ_PIXEL_SOFTEN_TOT 4 +/* blur picking offset (in screenspace) */ +#define PROJ_PIXEL_SOFTEN_OFS_PX 1.0f + +static const float proj_pixel_soften_v2[PROJ_PIXEL_SOFTEN_TOT][2] = { + {-PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f}, + { 0.0f, -PROJ_PIXEL_SOFTEN_OFS_PX}, + { 0.0f, PROJ_PIXEL_SOFTEN_OFS_PX}, + { PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f}, +}; + /* Finish projection painting structs */ typedef struct UndoImageTile { @@ -480,7 +500,7 @@ static void image_undo_restore(bContext *C, ListBase *lb) ima = BLI_findstring(&bmain->image, tile->idname, offsetof(ID, name)); } - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima && ibuf && strcmp(tile->ibufname, ibuf->name) != 0) { /* current ImBuf filename was changed, probably current frame @@ -488,19 +508,27 @@ static void image_undo_restore(bContext *C, ListBase *lb) * full image user (which isn't so obvious, btw) try to find ImBuf with * matched file name in list of already loaded images */ + BKE_image_release_ibuf(ima, ibuf, NULL); + ibuf = BLI_findstring(&ima->ibufs, tile->ibufname, offsetof(ImBuf, name)); } - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } - if (ima->gen_type != tile->gen_type || ima->source != tile->source) + if (ima->gen_type != tile->gen_type || ima->source != tile->source) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } use_float = ibuf->rect_float ? 1 : 0; - if (use_float != tile->use_float) + if (use_float != tile->use_float) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } undo_copy_tile(tile, tmpibuf, ibuf, 1); @@ -510,6 +538,8 @@ static void image_undo_restore(bContext *C, ListBase *lb) if (ibuf->mipmap[0]) ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(ima, ibuf, NULL); } IMB_freeImBuf(tmpibuf); @@ -626,7 +656,7 @@ static float VecZDepthPersp(const float pt[2], * barycentric_weights_v2 would return, in this case its easiest just to * undo the 4th axis division and make it unit-sum * - * don't call barycentric_weights_v2() becaue our callers expect 'w' + * don't call barycentric_weights_v2() because our callers expect 'w' * to be weighted from the perspective */ w_tmp[0] = w[0] * v1[3]; w_tmp[1] = w[1] * v2[3]; @@ -1029,11 +1059,11 @@ static int pixel_bounds_uv( INIT_MINMAX2(min_uv, max_uv); - DO_MINMAX2(uv1, min_uv, max_uv); - DO_MINMAX2(uv2, min_uv, max_uv); - DO_MINMAX2(uv3, min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, uv1); + minmax_v2v2_v2(min_uv, max_uv, uv2); + minmax_v2v2_v2(min_uv, max_uv, uv3); if (is_quad) - DO_MINMAX2(uv4, min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, uv4); bounds_px->xmin = (int)(ibuf_x * min_uv[0]); bounds_px->ymin = (int)(ibuf_y * min_uv[1]); @@ -1059,7 +1089,7 @@ static int pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x, INIT_MINMAX2(min_uv, max_uv); while (tot--) { - DO_MINMAX2((*uv), min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, (*uv)); uv++; } @@ -1378,8 +1408,8 @@ static float project_paint_uvpixel_mask( Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index); const MTFace *tf_other = ps->dm_mtface_stencil + face_index; - if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) { - /* BKE_image_get_ibuf - TODO - this may be slow */ + if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { + /* BKE_image_acquire_ibuf - TODO - this may be slow */ unsigned char rgba_ub[4]; float rgba_f[4]; @@ -1391,7 +1421,9 @@ static float project_paint_uvpixel_mask( else { /* from char to float */ mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f); } - + + BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); + if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */ mask = (1.0f - mask); @@ -1491,6 +1523,16 @@ static float project_paint_uvpixel_mask( return mask; } +static int project_paint_pixel_sizeof(const short tool) +{ + if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) { + return sizeof(ProjPixelClone); + } + else { + return sizeof(ProjPixel); + } +} + /* run this function when we know a bucket's, face's pixel can be initialized, * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */ static ProjPixel *project_paint_uvpixel_init( @@ -1506,33 +1548,23 @@ static ProjPixel *project_paint_uvpixel_init( const float w[3]) { ProjPixel *projPixel; - short size; - + /* wrap pixel location */ x_px = x_px % ibuf->x; if (x_px < 0) x_px += ibuf->x; y_px = y_px % ibuf->y; if (y_px < 0) y_px += ibuf->y; - - if (ps->tool == PAINT_TOOL_CLONE) { - size = sizeof(ProjPixelClone); - } - else if (ps->tool == PAINT_TOOL_SMEAR) { - size = sizeof(ProjPixelClone); - } - else { - size = sizeof(ProjPixel); - } - - projPixel = (ProjPixel *)BLI_memarena_alloc(arena, size); + + BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool)); + projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof); //memset(projPixel, 0, size); if (ibuf->rect_float) { projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4); - projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0]; - projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1]; - projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2]; - projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3]; + projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0]; + projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1]; + projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2]; + projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3]; } else { projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4)); @@ -1559,8 +1591,8 @@ static ProjPixel *project_paint_uvpixel_init( Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index); const MTFace *tf_other = ps->dm_mtface_clone + face_index; - if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) { - /* BKE_image_get_ibuf - TODO - this may be slow */ + if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { + /* BKE_image_acquire_ibuf - TODO - this may be slow */ if (ibuf->rect_float) { if (ibuf_other->rect_float) { /* from float to float */ @@ -1582,6 +1614,8 @@ static ProjPixel *project_paint_uvpixel_init( project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL); } } + + BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); } else { if (ibuf->rect_float) { @@ -2906,7 +2940,7 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, fidx = mf->v4 ? 3 : 2; do { vCoSS = ps->screenCoords[*(&mf->v1 + fidx)]; - DO_MINMAX2(vCoSS, min, max); + minmax_v2v2_v2(min, max, vCoSS); } while (fidx--); project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax); @@ -3171,7 +3205,7 @@ static void project_paint_begin(ProjPaintState *ps) /* screen space, not clamped */ projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0]; projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1]; - DO_MINMAX2(projScreenCo, ps->screenMin, ps->screenMax); + minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); } } else { @@ -3186,7 +3220,7 @@ static void project_paint_begin(ProjPaintState *ps) projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0] / projScreenCo[3]; projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1] / projScreenCo[3]; projScreenCo[2] = projScreenCo[2] / projScreenCo[3]; /* Use the depth for bucket point occlusion */ - DO_MINMAX2(projScreenCo, ps->screenMin, ps->screenMax); + minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); } else { /* TODO - deal with cases where 1 side of a face goes behind the view ? @@ -3388,7 +3422,7 @@ static void project_paint_begin(ProjPaintState *ps) image_index = BLI_linklist_index(image_LinkList, tpage); - if (image_index == -1 && BKE_image_get_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ + if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ BLI_linklist_append(&image_LinkList, tpage); image_index = ps->image_tot; ps->image_tot++; @@ -3411,7 +3445,7 @@ static void project_paint_begin(ProjPaintState *ps) for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) { projIma->ima = node->link; projIma->touch = 0; - projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL); + projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL); projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); } @@ -3438,6 +3472,7 @@ static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2]) static void project_paint_end(ProjPaintState *ps) { int a; + ProjPaintImage *projIma; /* build undo data from original pixel colors */ if (U.uiflag & USER_GLOBALUNDO) { @@ -3525,7 +3560,14 @@ static void project_paint_end(ProjPaintState *ps) if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float); } /* done calculating undo data */ - + + /* dereference used image buffers */ + for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { + BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); + } + + BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL); + MEM_freeN(ps->screenCoords); MEM_freeN(ps->bucketRect); MEM_freeN(ps->bucketFaces); @@ -3814,15 +3856,97 @@ static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, fl BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena); } +/* do_projectpaint_soften for float & byte + */ +static float inv_pow2(float f) +{ + f = 1.0f - f; + f = f * f; + return 1.0f - f; +} + +static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *softenArena, LinkNode **softenPixels) +{ + unsigned int accum_tot = 0; + unsigned int i; + + float *rgba = projPixel->newColor.f; + + /* sigh, alpha values tend to need to be a _lot_ stronger with blur */ + mask = inv_pow2(mask); + alpha = inv_pow2(alpha); + + /* rather then painting, accumulate surrounding colors */ + zero_v4(rgba); + + for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) { + float co_ofs[2]; + float rgba_tmp[4]; + sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]); + if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) { + add_v4_v4(rgba, rgba_tmp); + accum_tot++; + } + } + + if (LIKELY(accum_tot != 0)) { + mul_v4_fl(rgba, 1.0f / (float)accum_tot); + blend_color_mix_float(rgba, projPixel->pixel.f_pt, rgba, alpha); + if (mask < 1.0f) blend_color_mix_float(rgba, projPixel->origColor.f, rgba, mask); + BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); + } +} + +static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *softenArena, LinkNode **softenPixels) +{ + unsigned int accum_tot = 0; + unsigned int i; + + float rgba[4]; /* convert to byte after */ + + /* sigh, alpha values tend to need to be a _lot_ stronger with blur */ + mask = inv_pow2(mask); + alpha = inv_pow2(alpha); + + /* rather then painting, accumulate surrounding colors */ + zero_v4(rgba); + + for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) { + float co_ofs[2]; + float rgba_tmp[4]; + sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]); + if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) { + add_v4_v4(rgba, rgba_tmp); + accum_tot++; + } + } + + if (LIKELY(accum_tot != 0)) { + unsigned char *rgba_ub = projPixel->newColor.ch; + + mul_v4_fl(rgba, 1.0f / (float)accum_tot); + IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_ub, rgba); + + blend_color_mix(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * 255)); + if (mask != 1.0f) blend_color_mix(rgba_ub, projPixel->origColor.ch, rgba_ub, (int)(mask * 255)); + BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); + } +} + +BLI_INLINE void rgba_float_to_uchar__mul_v3(unsigned char rgba_ub[4], const float rgba[4], const float rgb[3]) +{ + rgba_ub[0] = f_to_char(rgba[0] * rgb[0]); + rgba_ub[1] = f_to_char(rgba[1] * rgb[1]); + rgba_ub[2] = f_to_char(rgba[2] * rgb[2]); + rgba_ub[3] = f_to_char(rgba[3]); +} + static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float rgba[4], float alpha, float mask) { unsigned char rgba_ub[4]; if (ps->is_texbrush) { - rgba_ub[0] = FTOCHAR(rgba[0] * ps->brush->rgb[0]); - rgba_ub[1] = FTOCHAR(rgba[1] * ps->brush->rgb[1]); - rgba_ub[2] = FTOCHAR(rgba[2] * ps->brush->rgb[2]); - rgba_ub[3] = FTOCHAR(rgba[3]); + rgba_float_to_uchar__mul_v3(rgba_ub, rgba, ps->brush->rgb); } else { IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb); @@ -3912,6 +4036,10 @@ static void *do_projectpaint_thread(void *ph_v) LinkNode *smearPixels = NULL; LinkNode *smearPixels_f = NULL; MemArena *smearArena = NULL; /* mem arena for this brush projection only */ + + LinkNode *softenPixels = NULL; + LinkNode *softenPixels_f = NULL; + MemArena *softenArena = NULL; /* mem arena for this brush projection only */ if (tool == PAINT_TOOL_SMEAR) { pos_ofs[0] = pos[0] - lastpos[0]; @@ -3919,6 +4047,9 @@ static void *do_projectpaint_thread(void *ph_v) smearArena = BLI_memarena_new(1 << 16, "paint smear arena"); } + else if (tool == PAINT_TOOL_SOFTEN) { + softenArena = BLI_memarena_new(1 << 16, "paint soften arena"); + } /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */ @@ -4058,6 +4189,10 @@ static void *do_projectpaint_thread(void *ph_v) if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, alpha, mask, smearArena, &smearPixels_f, co); else do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co); break; + case PAINT_TOOL_SOFTEN: + if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, alpha, mask, softenArena, &softenPixels_f); + else do_projectpaint_soften(ps, projPixel, alpha, mask, softenArena, &softenPixels); + break; default: if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask, use_color_correction); else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask); @@ -4092,7 +4227,21 @@ static void *do_projectpaint_thread(void *ph_v) BLI_memarena_free(smearArena); } - + else if (tool == PAINT_TOOL_SOFTEN) { + + for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */ + projPixel = node->link; + *projPixel->pixel.uint_pt = projPixel->newColor.uint; + } + + for (node = softenPixels_f; node; node = node->next) { + projPixel = node->link; + copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f); + } + + BLI_memarena_free(softenArena); + } + return NULL; } @@ -4545,7 +4694,7 @@ static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float static int imapaint_canvas_set(ImagePaintState *s, Image *ima) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, s->sima ? &s->sima->iuser : NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); /* verify that we can paint and set canvas */ if (ima == NULL) { @@ -4568,10 +4717,12 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) /* set clone canvas */ if (s->tool == PAINT_TOOL_CLONE) { ima = s->brush->clone.image; - ibuf = BKE_image_get_ibuf(ima, s->sima ? &s->sima->iuser : NULL); + ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { + BKE_image_release_ibuf(ima, ibuf, NULL); return 0; + } s->clonecanvas = ibuf; @@ -4586,13 +4737,15 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) return 1; } -static void imapaint_canvas_free(ImagePaintState *UNUSED(s)) +static void imapaint_canvas_free(ImagePaintState *s) { + BKE_image_release_ibuf(s->image, s->canvas, NULL); + BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL); } static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) { - ImBuf *ibuf = BKE_image_get_ibuf(image, s->sima ? &s->sima->iuser : NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, s->sima ? &s->sima->iuser : NULL, NULL); float pos[2]; int is_data; @@ -4612,9 +4765,13 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) { if (update) imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint); + BKE_image_release_ibuf(image, ibuf, NULL); return 1; } - else return 0; + else { + BKE_image_release_ibuf(image, ibuf, NULL); + return 0; + } } static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPainter *painter, short texpaint, const int prevmval[2], const int mval[2], double time, float pressure) @@ -4632,7 +4789,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint ImBuf *ibuf; newimage = imapaint_face_image(s, newfaceindex); - ibuf = BKE_image_get_ibuf(newimage, s->sima ? &s->sima->iuser : NULL); + ibuf = BKE_image_acquire_ibuf(newimage, s->sima ? &s->sima->iuser : NULL, NULL); if (ibuf && ibuf->rect) imapaint_pick_uv(s->scene, s->ob, newfaceindex, mval, newuv); @@ -4640,6 +4797,8 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint newimage = NULL; newuv[0] = newuv[1] = 0.0f; } + + BKE_image_release_ibuf(newimage, ibuf, NULL); } else newuv[0] = newuv[1] = 0.0f; @@ -4842,6 +5001,10 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps) ps->tool = brush->imagepaint_tool; ps->blend = brush->blend; + /* sizeof ProjPixel, since we alloc this a _lot_ */ + ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool); + BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel)); + ps->is_airbrush = (brush->flag & BRUSH_AIRBRUSH) ? 1 : 0; ps->is_texbrush = (brush->mtex.tex) ? 1 : 0; @@ -4907,13 +5070,6 @@ static int texture_paint_init(bContext *C, wmOperator *op) pop->first = 1; op->customdata = pop; - - /* XXX: Soften tool does not support projection painting atm, so just disable - * projection for this brush */ - if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) { - settings->imapaint.flag |= IMAGEPAINT_PROJECT_DISABLE; - pop->restore_projection = 1; - } /* initialize from context */ if (CTX_wm_region_view3d(C)) { @@ -5766,7 +5922,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) } ps.reproject_image = image; - ps.reproject_ibuf = BKE_image_get_ibuf(image, NULL); + ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ps.reproject_ibuf == NULL || ps.reproject_ibuf->rect == NULL) { BKE_report(op->reports, RPT_ERROR, "Image data could not be found"); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 6396a0c2cbc..9ebeb61a7bb 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -195,7 +195,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev /* Returns zero if no sculpt changes should be made, non-zero otherwise */ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], - const PaintSample *sample) + const PaintSample *sample) { output[0] = sample->mouse[0]; output[1] = sample->mouse[1]; diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index c5eff1a1f0e..cb4b6346c2a 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -257,8 +257,8 @@ void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const in /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } minabsw = 1e10; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 56d46a22e10..94b00101dc2 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -125,9 +125,11 @@ static void update_tessface_data(Object *ob, Mesh *me) if (!me->mcol || !me->mface) { /* should always be true */ /* XXX Why this clearing? tessface_calc will reset it anyway! */ -/* if (me->mcol) {*/ -/* memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);*/ -/* }*/ +#if 0 + if (me->mcol) { + memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface); + } +#endif /* create tessfaces because they will be used for drawing & fast updates */ BKE_mesh_tessface_calc(me); /* does own call to update pointers */ diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 38dbdcd8337..e2ed7776b7e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3356,7 +3356,10 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio sculpt_init_mirror_clipping(ob, ss); /* Initial mouse location */ - copy_v2_v2(ss->cache->initial_mouse, mouse); + if (mouse) + copy_v2_v2(ss->cache->initial_mouse, mouse); + else + zero_v2(ss->cache->initial_mouse); mode = RNA_enum_get(op->ptr, "mode"); cache->invert = mode == BRUSH_STROKE_INVERT; @@ -3761,6 +3764,7 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]) mval[0] = mouse[0] - vc.ar->winrct.xmin; mval[1] = mouse[1] - vc.ar->winrct.ymin; + /* TODO: what if the segment is totally clipped? (return == 0) */ ED_view3d_win_to_segment_clip(vc.ar, vc.v3d, mval, ray_start, ray_end); invert_m4_m4(obimat, ob->obmat); @@ -3890,8 +3894,8 @@ static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2]) { /* Don't start the stroke until mouse goes over the mesh. - * note: event will only be null when re-executing the saved stroke. */ - if (over_mesh(C, op, mouse[0], mouse[1])) { + * note: mouse will only be null when re-executing the saved stroke. */ + if (!mouse || over_mesh(C, op, mouse[0], mouse[1])) { Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index ae78b71f2ad..a80d425b90a 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -52,6 +52,7 @@ #include "BKE_action.h" #include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_report.h" @@ -493,7 +494,7 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* copy keyframes */ - if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { + if (ac.datatype == ANIMCONT_GPENCIL) { /* FIXME... */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil mode"); return OPERATOR_CANCELLED; @@ -1308,6 +1309,15 @@ void ACTION_OT_keyframe_type(wmOperatorType *ot) /* ***************** Jump to Selected Frames Operator *********************** */ +static int actkeys_framejump_poll(bContext *C) +{ + /* prevent changes during render */ + if (G.is_rendering) + return 0; + + return ED_operator_action_active(C); +} + /* snap current-frame indicator to 'average time' of selected keyframe */ static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1361,7 +1371,7 @@ void ACTION_OT_frame_jump(wmOperatorType *ot) /* api callbacks */ ot->exec = actkeys_framejump_exec; - ot->poll = ED_operator_action_active; + ot->poll = actkeys_framejump_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1412,15 +1422,20 @@ static void snap_action_keys(bAnimContext *ac, short mode) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); - if (adt) { + if (ale->type == ANIMTYPE_GPLAYER) { + ED_gplayer_snap_frames(ale->data, ac->scene, mode); + } + else if (ale->type == ANIMTYPE_MASKLAYER) { + ED_masklayer_snap_frames(ale->data, ac->scene, mode); + } + else if (adt) { ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } - //else if (ale->type == ACTTYPE_GPLAYER) - // snap_gplayer_frames(ale->data, mode); - else + else { ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); + } } BLI_freelistN(&anim_data); @@ -1436,11 +1451,7 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - - /* XXX... */ - if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) - return OPERATOR_PASS_THROUGH; - + /* get snapping mode */ mode = RNA_enum_get(op->ptr, "type"); @@ -1448,7 +1459,8 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op) snap_action_keys(&ac, mode); /* validate keyframes after editing */ - ANIM_editkeyframes_refresh(&ac); + if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) + ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 9c47c407bd9..2a5b64cd6ed 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -680,9 +680,9 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts) /************************* Context Callback ************************/ const char *buttons_context_dir[] = { - "world", "object", "mesh", "armature", "lattice", "curve", + "texture_slot", "world", "object", "mesh", "armature", "lattice", "curve", "meta_ball", "lamp", "speaker", "camera", "material", "material_slot", - "texture", "texture_slot", "texture_user", "bone", "edit_bone", + "texture", "texture_user", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable", "particle_settings", "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint", NULL }; @@ -697,7 +697,12 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r /* here we handle context, getting data from precomputed path */ if (CTX_data_dir(member)) { - CTX_data_dir_set(result, buttons_context_dir); + /* in case of new shading system we skip texture_slot, complex python + * UI script logic depends on checking if this is available */ + if (sbuts->texuser) + CTX_data_dir_set(result, buttons_context_dir + 1); + else + CTX_data_dir_set(result, buttons_context_dir); return 1; } else if (CTX_data_equals(member, "world")) { @@ -817,12 +822,12 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r ButsContextTexture *ct = sbuts->texuser; PointerRNA *ptr; - if (ct) - return 0; /* new shading system */ - if ((ptr = get_pointer_type(path, &RNA_Material))) { Material *ma = ptr->data; + if (ct) + return 0; /* new shading system */ + /* if we have a node material, get slot from material in material node */ if (ma && ma->use_nodes && ma->nodetree) { /* if there's an active texture node in the node tree, @@ -843,12 +848,18 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r else if ((ptr = get_pointer_type(path, &RNA_Lamp))) { Lamp *la = ptr->data; + if (ct) + return 0; /* new shading system */ + if (la) CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]); } else if ((ptr = get_pointer_type(path, &RNA_World))) { World *wo = ptr->data; + if (ct) + return 0; /* new shading system */ + if (wo) CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]); } diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 0e82d8651f3..abfefba02b9 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -248,7 +248,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext * void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts) { - /* gatheravailable texture users in context. runs on every draw of + /* gather available texture users in context. runs on every draw of * properties editor, before the buttons are created. */ ButsContextTexture *ct = sbuts->texuser; Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 09ad7312123..c98d213e949 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -297,6 +297,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) buttons_area_redraw(sa, BCONTEXT_PHYSICS); case ND_SHADING: case ND_SHADING_DRAW: + case ND_SHADING_LINKS: /* currently works by redraws... if preview is set, it (re)starts job */ sbuts->preview = 1; break; @@ -319,6 +320,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) switch (wmn->data) { case ND_SHADING: case ND_SHADING_DRAW: + case ND_SHADING_LINKS: case ND_NODES: /* currently works by redraws... if preview is set, it (re)starts job */ sbuts->preview = 1; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index a2e4da719e9..9cf389c4508 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -252,7 +252,6 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy) { int x, y; - MovieClip *clip = ED_space_clip_get_clip(sc); /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); @@ -306,6 +305,15 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, IMB_display_buffer_release(cache_handle); } +} + +static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy) +{ + int x, y; + MovieClip *clip = ED_space_clip_get_clip(sc); + + /* find window pixel coordinates of origin */ + UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); /* draw boundary border for frame if stabilization is enabled */ if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) { @@ -1276,7 +1284,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, BKE_tracking_undistort_v2(tracking, pos, tpos); - DO_MINMAX2(tpos, min, max); + minmax_v2v2_v2(min, max, tpos); } copy_v2_v2(pos, min); @@ -1469,6 +1477,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) } if (width && height) { + draw_stabilization_border(sc, ar, width, height, zoomx, zoomy); draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy); draw_distortion(sc, ar, clip, width, height, zoomx, zoomy); } @@ -1488,7 +1497,7 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) if (onlyv2d) { /* if manual calibration is used then grease pencil data is already - * drawed in draw_distortion */ + * drawn in draw_distortion */ if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || sc->mode != SC_MODE_DISTORTION) { glPushMatrix(); glMultMatrixf(sc->unistabmat); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 71589517c83..1a62af39600 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -349,7 +349,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) mul_v3_m4v3(pos, sc->stabmat, pos); - DO_MINMAX2(pos, min, max); + minmax_v2v2_v2(min, max, pos); ok = TRUE; } diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 9ec2ad82bef..4e53f34359e 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1065,7 +1065,7 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) if (clip->anim) { pj->index_context = IMB_anim_index_rebuild_context(clip->anim, clip->proxy.build_tc_flag, - clip->proxy.build_size_flag, clip->proxy.quality); + clip->proxy.build_size_flag, clip->proxy.quality); } WM_jobs_customdata_set(wm_job, pj, proxy_freejob); diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index ddc624b4cdf..d7a9b1c0cb6 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -63,11 +63,12 @@ #include "clip_intern.h" // own include -void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack *track, void *userdata, - void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, - int scene_framenr, float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), - void (*segment_end)(void *userdata)) +void clip_graph_tracking_values_iterate_track( + SpaceClip *sc, MovieTrackingTrack *track, void *userdata, + void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, + int scene_framenr, float val), + void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), + void (*segment_end)(void *userdata)) { MovieClip *clip = ED_space_clip_get_clip(sc); int width, height, coord; @@ -122,11 +123,12 @@ void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack } } -void clip_graph_tracking_values_iterate(SpaceClip *sc, int selected_only, int include_hidden, void *userdata, - void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int coord, int scene_framenr, float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), - void (*segment_end)(void *userdata)) +void clip_graph_tracking_values_iterate( + SpaceClip *sc, int selected_only, int include_hidden, void *userdata, + void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int coord, int scene_framenr, float val), + void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), + void (*segment_end)(void *userdata)) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index ffe4762ad15..77e2a1bb3d3 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1028,17 +1028,14 @@ static void clip_refresh(const bContext *C, ScrArea *sa) static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar) { SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip_get_clip(sc); - float x1, y1, w, h; + float x1, y1, w, h, aspx, aspy; int width, height, winx, winy; ED_space_clip_get_size(sc, &width, &height); + ED_space_clip_get_aspect(sc, &aspx, &aspy); - w = width; - h = height; - - if (clip) - h *= clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect; + w = width * aspx; + h = height * aspy; winx = BLI_rcti_size_x(&ar->winrct) + 1; winy = BLI_rcti_size_y(&ar->winrct) + 1; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index dd939d57cbe..a29524de36d 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1409,7 +1409,7 @@ static void solve_camera_freejob(void *scv) id_us_plus(&clip->id); /* set blender camera focal length so result would look fine there */ - if (scene->camera && GS(scene->camera->id.name) == ID_CA) { + if (scene->camera && scene->camera->data && GS(((ID *) scene->camera->data)->name) == ID_CA) { Camera *camera = (Camera *)scene->camera->data; int width, height; @@ -2944,6 +2944,19 @@ void CLIP_OT_track_copy_color(wmOperatorType *ot) /********************** add 2d stabilization tracks operator *********************/ +static int stabilize_2d_poll(bContext *C) +{ + if (ED_space_clip_tracking_poll(C)) { + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking); + + return tracking_object->flag & TRACKING_OBJECT_CAMERA; + } + + return FALSE; +} + static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -2985,7 +2998,7 @@ void CLIP_OT_stabilize_2d_add(wmOperatorType *ot) /* api callbacks */ ot->exec = stabilize_2d_add_exec; - ot->poll = ED_space_clip_tracking_poll; + ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3045,7 +3058,7 @@ void CLIP_OT_stabilize_2d_remove(wmOperatorType *ot) /* api callbacks */ ot->exec = stabilize_2d_remove_exec; - ot->poll = ED_space_clip_tracking_poll; + ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3088,7 +3101,7 @@ void CLIP_OT_stabilize_2d_select(wmOperatorType *ot) /* api callbacks */ ot->exec = stabilize_2d_select_exec; - ot->poll = ED_space_clip_tracking_poll; + ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3125,7 +3138,7 @@ void CLIP_OT_stabilize_2d_set_rotation(wmOperatorType *ot) /* api callbacks */ ot->exec = stabilize_2d_set_rotation_exec; - ot->poll = ED_space_clip_tracking_poll; + ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index f19835b7f85..a215b476094 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -146,7 +146,8 @@ static int console_textview_line_get(struct TextViewContext *tvc, const char **l ConsoleLine *cl = (ConsoleLine *)tvc->iter; *line = cl->line; *len = cl->len; - + // printf("'%s' %d\n", *line, cl->len); + BLI_assert(cl->line[cl->len] == '\0' && (cl->len == 0 || cl->line[cl->len - 1] != '\0')); return 1; } diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index d3ae5373a18..36716aeab95 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -157,10 +157,9 @@ static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from) ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add"); if (from) { - ci->line = BLI_strdup(from->line); - ci->len = strlen(ci->line); - ci->len_alloc = ci->len; - + BLI_assert(strlen(from->line) == from->len); + ci->line = BLI_strdupn(from->line, from->len); + ci->len = ci->len_alloc = from->len; ci->cursor = from->cursor; ci->type = from->type; } @@ -174,10 +173,8 @@ static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from) return ci; } -static ConsoleLine *console_history_add(const bContext *C, ConsoleLine *from) +static ConsoleLine *console_history_add(SpaceConsole *sc, ConsoleLine *from) { - SpaceConsole *sc = CTX_wm_space_console(C); - return console_lb_add__internal(&sc->history, from); } @@ -217,7 +214,7 @@ ConsoleLine *console_history_verify(const bContext *C) SpaceConsole *sc = CTX_wm_space_console(C); ConsoleLine *ci = sc->history.last; if (ci == NULL) - ci = console_history_add(C, NULL); + ci = console_history_add(sc, NULL); return ci; } @@ -447,7 +444,7 @@ static int console_indent_exec(bContext *C, wmOperator *UNUSED(op)) console_line_verify_length(ci, ci->len + len); - memmove(ci->line + len, ci->line, ci->len); + memmove(ci->line + len, ci->line, ci->len + 1); memset(ci->line, ' ', len); ci->len += len; BLI_assert(ci->len >= 0); @@ -623,8 +620,9 @@ static int console_clear_line_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - console_history_add(C, ci); - console_history_add(C, NULL); + console_history_add(sc, ci); + console_history_add(sc, NULL); + console_select_offset(sc, -ci->len); console_textview_update_rect(sc, ar); @@ -727,7 +725,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op) while ((cl = console_history_find(sc, ci->line, ci))) console_history_free(sc, cl); - console_history_add(C, (ConsoleLine *)sc->history.last); + console_history_add(sc, (ConsoleLine *)sc->history.last); } ci = sc->history.last; diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 75add570708..be8febdab23 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -170,16 +170,13 @@ static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event static void id_drop_copy(wmDrag *drag, wmDropBox *drop) { - char text[64]; + char *text; ID *id = drag->poin; - char id_esc[(sizeof(id->name) - 2) * 2]; - - BLI_strescape(id_esc, id->name + 2, sizeof(id_esc)); - - BLI_snprintf(text, sizeof(text), "bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id_esc); /* copy drag path to properties */ + text = RNA_path_from_ID_python(id); RNA_string_set(drop->ptr, "text", text); + MEM_freeN(text); } static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 8f94086013c..a49b75477e4 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -744,6 +744,7 @@ void filelist_setfilter_types(struct FileList *filelist, const char *filter_glob BLI_strncpy(filelist->filter_glob, filter_glob, sizeof(filelist->filter_glob)); } +/* would recognize .blend as well */ static int file_is_blend_backup(const char *str) { short a, b; diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 49562958f82..778a3f4df3e 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -164,6 +164,8 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->filter = 0; if (RNA_struct_find_property(op->ptr, "filter_blender")) params->filter |= RNA_boolean_get(op->ptr, "filter_blender") ? BLENDERFILE : 0; + if (RNA_struct_find_property(op->ptr, "filter_backup")) + params->filter |= RNA_boolean_get(op->ptr, "filter_backup") ? BLENDERFILE_BACKUP : 0; if (RNA_struct_find_property(op->ptr, "filter_image")) params->filter |= RNA_boolean_get(op->ptr, "filter_image") ? IMAGEFILE : 0; if (RNA_struct_find_property(op->ptr, "filter_movie")) diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 8bb57a32090..483348db18e 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -714,7 +714,17 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) row = uiLayoutRow(box, TRUE); uiItemL(row, IFACE_("Value:"), ICON_NONE); - BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); + if ((dvar->type == DVAR_TYPE_ROT_DIFF) || + (dvar->type == DVAR_TYPE_TRANSFORM_CHAN && + dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX && + dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX)) + { + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval)); + } + else { + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); + } + uiItemL(row, valBuf, ICON_NONE); } } diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 453549ebf79..21b0ed99f0b 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -56,6 +56,7 @@ #include "BLF_translation.h" #include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_report.h" @@ -1763,6 +1764,15 @@ void GRAPH_OT_euler_filter(wmOperatorType *ot) /* ***************** Jump to Selected Frames Operator *********************** */ +static int graphkeys_framejump_poll(bContext *C) +{ + /* prevent changes during render */ + if (G.is_rendering) + return 0; + + return graphop_visible_keyframes_poll(C); +} + /* snap current-frame indicator to 'average time' of selected keyframe */ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1829,7 +1839,7 @@ void GRAPH_OT_frame_jump(wmOperatorType *ot) /* api callbacks */ ot->exec = graphkeys_framejump_exec; - ot->poll = graphop_visible_keyframes_poll; + ot->poll = graphkeys_framejump_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 9b031c015a9..54b417e740a 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -39,6 +39,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_global.h" #include "BKE_main.h" #include "BKE_sound.h" @@ -66,6 +67,15 @@ * 2) Value Indicator (stored per Graph Editor instance) */ +static int graphview_cursor_poll(bContext *C) +{ + /* prevent changes during render */ + if (G.is_rendering) + return 0; + + return ED_operator_graphedit_active(C); +} + /* Set the new frame number */ static void graphview_cursor_apply(bContext *C, wmOperator *op) { @@ -172,7 +182,7 @@ static void GRAPH_OT_cursor_set(wmOperatorType *ot) ot->exec = graphview_cursor_exec; ot->invoke = graphview_cursor_invoke; ot->modal = graphview_cursor_modal; - ot->poll = ED_operator_graphedit_active; + ot->poll = graphview_cursor_poll; /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index f41169b6c39..fa7c6bd472a 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -563,13 +563,13 @@ static void graph_refresh(const bContext *C, ScrArea *sa) switch (fcu->array_index) { case 0: - col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f; + UI_GetThemeColor3fv(TH_AXIS_X, col); break; case 1: - col[0] = 0.0f; col[1] = 1.0f; col[2] = 0.0f; + UI_GetThemeColor3fv(TH_AXIS_Y, col); break; case 2: - col[0] = 0.0f; col[1] = 0.0f; col[2] = 1.0f; + UI_GetThemeColor3fv(TH_AXIS_Z, col); break; default: /* 'unknown' color - bluish so as to not conflict with handles */ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index ae7a718ab5b..0a3db59096a 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -593,7 +593,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char if (ima->source == IMA_SRC_VIEWER) { ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); uiItemL(layout, ima->id.name + 2, ICON_NONE); uiItemL(layout, str, ICON_NONE); @@ -663,7 +663,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char if (compact == 0) { ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); uiItemL(layout, str, ICON_NONE); } } @@ -722,7 +722,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, TRUE); - uiLayoutSetEnabled(col, 0); uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 9fc2b981547..d565e6f9e9a 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -652,7 +652,7 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int if (!brush || !brush->clone.image) return NULL; - ibuf = BKE_image_get_ibuf(brush->clone.image, NULL); + ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL); if (!ibuf) return NULL; @@ -660,6 +660,7 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (!display_buffer) { + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); IMB_display_buffer_release(cache_handle); return NULL; @@ -669,8 +670,10 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int IMB_display_buffer_release(cache_handle); - if (!rect) + if (!rect) { + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); return NULL; + } *width = ibuf->x; *height = ibuf->y; @@ -684,6 +687,8 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int cp += 4; } + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); + return rect; } @@ -799,7 +804,7 @@ void draw_image_main(const bContext *C, ARegion *ar) } #endif - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); if (show_viewer) { BLI_unlock_thread(LOCK_DRAW_IMAGE); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 4ca2f8888f8..c4e2230e7a7 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -117,8 +117,12 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) #endif ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r); - if (ibuf && (ibuf->rect || ibuf->rect_float)) - return ibuf; + if (ibuf) { + if (ibuf->rect || ibuf->rect_float) + return ibuf; + + BKE_image_release_ibuf(sima->image, ibuf, NULL); + } } else *lock_r = NULL; @@ -126,10 +130,10 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) return NULL; } -void ED_space_image_release_buffer(SpaceImage *sima, void *lock) +void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock) { if (sima && sima->image) - BKE_image_release_ibuf(sima->image, lock); + BKE_image_release_ibuf(sima->image, ibuf, lock); } int ED_space_image_has_buffer(SpaceImage *sima) @@ -140,7 +144,7 @@ int ED_space_image_has_buffer(SpaceImage *sima) ibuf = ED_space_image_acquire_buffer(sima, &lock); has_buffer = (ibuf != NULL); - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return has_buffer; } @@ -175,7 +179,7 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) *height = IMG_SIZE_FALLBACK; } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } void ED_space_image_get_size_fl(SpaceImage *sima, float size[2]) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index ce3c6e1fd26..0d0fdc6be1c 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -81,6 +81,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "PIL_time.h" + #include "image_intern.h" /******************** view navigation utilities *********************/ @@ -167,7 +169,7 @@ static int space_image_file_exists_poll(bContext *C) ret = TRUE; } } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return ret; } @@ -367,10 +369,18 @@ void IMAGE_OT_view_pan(wmOperatorType *ot) /********************** view zoom operator *********************/ typedef struct ViewZoomData { - float x, y; + float origx, origy; float zoom; int event_type; float location[2]; + + /* needed for continuous zoom */ + wmTimer *timer; + double timer_lastdraw; + + /* */ + SpaceImage *sima; + ARegion *ar; } ViewZoomData; static void image_view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) @@ -382,13 +392,22 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData"); WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR); - vpd->x = event->x; - vpd->y = event->y; + vpd->origx = event->x; + vpd->origy = event->y; vpd->zoom = sima->zoom; vpd->event_type = event->type; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]); + if (U.viewzoom == USER_ZOOM_CONT) { + /* needs a timer to continue redrawing */ + vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); + vpd->timer_lastdraw = PIL_check_seconds_timer(); + } + + vpd->sima = sima; + vpd->ar = ar; + WM_event_add_modal_handler(C, op); } @@ -402,6 +421,9 @@ static void image_view_zoom_exit(bContext *C, wmOperator *op, int cancel) ED_region_tag_redraw(CTX_wm_region(C)); } + if (vpd->timer) + WM_event_remove_timer(CTX_wm_manager(C), vpd->timer->win, vpd->timer); + WM_cursor_restore(CTX_wm_window(C)); MEM_freeN(op->customdata); } @@ -427,6 +449,12 @@ static int image_view_zoom_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +enum { + VIEW_PASS = 0, + VIEW_APPLY, + VIEW_CONFIRM +}; + static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) { if (event->type == MOUSEZOOM) { @@ -454,31 +482,72 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) } } +static void image_zoom_apply(ViewZoomData *vpd, wmOperator *op, const int x, const int y, const short viewzoom, const short zoom_invert) +{ + float factor; + + if (viewzoom == USER_ZOOM_CONT) { + double time = PIL_check_seconds_timer(); + float time_step = (float)(time - vpd->timer_lastdraw); + float fac; + float zfac; + + if (U.uiflag & USER_ZOOM_HORIZ) { + fac = (float)(x - vpd->origx); + } + else { + fac = (float)(y - vpd->origy); + } + + if (zoom_invert) { + fac = -fac; + } + + /* oldstyle zoom */ + zfac = 1.0f + ((fac / 20.0f) * time_step); + vpd->timer_lastdraw = time; + /* this is the final zoom, but instead make it into a factor */ + //zoom = vpd->sima->zoom * zfac; + factor = (vpd->sima->zoom * zfac) / vpd->zoom; + } + else { + /* for now do the same things for scale and dolly */ + float delta = x - vpd->origx + y - vpd->origy; + + if (zoom_invert) + delta *= -1.0f; + + factor = 1.0f + delta / 300.0f; + } + + RNA_float_set(op->ptr, "factor", factor); + sima_zoom_set(vpd->sima, vpd->ar, vpd->zoom * factor, vpd->location); + ED_region_tag_redraw(vpd->ar); +} + static int image_view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) { - SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); ViewZoomData *vpd = op->customdata; - float delta, factor; + short event_code = VIEW_PASS; - switch (event->type) { - case MOUSEMOVE: - delta = event->x - vpd->x + event->y - vpd->y; + /* execute the events */ + if (event->type == TIMER && event->customdata == vpd->timer) { + /* continuous zoom */ + event_code = VIEW_APPLY; + } + else if (event->type == MOUSEMOVE) { + event_code = VIEW_APPLY; + } + else if (event->type == vpd->event_type && event->val == KM_RELEASE) { + event_code = VIEW_CONFIRM; + } - if (U.uiflag & USER_ZOOM_INVERT) - delta *= -1; - - factor = 1.0f + delta / 300.0f; - RNA_float_set(op->ptr, "factor", factor); - sima_zoom_set(sima, ar, vpd->zoom * factor, vpd->location); - ED_region_tag_redraw(CTX_wm_region(C)); - break; - default: - if (event->type == vpd->event_type && event->val == KM_RELEASE) { - image_view_zoom_exit(C, op, 0); - return OPERATOR_FINISHED; - } - break; + if (event_code == VIEW_APPLY) { + image_zoom_apply(vpd, op, event->x, event->y, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0); + } + else if (event_code == VIEW_CONFIRM) { + image_view_zoom_exit(C, op, 0); + return OPERATOR_FINISHED; } return OPERATOR_RUNNING_MODAL; @@ -1188,7 +1257,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return (ibuf != NULL); } @@ -1328,7 +1397,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI IMB_freeImBuf(colormanaged_ibuf); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } static void image_save_as_free(wmOperator *op) @@ -1743,17 +1812,14 @@ void IMAGE_OT_new(wmOperatorType *ot) static int image_invert_poll(bContext *C) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); - - if (ibuf != NULL) - return 1; - return 0; + + return BKE_image_has_ibuf(ima, NULL); } static int image_invert_exec(bContext *C, wmOperator *op) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); /* flags indicate if this channel should be inverted */ const short r = RNA_boolean_get(op->ptr, "invert_r"); @@ -1792,6 +1858,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) } } else { + BKE_image_release_ibuf(ima, ibuf, NULL); return OPERATOR_CANCELLED; } @@ -1800,6 +1867,9 @@ static int image_invert_exec(bContext *C, wmOperator *op) ibuf->userflags |= IB_MIPMAP_INVALID; WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_FINISHED; } @@ -1848,7 +1918,7 @@ static int image_pack_exec(bContext *C, wmOperator *op) { struct Main *bmain = CTX_data_main(C); Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); int as_png = RNA_boolean_get(op->ptr, "as_png"); if (!image_pack_test(C, op)) @@ -1865,30 +1935,38 @@ static int image_pack_exec(bContext *C, wmOperator *op) ima->packedfile = newPackedFile(op->reports, ima->name, ID_BLEND_PATH(bmain, &ima->id)); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); - + + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_FINISHED; } static int image_pack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf; uiPopupMenu *pup; uiLayout *layout; int as_png = RNA_boolean_get(op->ptr, "as_png"); if (!image_pack_test(C, op)) return OPERATOR_CANCELLED; - + + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { pup = uiPupMenuBegin(C, "OK", ICON_QUESTION); layout = uiPupMenuLayout(pup); uiItemBooleanO(layout, "Can't pack edited image from disk. Pack as internal PNG?", ICON_NONE, op->idname, "as_png", 1); uiPupMenuEnd(C, pup); + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_CANCELLED; } + BKE_image_release_ibuf(ima, ibuf, NULL); + return image_pack_exec(C, op); } @@ -2032,7 +2110,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa int ret = FALSE; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return FALSE; } @@ -2058,7 +2136,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa } } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return ret; } @@ -2074,7 +2152,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) CurveMapping *curve_mapping = scene->view_settings.curve_mapping; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); info->draw = 0; return; } @@ -2175,7 +2253,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->draw = 0; } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); } @@ -2266,12 +2344,12 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) float x1f, y1f, x2f, y2f; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return OPERATOR_CANCELLED; } /* hmmmm */ if (ibuf->channels < 3) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return OPERATOR_CANCELLED; } @@ -2288,7 +2366,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) /* reset y zoom */ hist->ymax = 1.0f; - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); @@ -2383,11 +2461,13 @@ static int image_record_composite_apply(bContext *C, wmOperator *op) ED_area_tag_redraw(CTX_wm_area(C)); - ibuf = BKE_image_get_ibuf(sima->image, &sima->iuser); + ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, NULL); /* save memory in flipbooks */ if (ibuf) imb_freerectfloatImBuf(ibuf); - + + BKE_image_release_ibuf(sima->image, ibuf, NULL); + scene->r.cfra++; return (scene->r.cfra <= rcd->efra); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 4131cbfdd0d..ea696772957 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -780,7 +780,7 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar) } scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_region_panels(C, ar, 1, NULL, -1); } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 131908bc9db..48b5eaf7b44 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -87,10 +87,14 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) // first check for dirty images for (ima = bmain->image.first; ima; ima = ima->id.next) { if (ima->ibufs.first) { /* XXX FIX */ - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) + if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { + BKE_image_release_ibuf(ima, ibuf, NULL); break; + } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index f108881091a..cba0a808d63 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -58,6 +58,7 @@ #include "UI_view2d.h" #include "info_intern.h" /* own include */ +#include "BLO_readfile.h" /* ******************** default callbacks for info space ***************** */ @@ -271,11 +272,16 @@ static void info_header_listener(ARegion *ar, wmNotifier *wmn) static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu) { struct RecentFile *recent; + char file [FILE_MAX]; uiLayout *layout = menu->layout; uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN); if (G.recent_files.first) { for (recent = G.recent_files.first; (recent); recent = recent->next) { - uiItemStringO(layout, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath); + BLI_split_file_part(recent->filepath, file, sizeof(file)); + if (BLO_has_bfile_extension(file)) + uiItemStringO(layout, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath); + else + uiItemStringO(layout, BLI_path_basename(recent->filepath), ICON_FILE_BACKUP, "WM_OT_open_mainfile", "filepath", recent->filepath); } } else { diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 0938562857b..92edac356e6 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -108,6 +108,43 @@ static void node_socket_button_default(const bContext *C, uiBlock *block, } } +static void node_socket_button_string(const bContext *C, uiBlock *block, + bNodeTree *ntree, bNode *node, bNodeSocket *sock, + const char *name, int x, int y, int width) +{ + if (sock->link || (sock->flag & SOCK_HIDE_VALUE)) + node_socket_button_label(C, block, ntree, node, sock, name, x, y, width); + else { + PointerRNA ptr; + uiBut *bt; + + SpaceNode *snode = CTX_wm_space_node(C); + const char *ui_name = IFACE_(name); + float slen; + + UI_ThemeColor(TH_TEXT); + slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt; + while (slen > (width * 0.5f) && *ui_name) { + ui_name = BLI_str_find_next_char_utf8(ui_name, NULL); + slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt; + } + + RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr); + + if (name[0] == '\0') + slen = 0.0; + + bt = uiDefButR(block, TEX, B_NODE_EXEC, "", + x, y + 1, width - slen, NODE_DY - 2, + &ptr, "default_value", 0, 0, 0, -1, -1, ""); + if (node) + uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node); + + if (slen > 0.0f) + uiDefBut(block, LABEL, 0, IFACE_(name), x + (width - slen), y + 2, slen, NODE_DY - 2, NULL, 0, 0, 0, 0, ""); + } +} + typedef struct SocketComponentMenuArgs { PointerRNA ptr; int x, y, width; @@ -209,9 +246,9 @@ static void node_draw_output_default(const bContext *C, uiBlock *block, if (*ui_name) { uiDefBut(block, LABEL, 0, ui_name, - (int)(sock->locx - slen), (int)(sock->locy - 9.0f), - (short)slen, (short)NODE_DY, - NULL, 0, 0, 0, 0, ""); + (int)(sock->locx - slen), (int)(sock->locy - 9.0f), + (short)slen, (short)NODE_DY, + NULL, 0, 0, 0, 0, ""); } } @@ -282,7 +319,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr); col = uiLayoutColumn(layout, FALSE); - uiTemplateColorWheel(col, &sockptr, "default_value", 1, 0, 0, 0); + uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0); uiItemR(col, &sockptr, "default_value", 0, "", ICON_NONE); } @@ -361,29 +398,15 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0, 0); } -static void node_normal_cb(bContext *C, void *ntree_v, void *node_v) -{ - Main *bmain = CTX_data_main(C); - - ED_node_generic_update(bmain, ntree_v, node_v); - WM_event_add_notifier(C, NC_NODE | NA_EDITED, ntree_v); -} - static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiBlock *block = uiLayoutAbsoluteBlock(layout); - bNodeTree *ntree = ptr->id.data; - bNode *node = ptr->data; - rctf *butr = &node->butr; + bNodeTree *ntree = (bNodeTree*)ptr->id.data; + bNode *node = (bNode*)ptr->data; bNodeSocket *sock = node->outputs.first; /* first socket stores normal */ - float *nor = ((bNodeSocketValueVector *)sock->default_value)->value; - uiBut *bt; - - bt = uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "", - (int)butr->xmin, (int)butr->xmin, - (short)BLI_rctf_size_x(butr), (short)BLI_rctf_size_x(butr), - nor, 0.0f, 1.0f, 0, 0, ""); - uiButSetFunc(bt, node_normal_cb, ntree, node); + PointerRNA sockptr; + + RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr); + uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); } #if 0 /* not used in 2.5x yet */ static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v) @@ -486,8 +509,9 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode) bNodeSocket *sock, *gsock; float locx, locy; rctf *rect = &gnode->totr; - float node_group_frame = U.dpi * NODE_GROUP_FRAME / 72; - float group_header = 26 * U.dpi / 72; + const float dpi_fac = UI_DPI_ICON_FAC; + const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; + const float group_header = 26 * dpi_fac; int counter; int dy; @@ -664,7 +688,7 @@ static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket * static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode, bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out) { - const float dpi_fac = U.dpi / 72.0f; + const float dpi_fac = UI_DPI_ICON_FAC; bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type); uiBut *bt; @@ -776,9 +800,9 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN uiLayout *layout; PointerRNA ptr; rctf rect = gnode->totr; - const float dpi_fac = U.dpi / 72.0f; - float node_group_frame = NODE_GROUP_FRAME * dpi_fac; - float group_header = 26 * dpi_fac; + const float dpi_fac = UI_DPI_ICON_FAC; + const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; + const float group_header = 26 * dpi_fac; int index; @@ -1379,6 +1403,46 @@ static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), Po uiItemR(layout, ptr, "from_dupli", 0, NULL, 0); } +static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "space", 0, "", 0); + + if (RNA_enum_get(ptr, "space") == SHD_NORMAL_MAP_TANGENT) { + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + } + else + uiItemR(layout, ptr, "uv_map", 0, "", 0); + } +} + +static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiLayout *split, *row; + + split = uiLayoutSplit(layout, 0.0f, FALSE); + + uiItemR(split, ptr, "direction_type", 0, "", 0); + + row = uiLayoutRow(split, FALSE); + + if (RNA_enum_get(ptr, "direction_type") == SHD_TANGENT_UVMAP) { + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + } + else + uiItemR(row, ptr, "uv_map", 0, "", 0); + } + else + uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0); +} + static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); @@ -1407,9 +1471,10 @@ static void node_shader_buts_script_details(uiLayout *layout, bContext *C, Point node_shader_buts_script(layout, C, ptr); - /* not implemented yet - if(RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) - uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE);*/ +#if 0 /* not implemented yet */ + if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) + uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE); +#endif } /* only once called */ @@ -1491,8 +1556,15 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_TEX_COORD: ntype->uifunc = node_shader_buts_tex_coord; break; + case SH_NODE_NORMAL_MAP: + ntype->uifunc = node_shader_buts_normal_map; + break; + case SH_NODE_TANGENT: + ntype->uifunc = node_shader_buts_tangent; + break; case SH_NODE_BSDF_GLOSSY: case SH_NODE_BSDF_GLASS: + case SH_NODE_BSDF_REFRACTION: ntype->uifunc = node_shader_buts_glossy; break; case SH_NODE_SCRIPT: @@ -1802,6 +1874,14 @@ static void node_composit_buts_double_edge_mask(uiLayout *layout, bContext *UNUS uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE); } +static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col; + + col = uiLayoutColumn(layout, TRUE); + uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); +} + static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *sub, *col; @@ -2173,17 +2253,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "lift", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "gamma", 1, 1, 1, 1); + uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "gain", 1, 1, 1, 1); + uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE); @@ -2192,17 +2272,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "offset", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "power", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "power", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "slope", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE); } @@ -2214,23 +2294,23 @@ static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUS if (RNA_enum_get(ptr, "correction_method") == 0) { - uiTemplateColorWheel(layout, ptr, "lift", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1); uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "gamma", 1, 1, 1, 1); + uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1); uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "gain", 1, 1, 1, 1); + uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1); uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE); } else { - uiTemplateColorWheel(layout, ptr, "offset", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1); uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "power", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1); uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "slope", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1); uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE); } } @@ -2740,6 +2820,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_MAP_VALUE: ntype->uifunc = node_composit_buts_map_value; break; + case CMP_NODE_MAP_RANGE: + ntype->uifunc = node_composit_buts_map_range; + break; case CMP_NODE_TIME: ntype->uifunc = node_buts_time; break; @@ -3089,6 +3172,9 @@ void ED_node_init_butfuncs(void) case SOCK_BOOLEAN: stype->buttonfunc = node_socket_button_default; break; + case SOCK_STRING: + stype->buttonfunc = node_socket_button_string; + break; case SOCK_VECTOR: stype->buttonfunc = node_socket_button_components; break; @@ -3214,7 +3300,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) glPopMatrix(); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } } @@ -3227,7 +3313,7 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) if (snode->flag & SNODE_BACKDRAW) { Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf) { int x, y; float zoom = 1.0; @@ -3263,6 +3349,8 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 04d2947ce89..96ac716f383 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -386,6 +386,9 @@ static int node_add_file_exec(bContext *C, wmOperator *op) node->id = (ID *)ima; id_us_plus(node->id); + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + snode_notify(C, snode); snode_dag_update(C, snode); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 1d3b21fe2d6..72461cfb2a8 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -843,7 +843,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b rctf *rct = &node->totr; float dx, centy = BLI_rctf_cent_y(rct); float hiddenrad = BLI_rctf_size_y(rct) / 2.0f; - float socket_size = NODE_SOCKSIZE * U.dpi / 72; + float socket_size = NODE_SOCKSIZE * UI_DPI_ICON_FAC; int color_id = node_get_colorid(node); char showname[128]; /* 128 is used below */ diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 6bf0e9f73e3..f757345bdcb 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -86,6 +86,7 @@ typedef struct CompoJob { short *stop; short *do_update; float *progress; + short need_sync; } CompoJob; /* called by compo, only to check job 'stop' value */ @@ -102,8 +103,17 @@ static int compo_breakjob(void *cjv) ); } +/* called by compo, wmJob sends notifier, old compositor system only */ +static void compo_statsdrawjob(void *cjv, char *UNUSED(str)) +{ + CompoJob *cj = cjv; + + *(cj->do_update) = TRUE; + cj->need_sync = TRUE; +} + /* called by compo, wmJob sends notifier */ -static void compo_redrawjob(void *cjv, char *UNUSED(str)) +static void compo_redrawjob(void *cjv) { CompoJob *cj = cjv; @@ -133,8 +143,15 @@ static void compo_initjob(void *cjv) static void compo_updatejob(void *cjv) { CompoJob *cj = cjv; - - ntreeLocalSync(cj->localtree, cj->ntree); + + if (cj->need_sync) { + /* was used by old compositor system only */ + ntreeLocalSync(cj->localtree, cj->ntree); + + cj->need_sync = FALSE; + } + + WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); } static void compo_progressjob(void *cjv, float progress) @@ -161,11 +178,13 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog ntree->test_break = compo_breakjob; ntree->tbh = cj; - ntree->stats_draw = compo_redrawjob; + ntree->stats_draw = compo_statsdrawjob; ntree->sdh = cj; ntree->progress = compo_progressjob; ntree->prh = cj; - + ntree->update_draw = compo_redrawjob; + ntree->udh = cj; + // XXX BIF_store_spare(); ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */ @@ -177,7 +196,7 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog } /** - * \param sa_owner is the owner of the job, + * \param scene_owner is the owner of the job, * we don't use it for anything else currently so could also be a void pointer, * but for now keep it an 'Scene' for consistency. * @@ -2226,13 +2245,13 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op) data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; if (data.text) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); + bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); if (ntreetype && ntreetype->foreach_nodetree) ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text); if (!data.found) - BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done."); + BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done"); } } diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 5f8b5db7766..4dd9c89375d 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -29,13 +29,18 @@ * \ingroup spnode */ +#include + #include "MEM_guardedalloc.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_anim_types.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_rect.h" +#include "BLI_math.h" #include "BKE_action.h" #include "BKE_animsys.h" @@ -865,7 +870,7 @@ static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, if (node == gnode) continue; if (node->flag & NODE_SELECT) { - DO_MINMAX2((&node->locx), min, max); + minmax_v2v2_v2(min, max, &node->locx); } } } diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index ccf5c4b540f..f386657c460 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -241,7 +241,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf == NULL) { - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return OPERATOR_CANCELLED; } @@ -255,7 +255,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) nvm->ymin = -(ar->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad; nvm->ymax = (ar->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad; - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -330,6 +330,12 @@ typedef struct ImageSampleInfo { unsigned char col[4]; float colf[4]; + + int z; + float zf; + + int *zp; + float *zfp; int draw; int color_manage; @@ -343,8 +349,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) if (info->draw) { ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels, info->x, info->y, info->col, info->colf, - NULL, NULL /* zbuf - unused for nodes */ - ); + info->zp, info->zfp); } } @@ -398,7 +403,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float } } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return ret; } @@ -443,6 +448,9 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->draw = 1; info->channels = ibuf->channels; + info->zp = NULL; + info->zfp = NULL; + if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); @@ -468,6 +476,15 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->color_manage = TRUE; } + + if (ibuf->zbuf) { + info->z = ibuf->zbuf[y * ibuf->x + x]; + info->zp = &info->z; + } + if (ibuf->zbuf_float) { + info->zf = ibuf->zbuf_float[y * ibuf->x + x]; + info->zfp = &info->zf; + } ED_node_sample_set(info->colf); } @@ -476,7 +493,7 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) ED_node_sample_set(NULL); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); } diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 4d2512cdc93..f7e0d51ea03 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -193,6 +193,8 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_refresh(sa); else if (wmn->data == ND_SHADING_DRAW) ED_area_tag_refresh(sa); + else if (wmn->data == ND_SHADING_LINKS) + ED_area_tag_refresh(sa); else if (wmn->action == NA_ADDED && snode->edittree) nodeSetActiveID(snode->edittree, ID_MA, wmn->reference); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index c4afe32e85f..d37cb4be8fa 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -631,7 +631,7 @@ static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi) uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 15, uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL); but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, UI_UNIT_Y, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot); @@ -1038,11 +1038,13 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_MOD_WARP); break; case eModifierType_Skin: UI_icon_draw(x, y, ICON_MOD_SKIN); break; + case eModifierType_Triangulate: + UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break; /* Default */ case eModifierType_None: case eModifierType_ShapeKey: - case NUM_MODIFIER_TYPES: + case NUM_MODIFIER_TYPES: UI_icon_draw(x, y, ICON_DOT); break; } break; diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 23766d6a6fe..d11a8ed6369 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -836,6 +836,8 @@ static int outliner_one_level_exec(bContext *C, wmOperator *op) void OUTLINER_OT_show_one_level(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Show/Hide One Level"; ot->idname = "OUTLINER_OT_show_one_level"; @@ -848,7 +850,8 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot) /* no undo or registry, UI option */ /* properties */ - RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep"); + prop = RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* Show Hierarchy ----------------------------------------------- */ @@ -1859,7 +1862,7 @@ static int material_drop_invoke(bContext *C, wmOperator *op, wmEvent *event) DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, ma); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 4668dfa1386..0b585e1272b 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -222,7 +222,7 @@ static int tree_element_active_material(bContext *C, Scene *scene, SpaceOops *so } } if (set) { - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, NULL); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); } return 0; } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index af890a81ad6..e6910280da4 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -133,7 +133,7 @@ static void outliner_storage_cleanup(SpaceOops *soops) } /* XXX - THIS FUNCTION IS INCREDIBLY SLOW - * ... it can bring blenders tools and viewport to a grinding halt becuase of searching + * ... it can bring blenders tools and viewport to a grinding halt because of searching * for duplicate items every times they are added. * * TODO (possible speedups) diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 6cfc3f97b31..ecc09a35670 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -326,19 +326,14 @@ static void outliner_main_area_listener(ARegion *ar, wmNotifier *wmn) break; case NC_MATERIAL: switch (wmn->data) { - case ND_SHADING: - case ND_SHADING_DRAW: + case ND_SHADING_LINKS: ED_region_tag_redraw(ar); break; } break; - case NC_TEXTURE: - ED_region_tag_redraw(ar); - break; case NC_GEOM: switch (wmn->data) { - case ND_DATA: - /* needed for vertex groups only, no special notifier atm so use NC_GEOM|ND_DATA */ + case ND_VERTEX_GROUP: ED_region_tag_redraw(ar); break; } diff --git a/source/blender/editors/space_sequencer/SConscript b/source/blender/editors/space_sequencer/SConscript index 0b429ae750b..bc72786fc5f 100644 --- a/source/blender/editors/space_sequencer/SConscript +++ b/source/blender/editors/space_sequencer/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('*.c') -incs = '../include ../../blenlib ../../blenkernel ../../blenfont ../../makesdna ../../imbuf' +incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../makesrna ../../blenloader ../../blenfont' incs += ' #/intern/audaspace/intern' diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 29babd355ad..1a84efa0b50 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -285,8 +285,8 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, drawmeta_stipple(1); for (seq = seqm->seqbase.first; seq; seq = seq->next) { - chan_min = MIN2(chan_min, seq->machine); - chan_max = MAX2(chan_max, seq->machine); + chan_min = min_ii(chan_min, seq->machine); + chan_max = max_ii(chan_max, seq->machine); } chan_range = (chan_max - chan_min) + 1; @@ -822,6 +822,7 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int int rectx, recty; float render_size = 0.0; float proxy_size = 100.0; + short is_break = G.is_break; render_size = sseq->render_size; if (render_size == 0) { @@ -840,6 +841,11 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int context = BKE_sequencer_new_render_data(bmain, scene, rectx, recty, proxy_size); + /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled + * by Esc pressed somewhere in the past + */ + G.is_break = FALSE; + if (special_seq_update) ibuf = BKE_sequencer_give_ibuf_direct(context, cfra + frame_ofs, special_seq_update); else if (!U.prefetchframes) // XXX || (G.f & G_PLAYANIM) == 0) { @@ -847,6 +853,9 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int else ibuf = BKE_sequencer_give_ibuf_threaded(context, cfra + frame_ofs, sseq->chanshown); + /* restore state so real rendering would be canceled (if needed) */ + G.is_break = is_break; + return ibuf; } @@ -913,6 +922,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq unsigned char *display_buffer; void *cache_handle = NULL; + if (G.is_rendering == FALSE) { + /* stop all running jobs, except screen one. currently previews frustrate Render + * needed to make so sequencer's rendering doesn't conflict with compositor + */ + WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE); + } + render_size = sseq->render_size; if (render_size == 0) { render_size = scene->r.size; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 7270516aa51..e7f77db3b9e 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1686,7 +1686,7 @@ static int sequencer_delete_invoke(bContext *C, wmOperator *op, wmEvent *event) if (ar->regiontype == RGN_TYPE_WINDOW) { /* bounding box of 30 pixels is used for markers shortcuts, - * prevent conflict with markers shortcurts here + * prevent conflict with markers shortcuts here */ if (event->mval[1] <= 30) return OPERATOR_PASS_THROUGH; @@ -1850,6 +1850,7 @@ void SEQUENCER_OT_images_separate(wmOperatorType *ot) /* api callbacks */ ot->exec = sequencer_separate_images_exec; + ot->invoke = WM_operator_props_popup; ot->poll = sequencer_edit_poll; /* flags */ @@ -2404,6 +2405,15 @@ static int strip_jump_internal(Scene *scene, return change; } +static int sequencer_strip_jump_poll(bContext *C) +{ + /* prevent changes during render */ + if (G.is_rendering) + return 0; + + return sequencer_edit_poll(C); +} + /* jump frame to edit point operator */ static int sequencer_strip_jump_exec(bContext *C, wmOperator *op) { @@ -2430,7 +2440,7 @@ void SEQUENCER_OT_strip_jump(wmOperatorType *ot) /* api callbacks */ ot->exec = sequencer_strip_jump_exec; - ot->poll = sequencer_edit_poll; + ot->poll = sequencer_strip_jump_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3075,8 +3085,12 @@ static int sequencer_change_path_invoke(bContext *C, wmOperator *op, wmEvent *UN { Scene *scene = CTX_data_scene(C); Sequence *seq = BKE_sequencer_active_get(scene); + char filepath[FILE_MAX]; + + BLI_join_dirfile(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name); RNA_string_set(op->ptr, "directory", seq->strip->dir); + RNA_string_set(op->ptr, "filepath", filepath); /* set default display depending on seq type */ if (seq->type == SEQ_TYPE_IMAGE) { diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 3f70b2cb66e..d74e32620af 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -196,10 +196,6 @@ static void text_operatortypes(void) WM_operatortype_append(TEXT_OT_unindent); WM_operatortype_append(TEXT_OT_indent); - WM_operatortype_append(TEXT_OT_markers_clear); - WM_operatortype_append(TEXT_OT_next_marker); - WM_operatortype_append(TEXT_OT_previous_marker); - WM_operatortype_append(TEXT_OT_select_line); WM_operatortype_append(TEXT_OT_select_all); WM_operatortype_append(TEXT_OT_select_word); @@ -227,7 +223,6 @@ static void text_operatortypes(void) WM_operatortype_append(TEXT_OT_find_set_selected); WM_operatortype_append(TEXT_OT_replace); WM_operatortype_append(TEXT_OT_replace_set_selected); - WM_operatortype_append(TEXT_OT_mark_all); WM_operatortype_append(TEXT_OT_to_3d_object); diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 94f64563fd8..46ab2d9e688 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -95,7 +95,7 @@ static int text_font_draw_character(SpaceText *st, int x, int y, char c) static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c) { char str[BLI_UTF8_MAX + 1]; - size_t len = BLI_str_utf8_size(c); + size_t len = BLI_str_utf8_size_safe(c); memcpy(str, c, len); str[len] = '\0'; @@ -158,7 +158,7 @@ int flatten_string(SpaceText *st, FlattenString *fs, const char *in) in++; } else { - size_t len = BLI_str_utf8_size(in); + size_t len = BLI_str_utf8_size_safe(in); flatten_string_append(fs, in, r, len); in += len; total++; @@ -342,7 +342,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) if (*str == '\\') { *fmt = prev; fmt++; str++; if (*str == '\0') break; - *fmt = prev; fmt++; str += BLI_str_utf8_size(str); + *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str); continue; } /* Handle continuations */ @@ -363,14 +363,14 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) } *fmt = 'l'; - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; } /* Not in a string... */ else { /* Deal with comments first */ if (prev == '#' || *str == '#') { *fmt = '#'; - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; } else if (*str == '"' || *str == '\'') { /* Strings */ @@ -399,7 +399,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = 'n'; } else { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } /* Punctuation */ @@ -407,7 +407,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = '!'; /* Identifiers and other text (no previous ws. or delims. so text continues) */ else if (prev == 'q') { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ @@ -427,7 +427,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = prev; } else { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } } @@ -575,7 +575,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * end = max; chop = 1; *offc = 0; - for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size(linep->line + j)) { + for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) { int chars; /* Mimic replacement of tabs */ @@ -640,7 +640,7 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi *offc = 0; cursin = txt_utf8_offset_to_index(linein->line, cursin); - for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size(linein->line + j)) { + for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) { /* Mimic replacement of tabs */ ch = linein->line[j]; @@ -685,7 +685,7 @@ int text_get_char_pos(SpaceText *st, const char *line, int cur) { int a = 0, i; - for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size(line + i)) { + for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) { if (line[i] == '\t') a += st->tabnumber - a % st->tabnumber; else @@ -698,7 +698,7 @@ static const char *txt_utf8_get_nth(const char *str, int n) { int pos = 0; while (str[pos] && n--) { - pos += BLI_str_utf8_size(str + pos); + pos += BLI_str_utf8_size_safe(str + pos); } return str + pos; } @@ -719,7 +719,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w start = 0; mstart = 0; end = max; mend = txt_utf8_get_nth(str, max) - str; - for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size(str + mi)) { + for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size_safe(str + mi)) { if (i - start >= max) { /* skip hidden part of line */ if (skip) { @@ -730,11 +730,11 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w } /* Draw the visible portion of text on the overshot line */ - for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size(str + ma)) { + for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (st->showsyntax && format) format_draw_color(format[a]); x += text_font_draw_character_utf8(st, x, y, str + ma); } - y -= st->lheight; + y -= st->lheight + TXT_LINE_SPACING; x = basex; lines++; start = end; mstart = mend; @@ -748,7 +748,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w } /* Draw the remaining text */ - for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size(str + ma)) { + for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (st->showsyntax && format) format_draw_color(format[a]); @@ -786,7 +786,7 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra for (a = 0; a < amount; a++) { format_draw_color(format[a]); x += text_font_draw_character_utf8(st, x, y, in + str_shift); - str_shift += BLI_str_utf8_size(in + str_shift); + str_shift += BLI_str_utf8_size_safe(in + str_shift); } } else text_font_draw(st, x, y, in); @@ -1016,7 +1016,7 @@ int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str) lines = 1; start = 0; end = max; - for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size(str + j)) { + for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) { /* Mimic replacement of tabs */ ch = str[j]; if (ch == '\t') { @@ -1070,40 +1070,6 @@ int text_get_total_lines(SpaceText *st, ARegion *ar) return drawcache->total_lines; } -/* Move pointer to first visible line (top) */ -static TextLine *first_visible_line(SpaceText *st, ARegion *ar, int *wrap_top) -{ - Text *text = st->text; - TextLine *pline = text->lines.first; - int i = st->top, lineno = 0; - - text_update_drawcache(st, ar); - - if (wrap_top) *wrap_top = 0; - - if (st->wordwrap) { - while (i > 0 && pline) { - int lines = text_get_visible_lines_no(st, lineno); - - if (i - lines < 0) { - if (wrap_top) *wrap_top = i; - break; - } - else { - pline = pline->next; - i -= lines; - lineno++; - } - } - } - else { - for (i = st->top; pline->next && i > 0; i--) - pline = pline->next; - } - - return pline; -} - /************************ draw scrollbar *****************************/ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back) @@ -1241,90 +1207,6 @@ static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back) glDisable(GL_BLEND); } -/************************** draw markers **************************/ - -static void draw_markers(SpaceText *st, ARegion *ar) -{ - Text *text = st->text; - TextMarker *marker, *next; - TextLine *top, *line; - int offl, offc, i, x1, x2, y1, y2, x, y; - int topi, topy; - - /* Move pointer to first visible line (top) */ - top = first_visible_line(st, ar, NULL); - topi = BLI_findindex(&text->lines, top); - - topy = txt_get_span(text->lines.first, top); - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - /* invisible line (before top) */ - if (marker->lineno < topi) continue; - - line = BLI_findlink(&text->lines, marker->lineno); - - /* Remove broken markers */ - if (marker->end > line->len || marker->start > marker->end) { - BLI_freelinkN(&text->markers, marker); - continue; - } - - wrap_offset(st, ar, line, marker->start, &offl, &offc); - y1 = txt_get_span(top, line) - st->top + offl + topy; - x1 = text_get_char_pos(st, line->line, marker->start) - st->left + offc; - - wrap_offset(st, ar, line, marker->end, &offl, &offc); - y2 = txt_get_span(top, line) - st->top + offl + topy; - x2 = text_get_char_pos(st, line->line, marker->end) - st->left + offc; - - /* invisible part of line (before top, after last visible line) */ - if (y2 < 0 || y1 > st->top + st->viewlines) continue; - - glColor3ubv(marker->color); - x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - y = ar->winy - 3; - - if (y1 == y2) { - y -= y1 * st->lheight; - glBegin(GL_LINE_LOOP); - glVertex2i(x + x2 * st->cwidth + 1, y); - glVertex2i(x + x1 * st->cwidth - 2, y); - glVertex2i(x + x1 * st->cwidth - 2, y - st->lheight); - glVertex2i(x + x2 * st->cwidth + 1, y - st->lheight); - glEnd(); - } - else { - y -= y1 * st->lheight; - glBegin(GL_LINE_STRIP); - glVertex2i(ar->winx, y); - glVertex2i(x + x1 * st->cwidth - 2, y); - glVertex2i(x + x1 * st->cwidth - 2, y - st->lheight); - glVertex2i(ar->winx, y - st->lheight); - glEnd(); - y -= st->lheight; - - for (i = y1 + 1; i < y2; i++) { - glBegin(GL_LINES); - glVertex2i(x, y); - glVertex2i(ar->winx, y); - glVertex2i(x, y - st->lheight); - glVertex2i(ar->winx, y - st->lheight); - glEnd(); - y -= st->lheight; - } - - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x + x2 * st->cwidth + 1, y); - glVertex2i(x + x2 * st->cwidth + 1, y - st->lheight); - glVertex2i(x, y - st->lheight); - glEnd(); - } - } -} - /*********************** draw documentation *******************************/ static void draw_documentation(SpaceText *st, ARegion *ar) @@ -1494,6 +1376,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar) Text *text = st->text; int vcurl, vcurc, vsell, vselc, hidden = 0; int x, y, w, i; + int lheight = st->lheight + TXT_LINE_SPACING; /* Draw the selection */ if (text->curl != text->sell || text->curc != text->selc) { @@ -1514,11 +1397,11 @@ static void draw_cursor(SpaceText *st, ARegion *ar) y = ar->winy - 2; if (vcurl == vsell) { - y -= vcurl * st->lheight; + y -= vcurl * lheight; if (vcurc < vselc) - glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - st->lheight); + glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight + TXT_LINE_SPACING); else - glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - st->lheight); + glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight + TXT_LINE_SPACING); } else { int froml, fromc, tol, toc; @@ -1532,12 +1415,12 @@ static void draw_cursor(SpaceText *st, ARegion *ar) fromc = vselc; toc = vcurc; } - y -= froml * st->lheight; - glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - st->lheight); y -= st->lheight; + y -= froml * lheight; + glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - lheight); y -= lheight; for (i = froml + 1; i < tol; i++) - glRecti(x - 4, y, ar->winx, y - st->lheight), y -= st->lheight; + glRecti(x - 4, y, ar->winx, y - lheight), y -= lheight; - glRecti(x - 4, y, x + toc * st->cwidth, y - st->lheight); y -= st->lheight; + glRecti(x - 4, y, x + toc * st->cwidth, y - lheight + TXT_LINE_SPACING); y -= lheight; } } else { @@ -1561,12 +1444,12 @@ static void draw_cursor(SpaceText *st, ARegion *ar) wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc); - y1 = ar->winy - 2 - (vsell - offl) * st->lheight; - y2 = y1 - st->lheight * visible_lines + 1; + y1 = ar->winy - 2 - (vsell - offl) * lheight; + y2 = y1 - lheight * visible_lines + 1; } else { - y1 = ar->winy - 2 - vsell * st->lheight; - y2 = y1 - st->lheight + 1; + y1 = ar->winy - 2 - vsell * lheight; + y2 = y1 - lheight + 1; } if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */ @@ -1577,7 +1460,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glRecti(x1 - 4, y1, x2, y2); + glRecti(x1 - 4, y1, x2, y2 + TXT_LINE_SPACING); glDisable(GL_BLEND); } } @@ -1586,20 +1469,21 @@ static void draw_cursor(SpaceText *st, ARegion *ar) /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; x += vselc * st->cwidth; - y = ar->winy - 2 - vsell * st->lheight; + y = ar->winy - 2 - vsell * lheight; if (st->overwrite) { char ch = text->sell->line[text->selc]; + y += TXT_LINE_SPACING; w = st->cwidth; if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber; UI_ThemeColor(TH_HILITE); - glRecti(x, y - st->lheight - 1, x + w, y - st->lheight + 1); + glRecti(x, y - lheight - 1, x + w, y - lheight + 1); } else { UI_ThemeColor(TH_HILITE); - glRecti(x - 1, y, x + 1, y - st->lheight); + glRecti(x - 1, y, x + 1, y - lheight + TXT_LINE_SPACING); } } } @@ -1639,7 +1523,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (b > 0) { /* opening bracket, search forward for close */ fc++; - c += BLI_str_utf8_size(linep->line + c); + c += BLI_str_utf8_size_safe(linep->line + c); while (linep) { while (c < linep->len) { if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') { @@ -1657,7 +1541,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) } } fc++; - c += BLI_str_utf8_size(linep->line + c); + c += BLI_str_utf8_size_safe(linep->line + c); } if (endl) break; linep = linep->next; @@ -1714,8 +1598,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (viewc >= 0) { viewl = txt_get_span(text->lines.first, startl) - st->top + offl; - text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * st->lheight, ch); - text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * st->lheight, ch); + text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); + text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); } /* draw closing bracket */ @@ -1726,8 +1610,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (viewc >= 0) { viewl = txt_get_span(text->lines.first, endl) - st->top + offl; - text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * st->lheight, ch); - text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * st->lheight, ch); + text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); + text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); } } @@ -1743,7 +1627,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) int wraplinecount = 0, wrap_skip = 0; int margin_column_x; - if (st->lheight) st->viewlines = (int)ar->winy / st->lheight; + if (st->lheight) st->viewlines = (int)ar->winy / (st->lheight + TXT_LINE_SPACING); else st->viewlines = 0; /* if no text, nothing to do */ @@ -1832,14 +1716,14 @@ void draw_text_main(SpaceText *st, ARegion *ar) if (st->wordwrap) { /* draw word wrapped text */ int lines = text_draw_wrapped(st, tmp->line, x, y, winx - x, tmp->format, wrap_skip); - y -= lines * st->lheight; + y -= lines * (st->lheight + TXT_LINE_SPACING); } else { /* draw unwrapped text */ text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, 1, x, y, tmp->format); - y -= st->lheight; + y -= st->lheight + TXT_LINE_SPACING; } - + wrap_skip = 0; } @@ -1858,7 +1742,6 @@ void draw_text_main(SpaceText *st, ARegion *ar) /* draw other stuff */ draw_brackets(st, ar); - draw_markers(st, ar); glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0f); /* XXX scroll requires exact pixel space */ draw_textscroll(st, &scroll, &back); draw_documentation(st, ar); diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h index 4f973e7076b..ea61644cee9 100644 --- a/source/blender/editors/space_text/text_intern.h +++ b/source/blender/editors/space_text/text_intern.h @@ -57,6 +57,7 @@ void text_update_cursor_moved(struct bContext *C); #define TXT_OFFSET 15 #define TXT_SCROLL_WIDTH 20 #define TXT_SCROLL_SPACE 2 +#define TXT_LINE_SPACING 4 /* space between lines */ #define TEXTXLOC (st->cwidth * st->linenrs_tot) @@ -68,9 +69,6 @@ void text_update_cursor_moved(struct bContext *C); #define TOOL_SUGG_LIST 0x01 #define TOOL_DOCUMENT 0x02 -#define TMARK_GRP_CUSTOM 0x00010000 /* Lower 2 bytes used for Python groups */ -#define TMARK_GRP_FINDALL 0x00020000 - typedef struct FlattenString { char fixedbuf[256]; int fixedaccum[256]; @@ -129,10 +127,6 @@ void TEXT_OT_indent(struct wmOperatorType *ot); void TEXT_OT_line_break(struct wmOperatorType *ot); void TEXT_OT_insert(struct wmOperatorType *ot); -void TEXT_OT_markers_clear(struct wmOperatorType *ot); -void TEXT_OT_next_marker(struct wmOperatorType *ot); -void TEXT_OT_previous_marker(struct wmOperatorType *ot); - void TEXT_OT_select_line(struct wmOperatorType *ot); void TEXT_OT_select_all(struct wmOperatorType *ot); void TEXT_OT_select_word(struct wmOperatorType *ot); @@ -157,7 +151,6 @@ void TEXT_OT_find(struct wmOperatorType *ot); void TEXT_OT_find_set_selected(struct wmOperatorType *ot); void TEXT_OT_replace(struct wmOperatorType *ot); void TEXT_OT_replace_set_selected(struct wmOperatorType *ot); -void TEXT_OT_mark_all(struct wmOperatorType *ot); void TEXT_OT_to_3d_object(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 2d902c4586a..5b7f92739ed 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -615,6 +615,8 @@ static int text_run_script(bContext *C, ReportList *reports) } BKE_report(reports, RPT_ERROR, "Python script fail, look in the console for now..."); + + return OPERATOR_FINISHED; } #else (void)C; @@ -1135,7 +1137,8 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op) tmp = text->lines.first; - //first convert to all space, this make it a lot easier to convert to tabs because there is no mixtures of ' ' && '\t' + /* first convert to all space, this make it a lot easier to convert to tabs + * because there is no mixtures of ' ' && '\t' */ while (tmp) { text_check_line = tmp->line; number = flatten_string(st, &fs, text_check_line) + 1; @@ -1376,104 +1379,6 @@ void TEXT_OT_move_lines(wmOperatorType *ot) RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", ""); } -/******************* previous marker operator *********************/ - -static int text_previous_marker_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - TextMarker *mrk; - int lineno; - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.last; - while (mrk && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc))) - mrk = mrk->prev; - if (!mrk) mrk = text->markers.last; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_previous_marker(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Previous Marker"; - ot->idname = "TEXT_OT_previous_marker"; - ot->description = "Move to previous marker"; - - /* api callbacks */ - ot->exec = text_previous_marker_exec; - ot->poll = text_edit_poll; -} - -/******************* next marker operator *********************/ - -static int text_next_marker_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - TextMarker *mrk; - int lineno; - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk && (mrk->lineno < lineno || (mrk->lineno == lineno && mrk->start <= text->curc))) - mrk = mrk->next; - if (!mrk) mrk = text->markers.first; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_next_marker(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Next Marker"; - ot->idname = "TEXT_OT_next_marker"; - ot->description = "Move to next marker"; - - /* api callbacks */ - ot->exec = text_next_marker_exec; - ot->poll = text_edit_poll; -} - -/******************* clear all markers operator *********************/ - -static int text_clear_all_markers_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - - txt_clear_markers(text, 0, 0); - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_markers_clear(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Clear All Markers"; - ot->idname = "TEXT_OT_markers_clear"; - ot->description = "Clear all markers"; - - /* api callbacks */ - ot->exec = text_clear_all_markers_exec; - ot->poll = text_edit_poll; -} - /************************ move operator ************************/ static EnumPropertyItem move_type_items[] = { @@ -1503,7 +1408,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int end = max; chop = loop = 1; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size(linein->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) { int chars; /* Mimic replacement of tabs */ ch = linein->line[j]; @@ -1664,16 +1569,15 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, i, j, max, start, end, endj, chop, loop; + int oldc, i, j, max, start, end, endj, chop, loop; char ch; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } oldc = *charp; - oldl = txt_get_span(text->lines.first, *linep); max = wrap_width(st, ar); @@ -1682,7 +1586,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) chop = loop = 1; *charp = 0; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { int chars; /* Mimic replacement of tabs */ ch = (*linep)->line[j]; @@ -1724,7 +1628,6 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp); } static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) @@ -1732,16 +1635,15 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, i, j, max, start, end, endj, chop, loop; + int oldc, i, j, max, start, end, endj, chop, loop; char ch; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } oldc = *charp; - oldl = txt_get_span(text->lines.first, *linep); max = wrap_width(st, ar); @@ -1750,7 +1652,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) chop = loop = 1; *charp = 0; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { int chars; /* Mimic replacement of tabs */ ch = (*linep)->line[j]; @@ -1790,7 +1692,6 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp); } static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) @@ -1798,22 +1699,17 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, offl, offc, col, newl; + int offl, offc, col; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - - /* store previous position */ - oldc = *charp; - newl = oldl = txt_get_span(text->lines.first, *linep); + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); col = text_get_char_pos(st, (*linep)->line, *charp) + offc; if (offl) { *charp = text_get_cursor_rel(st, ar, *linep, offl - 1, col); - newl = BLI_findindex(&text->lines, linep); } else { if ((*linep)->prev) { @@ -1822,13 +1718,11 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) *linep = (*linep)->prev; visible_lines = text_get_visible_lines(st, ar, (*linep)->line); *charp = text_get_cursor_rel(st, ar, *linep, visible_lines - 1, col); - newl--; } else *charp = 0; } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp); } static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) @@ -1836,35 +1730,28 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, offl, offc, col, newl, visible_lines; + int offl, offc, col, visible_lines; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - - /* store previous position */ - oldc = *charp; - newl = oldl = txt_get_span(text->lines.first, *linep); + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); col = text_get_char_pos(st, (*linep)->line, *charp) + offc; visible_lines = text_get_visible_lines(st, ar, (*linep)->line); if (offl < visible_lines - 1) { *charp = text_get_cursor_rel(st, ar, *linep, offl + 1, col); - newl = BLI_findindex(&text->lines, linep); } else { if ((*linep)->next) { *linep = (*linep)->next; *charp = text_get_cursor_rel(st, ar, *linep, 0, col); - newl++; } else *charp = (*linep)->len; } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp); } /* Moves the cursor vertically by the specified number of lines. @@ -1876,12 +1763,10 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int sel) { TextLine **linep; - int oldl, oldc, *charp; + int *charp; - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - oldl = txt_get_span(text->lines.first, *linep); - oldc = *charp; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } if (st && ar && st->wordwrap) { int rell, relc; @@ -1904,7 +1789,6 @@ static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int s if (*charp > (*linep)->len) *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp); } static int text_move_cursor(bContext *C, int type, int select) @@ -2222,10 +2106,10 @@ static void text_scroll_apply(bContext *C, wmOperator *op, wmEvent *event) if (!tsc->scrollbar) { txtdelta[0] = -tsc->delta[0] / st->cwidth; - txtdelta[1] = tsc->delta[1] / st->lheight; + txtdelta[1] = tsc->delta[1] / (st->lheight + TXT_LINE_SPACING); tsc->delta[0] %= st->cwidth; - tsc->delta[1] %= st->lheight; + tsc->delta[1] %= (st->lheight + TXT_LINE_SPACING); } else { txtdelta[1] = -tsc->delta[1] * st->pix_per_line; @@ -2462,7 +2346,7 @@ static int flatten_len(SpaceText *st, const char *str) { int i, total = 0; - for (i = 0; str[i]; i += BLI_str_utf8_size(str + i)) { + for (i = 0; str[i]; i += BLI_str_utf8_size_safe(str + i)) { if (str[i] == '\t') { total += st->tabnumber - total % st->tabnumber; } @@ -2475,7 +2359,7 @@ static int flatten_len(SpaceText *st, const char *str) static int flatten_index_to_offset(SpaceText *st, const char *str, int index) { int i, j; - for (i = 0, j = 0; i < index; j += BLI_str_utf8_size(str + j)) + for (i = 0, j = 0; i < index; j += BLI_str_utf8_size_safe(str + j)) if (str[j] == '\t') i += st->tabnumber - i % st->tabnumber; else @@ -2519,7 +2403,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in int j = 0, curs = 0, endj = 0; /* mem */ int chop = 1; /* flags */ - for (; loop; j += BLI_str_utf8_size(linep->line + j)) { + for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) { int chars; /* Mimic replacement of tabs */ @@ -2611,7 +2495,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in if (linep && charp != -1) { if (sel) { text->sell = linep; text->selc = charp; } - else { text->curl = linep; text->curc = charp; } + else { text->curl = linep; text->curc = charp; } } } @@ -2619,7 +2503,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int { Text *text = st->text; text_update_character_width(st); - y = (ar->winy - 2 - y) / st->lheight; + y = (ar->winy - 2 - y) / (st->lheight + TXT_LINE_SPACING); if (st->showlinenrs) x -= TXT_OFFSET + TEXTXLOC; else x -= TXT_OFFSET; @@ -2636,7 +2520,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int int w; if (sel) { linep = &text->sell; charp = &text->selc; } - else { linep = &text->curl; charp = &text->curc; } + else { linep = &text->curl; charp = &text->curc; } y -= txt_get_span(text->lines.first, *linep) - st->top; @@ -2696,7 +2580,6 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op) SpaceText *st = CTX_wm_space_text(C); Text *text = st->text; SetSelection *ssel = op->customdata; - int linep2, charp2; char *buffer; if (txt_has_sel(text)) { @@ -2705,12 +2588,6 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op) MEM_freeN(buffer); } - linep2 = txt_get_span(st->text->lines.first, st->text->sell); - charp2 = st->text->selc; - - if (ssel->sell != linep2 || ssel->selc != charp2) - txt_undo_add_toop(st->text, UNDO_STO, ssel->sell, ssel->selc, linep2, charp2); - text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); @@ -2786,19 +2663,12 @@ void TEXT_OT_selection_set(wmOperatorType *ot) static int text_cursor_set_exec(bContext *C, wmOperator *op) { SpaceText *st = CTX_wm_space_text(C); - Text *text = st->text; ARegion *ar = CTX_wm_region(C); int x = RNA_int_get(op->ptr, "x"); int y = RNA_int_get(op->ptr, "y"); - int oldl, oldc; - - oldl = txt_get_span(text->lines.first, text->curl); - oldc = text->curc; text_cursor_set_to_pos(st, ar, x, y, 0); - txt_undo_add_toop(text, UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, text->curl), text->curc); - text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); @@ -2945,7 +2815,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event) size_t len; if (event->utf8_buf[0]) { - len = BLI_str_utf8_size(event->utf8_buf); + len = BLI_str_utf8_size_safe(event->utf8_buf); memcpy(str, event->utf8_buf, len); } else { @@ -2990,14 +2860,13 @@ void TEXT_OT_insert(wmOperatorType *ot) /* mode */ #define TEXT_FIND 0 #define TEXT_REPLACE 1 -#define TEXT_MARK_ALL 2 static int text_find_and_replace(bContext *C, wmOperator *op, short mode) { Main *bmain = CTX_data_main(C); SpaceText *st = CTX_wm_space_text(C); - Text *start = NULL, *text = st->text; - int flags, first = 1; + Text *text = st->text; + int flags; int found = 0; char *tmp; @@ -3006,79 +2875,48 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode) flags = st->flags; if (flags & ST_FIND_ALL) - flags ^= ST_FIND_WRAP; + flags &= ~ST_FIND_WRAP; - do { - int proceed = 0; + /* Replace current */ + if (mode != TEXT_FIND && txt_has_sel(text)) { + tmp = txt_sel_to_buf(text); - if (first) { - if (text->markers.first) + if (flags & ST_MATCH_CASE) found = strcmp(st->findstr, tmp) == 0; + else found = BLI_strcasecmp(st->findstr, tmp) == 0; + + if (found) { + if (mode == TEXT_REPLACE) { + txt_insert_buf(text, st->replacestr); + if (text->curl && text->curl->format) { + MEM_freeN(text->curl->format); + text->curl->format = NULL; + } + text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - txt_clear_markers(text, TMARK_GRP_FINDALL, 0); - } - - first = 0; - - /* Replace current */ - if (mode != TEXT_FIND && txt_has_sel(text)) { - tmp = txt_sel_to_buf(text); - - if (flags & ST_MATCH_CASE) proceed = strcmp(st->findstr, tmp) == 0; - else proceed = BLI_strcasecmp(st->findstr, tmp) == 0; - - if (proceed) { - if (mode == TEXT_REPLACE) { - txt_insert_buf(text, st->replacestr); - if (text->curl && text->curl->format) { - MEM_freeN(text->curl->format); - text->curl->format = NULL; - } - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - text_drawcache_tag_update(CTX_wm_space_text(C), 1); - } - else if (mode == TEXT_MARK_ALL) { - unsigned char color[4]; - UI_GetThemeColor4ubv(TH_SHADE2, color); - - if (txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) { - if (tmp) MEM_freeN(tmp), tmp = NULL; - break; - } - - txt_add_marker(text, text->curl, text->curc, text->selc, color, TMARK_GRP_FINDALL, TMARK_EDITALL); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - } + text_drawcache_tag_update(CTX_wm_space_text(C), 1); } - MEM_freeN(tmp); - tmp = NULL; } + MEM_freeN(tmp); + tmp = NULL; + } - /* Find next */ - if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) { - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - } - else if (flags & ST_FIND_ALL) { - if (text == start) break; - if (!start) start = text; - if (text->id.next) - text = st->text = text->id.next; - else - text = st->text = bmain->text.first; - txt_move_toline(text, 0, 0); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - first = 1; - } - else { - if (!found && !proceed) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr); - break; - } - found = 1; - } while (mode == TEXT_MARK_ALL); + /* Find next */ + if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) { + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + } + else if (flags & ST_FIND_ALL) { + if (text->id.next) + text = st->text = text->id.next; + else + text = st->text = bmain->text.first; + txt_move_toline(text, 0, 0); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + } + else { + if (!found) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr); + } return OPERATOR_FINISHED; } @@ -3119,25 +2957,6 @@ void TEXT_OT_replace(wmOperatorType *ot) ot->poll = text_space_edit_poll; } -/******************* mark all operator *********************/ - -static int text_mark_all_exec(bContext *C, wmOperator *op) -{ - return text_find_and_replace(C, op, TEXT_MARK_ALL); -} - -void TEXT_OT_mark_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Mark All"; - ot->idname = "TEXT_OT_mark_all"; - ot->description = "Mark all specified text"; - - /* api callbacks */ - ot->exec = text_mark_all_exec; - ot->poll = text_space_edit_poll; -} - /******************* find set selected *********************/ static int text_find_set_selected_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c index 966afe22e42..4c9b4b900cc 100644 --- a/source/blender/editors/space_text/text_python.c +++ b/source/blender/editors/space_text/text_python.c @@ -359,177 +359,3 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned return swallow; } - -static short UNUSED_FUNCTION(do_textmarkers) (SpaceText * st, char ascii, unsigned short evnt, short val) -{ - Text *text; - TextMarker *marker, *mrk, *nxt; - int c, s, draw = 0, swallow = 0; - int qual = 0; // XXX - - text = st->text; - if (!text || text->id.lib || text->curl != text->sell) return 0; - - marker = txt_find_marker(text, text->sell, text->selc, 0, 0); - if (marker && (marker->start > text->curc || marker->end < text->curc)) - marker = NULL; - - if (!marker) { - /* Find the next temporary marker */ - if (evnt == TABKEY) { - int lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk) { - if (!marker && (mrk->flags & TMARK_TEMP)) marker = mrk; - if ((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc))) { - marker = mrk; - break; - } - mrk = mrk->next; - } - if (marker) { - txt_move_to(text, marker->lineno, marker->start, 0); - txt_move_to(text, marker->lineno, marker->end, 1); - // XXX text_update_cursor_moved(C); - // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); - evnt = ascii = val = 0; - draw = 1; - swallow = 1; - } - } - else if (evnt == ESCKEY) { - if (txt_clear_markers(text, 0, TMARK_TEMP)) swallow = 1; - else if (txt_clear_markers(text, 0, 0)) swallow = 1; - else return 0; - evnt = ascii = val = 0; - draw = 1; - } - if (!swallow) return 0; - } - - if (ascii) { - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - if (st->overwrite) { - if (txt_replace_char(text, ascii)) - text_update_line_edited(st->text->curl); - } - else { - if (txt_add_char(text, ascii)) { - text_update_line_edited(st->text->curl); - } - } - - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - } - else if (val) { - switch (evnt) { - case BACKSPACEKEY: - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - txt_backspace_char(text); - text_update_line_edited(st->text->curl); - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - break; - case DELKEY: - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - txt_delete_char(text); - text_update_line_edited(st->text->curl); - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - break; - case TABKEY: - if (qual & LR_SHIFTKEY) { - nxt = marker->prev; - if (!nxt) nxt = text->markers.last; - } - else { - nxt = marker->next; - if (!nxt) nxt = text->markers.first; - } - if (marker->flags & TMARK_TEMP) { - if (nxt == marker) nxt = NULL; - BLI_freelinkN(&text->markers, marker); - } - mrk = nxt; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - // XXX text_update_cursor_moved(C); - // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); - } - swallow = 1; - draw = 1; - break; - - /* Events that should clear markers */ - case UKEY: if (!(qual & LR_ALTKEY)) break; - case ZKEY: if (evnt == ZKEY && !(qual & LR_CTRLKEY)) break; - case RETKEY: - case ESCKEY: - if (marker->flags & (TMARK_EDITALL | TMARK_TEMP)) - txt_clear_markers(text, marker->group, 0); - else - BLI_freelinkN(&text->markers, marker); - swallow = 1; - draw = 1; - break; - case RIGHTMOUSE: /* Marker context menu? */ - case LEFTMOUSE: - break; - case FKEY: /* Allow find */ - if (qual & LR_SHIFTKEY) swallow = 1; - break; - - default: - if (qual != 0 && qual != LR_SHIFTKEY) - swallow = 1; /* Swallow all other shortcut events */ - } - } - - if (draw) { - // XXX redraw_alltext(); - } - - return swallow; -} - diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index cb5556396dd..0ecde350b00 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -51,6 +51,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_effect.h" +#include "BKE_global.h" #include "BKE_image.h" #include "BKE_material.h" #include "BKE_paint.h" @@ -728,7 +729,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) BKE_bproperty_set_valstr(prop, string); characters = strlen(string); - if (!BKE_image_get_ibuf(mtpoly->tpage, NULL)) + if (!BKE_image_has_ibuf(mtpoly->tpage, NULL)) characters = 0; if (!mf_smooth) { @@ -965,7 +966,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Mesh *me = ob->data; TexMatCallback data = {scene, ob, me, dm}; int (*set_face_cb)(void *, int); - int glsl; + int glsl, picking = (G.f & G_PICKSEL); /* face hiding callback depending on mode */ if (ob == scene->obedit) @@ -976,11 +977,11 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, set_face_cb = NULL; /* test if we can use glsl */ - glsl = (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support(); + glsl = (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support() && !picking; GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); - if (glsl) { + if (glsl || picking) { /* draw glsl */ dm->drawMappedFacesMat(dm, tex_mat_set_material_cb, diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f100f003ff5..5ac7327b93b 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -229,7 +229,10 @@ static int check_alpha_pass(Base *base) if (G.f & G_PICKSEL) return 0; - + + if (base->object->mode & OB_MODE_ALL_PAINT) + return 0; + return (base->object->dtx & OB_DRAWTRANSP); } @@ -530,7 +533,7 @@ void drawaxes(float size, char drawtype) static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4]) { Image *ima = (Image *)ob->data; - ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL; + ImBuf *ibuf = ima ? BKE_image_acquire_ibuf(ima, NULL, NULL) : NULL; float scale, ofs_x, ofs_y, sca_x, sca_y; int ima_x, ima_y; @@ -615,6 +618,8 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char /* Reset GL settings */ glMatrixMode(GL_MODELVIEW); glPopMatrix(); + + BKE_image_release_ibuf(ima, ibuf, NULL); } static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4]) @@ -2577,7 +2582,7 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS BMIter iter; int i; - /* make the precision of the pronted value proportionate to the gridsize */ + /* make the precision of the display value proportionate to the gridsize */ if (grid < 0.01f) conv_float = "%.6g"; else if (grid < 0.1f) conv_float = "%.5g"; @@ -3600,9 +3605,12 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B return 0; } -/* returns 1 when nothing was drawn */ -static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) +/** + * Only called by #drawDispList + * \return 1 when nothing was drawn + */ +static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; ListBase *lb = NULL; @@ -3610,20 +3618,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas Curve *cu; const short render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE); const short solid = (dt > OB_WIRE); - int retval = 0; - - /* backface culling */ - if (v3d->flag2 & V3D_BACKFACE_CULLING) { - /* not all displists use same in/out normal direction convention */ - glEnable(GL_CULL_FACE); - glCullFace((ob->type == OB_MBALL) ? GL_BACK : GL_FRONT); - } if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == 0) { - if (v3d->flag2 & V3D_BACKFACE_CULLING) - glDisable(GL_CULL_FACE); - - return 0; + return FALSE; } switch (ob->type) { @@ -3635,7 +3632,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (solid) { dl = lb->first; - if (dl == NULL) return 1; + if (dl == NULL) { + return TRUE; + } if (dl->nors == NULL) BKE_displist_normals_add(lb); index3_nors_incr = 0; @@ -3669,9 +3668,11 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } else { if (!render_only || (render_only && BKE_displist_has_faces(lb))) { + int retval; draw_index_wire = 0; retval = drawDispListwire(lb); draw_index_wire = 1; + return retval; } } break; @@ -3681,7 +3682,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (solid) { dl = lb->first; - if (dl == NULL) return 1; + if (dl == NULL) { + return TRUE; + } if (dl->nors == NULL) BKE_displist_normals_add(lb); @@ -3697,7 +3700,7 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } } else { - retval = drawDispListwire(lb); + return drawDispListwire(lb); } break; case OB_MBALL: @@ -3705,7 +3708,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (BKE_mball_is_basis(ob)) { lb = &ob->disp; if (lb->first == NULL) BKE_displist_make_mball(scene, ob); - if (lb->first == NULL) return 1; + if (lb->first == NULL) { + return TRUE; + } if (solid) { @@ -3722,14 +3727,31 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } else { /* MetaBalls use DL_INDEX4 type of DispList */ - retval = drawDispListwire(lb); + return drawDispListwire(lb); } } break; } - - if (v3d->flag2 & V3D_BACKFACE_CULLING) + + return FALSE; +} +static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dt, const short dflag, const unsigned char ob_wire_col[4]) +{ + int retval; + + /* backface culling */ + if (v3d->flag2 & V3D_BACKFACE_CULLING) { + /* not all displists use same in/out normal direction convention */ + glEnable(GL_CULL_FACE); + glCullFace((base->object->type == OB_MBALL) ? GL_BACK : GL_FRONT); + } + + retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + + if (v3d->flag2 & V3D_BACKFACE_CULLING) { glDisable(GL_CULL_FACE); + } return retval; } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 6818c78bbd6..1c31cd23e33 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -702,6 +702,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) case NC_GEOM: switch (wmn->data) { case ND_DATA: + case ND_VERTEX_GROUP: case ND_SELECT: ED_region_tag_redraw(ar); break; @@ -723,6 +724,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) case NC_MATERIAL: switch (wmn->data) { case ND_SHADING_DRAW: + case ND_SHADING_LINKS: ED_region_tag_redraw(ar); break; } @@ -920,6 +922,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) case NC_GEOM: switch (wmn->data) { case ND_DATA: + case ND_VERTEX_GROUP: case ND_SELECT: ED_region_tag_redraw(ar); break; @@ -945,7 +948,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) ED_region_tag_redraw(ar); break; case NC_GPENCIL: - if (wmn->data == ND_DATA) + if (wmn->data == ND_DATA || wmn->action == NA_EDITED) ED_region_tag_redraw(ar); break; } @@ -1119,16 +1122,21 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes return 1; } else if (CTX_data_equals(member, "active_base")) { - if (scene->basact && (scene->basact->lay & lay)) - if ((scene->basact->object->restrictflag & OB_RESTRICT_VIEW) == 0) + if (scene->basact && (scene->basact->lay & lay)) { + Object *ob = scene->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact); + } return 1; } else if (CTX_data_equals(member, "active_object")) { - if (scene->basact && (scene->basact->lay & lay)) - if ((scene->basact->object->restrictflag & OB_RESTRICT_VIEW) == 0) + if (scene->basact && (scene->basact->lay & lay)) { + Object *ob = scene->basact->object; + if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) CTX_data_id_pointer_set(result, &scene->basact->object->id); + } return 1; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 4d4fad47698..51261f4c341 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -95,6 +95,16 @@ #include "view3d_intern.h" /* own include */ +/* handy utility for drawing shapes in the viewport for arbitrary code. + * could add lines and points too */ +// #define DEBUG_DRAW +#ifdef DEBUG_DRAW +static void bl_debug_draw(void); +/* add these locally when using these functions for testing */ +extern void bl_debug_draw_quad_clear(void); +extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]); +extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]); +#endif static void star_stuff_init_func(void) { @@ -441,10 +451,9 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char ** } #undef GRID_MIN_PX -float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) +/** could move this elsewhere, but tied into #ED_view3d_grid_scale */ +float ED_scene_grid_scale(Scene *scene, const char **grid_unit) { - float grid_scale = v3d->grid; - /* apply units */ if (scene->unit.system) { void *usys; @@ -456,11 +465,16 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) int i = bUnit_GetBaseUnit(usys); if (grid_unit) *grid_unit = bUnit_GetNameDisplay(usys, i); - grid_scale = (grid_scale * (float)bUnit_GetScaler(usys, i)) / scene->unit.scale_length; + return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; } } - return grid_scale; + return 1.0f; +} + +float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) +{ + return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) @@ -545,12 +559,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) } } } - - - - - if (v3d->zbuf && scene->obedit) glDepthMask(1); + if (v3d->zbuf && scene->obedit) glDepthMask(1); } static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) @@ -600,8 +610,8 @@ static void draw_view_axis(RegionView3D *rv3d) mul_qt_v3(rv3d->viewquat, vec); dx = vec[0] * k; dy = vec[1] * k; - - glColor4ub(220, 0, 0, bright); + + UI_ThemeColorShadeAlpha(TH_AXIS_X, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); @@ -620,8 +630,8 @@ static void draw_view_axis(RegionView3D *rv3d) mul_qt_v3(rv3d->viewquat, vec); dx = vec[0] * k; dy = vec[1] * k; - - glColor4ub(0, 220, 0, bright); + + UI_ThemeColorShadeAlpha(TH_AXIS_Y, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); @@ -640,7 +650,7 @@ static void draw_view_axis(RegionView3D *rv3d) dx = vec[0] * k; dy = vec[1] * k; - glColor4ub(30, 30, 220, bright); + UI_ThemeColorShadeAlpha(TH_AXIS_Z, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); @@ -1218,11 +1228,11 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) hmargin = 0.1f * (x2 - x1); vmargin = 0.05f * (y2 - y1); - uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f); hmargin = 0.035f * (x2 - x1); vmargin = 0.035f * (y2 - y1); - uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f); } if (ca && (ca->flag & CAM_SHOWSENSOR)) { /* determine sensor fit, and get sensor x/y, for auto fit we @@ -1416,8 +1426,8 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect); - view3d_validate_backbuf(vc); - + view3d_validate_backbuf(vc); + glReadPixels(vc->ar->winrct.xmin + xminc, vc->ar->winrct.ymin + yminc, (xmaxc - xminc + 1), @@ -1565,7 +1575,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ibuf = NULL; /* frame is out of range, dont show */ } else { - ibuf = BKE_image_get_ibuf(ima, &bgpic->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL); + freeibuf = ibuf; } image_aspect[0] = ima->aspx; @@ -1924,10 +1935,17 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) { tbase.object = dob->ob; - /* extra service: draw the duplicator in drawtype of parent */ - /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ - dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); - dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; + /* extra service: draw the duplicator in drawtype of parent, minimum taken + * to allow e.g. boundbox box objects in groups for LOD */ + dt = tbase.object->dt; + tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + + /* inherit draw extra, but not if a boundbox under the assumption that this + * is intended to speed up drawing, and drawing extra (especially wire) can + * slow it down too much */ + dtx = tbase.object->dtx; + if (tbase.object->dt != OB_BOUNDBOX) + tbase.object->dtx = base->object->dtx; /* negative scale flag has to propagate */ transflag = tbase.object->transflag; @@ -2989,10 +3007,11 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const v3d->zbuf = FALSE; /* enables anti-aliasing for 3D view drawing */ -#if 0 - if (!(U.gameflags & USER_DISABLE_AA)) + if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) { + // if (!(U.gameflags & USER_DISABLE_AA)) glEnable(GL_MULTISAMPLE_ARB); -#endif + } + /* needs to be done always, gridview is adjusted in drawgrid() now */ rv3d->gridview = v3d->grid; @@ -3105,12 +3124,13 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const BIF_draw_manipulator(C); -#if 0 /* Disable back anti-aliasing */ - if (!(U.gameflags & USER_DISABLE_AA)) + if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) { + // if (!(U.gameflags & USER_DISABLE_AA)) glDisable(GL_MULTISAMPLE_ARB); -#endif + } + if (v3d->zbuf) { v3d->zbuf = FALSE; glDisable(GL_DEPTH_TEST); @@ -3210,6 +3230,9 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) /* draw viewport using opengl */ if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) { view3d_main_area_draw_objects(C, ar, &grid_unit); +#ifdef DEBUG_DRAW + bl_debug_draw(); +#endif ED_region_pixelspace(ar); } @@ -3222,3 +3245,76 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) v3d->flag |= V3D_INVALID_BACKBUF; } +#ifdef DEBUG_DRAW +/* debug drawing */ +#define _DEBUG_DRAW_QUAD_TOT 1024 +#define _DEBUG_DRAW_EDGE_TOT 1024 +static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3]; +static int _bl_debug_draw_quads_tot = 0; +static float _bl_debug_draw_edges[_DEBUG_DRAW_QUAD_TOT][2][3]; +static int _bl_debug_draw_edges_tot = 0; + +void bl_debug_draw_quad_clear(void) +{ + _bl_debug_draw_quads_tot = 0; + _bl_debug_draw_edges_tot = 0; +} +void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]) +{ + if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) { + printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot); + } + else { + float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0]; + copy_v3_v3(pt, v0); pt += 3; + copy_v3_v3(pt, v1); pt += 3; + copy_v3_v3(pt, v2); pt += 3; + copy_v3_v3(pt, v3); pt += 3; + _bl_debug_draw_quads_tot++; + } +} +void bl_debug_draw_edge_add(const float v0[3], const float v1[3]) +{ + if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_EDGE_TOT) { + printf("%s: max edge count hit %d!", __func__, _bl_debug_draw_edges_tot); + } + else { + float *pt = &_bl_debug_draw_edges[_bl_debug_draw_edges_tot][0][0]; + copy_v3_v3(pt, v0); pt += 3; + copy_v3_v3(pt, v1); pt += 3; + _bl_debug_draw_edges_tot++; + } +} +static void bl_debug_draw(void) +{ + if (_bl_debug_draw_quads_tot) { + int i; + cpack(0x00FF0000); + glBegin(GL_LINE_LOOP); + for (i = 0; i < _bl_debug_draw_quads_tot; i ++) { + glVertex3fv(_bl_debug_draw_quads[i][0]); + glVertex3fv(_bl_debug_draw_quads[i][1]); + glVertex3fv(_bl_debug_draw_quads[i][2]); + glVertex3fv(_bl_debug_draw_quads[i][3]); + } + glEnd(); + } + if (_bl_debug_draw_edges_tot) { + int i; + cpack(0x00FFFF00); + glBegin(GL_LINES); + for (i = 0; i < _bl_debug_draw_edges_tot; i ++) { + glVertex3fv(_bl_debug_draw_edges[i][0]); + glVertex3fv(_bl_debug_draw_edges[i][1]); + } + glEnd(); + glPointSize(4.0); + glBegin(GL_POINTS); + for (i = 0; i < _bl_debug_draw_edges_tot; i ++) { + glVertex3fv(_bl_debug_draw_edges[i][0]); + glVertex3fv(_bl_debug_draw_edges[i][1]); + } + glEnd(); + } +} +#endif diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 36d7341f2f2..d45013c40d9 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -992,8 +992,10 @@ void ndof_to_quat(struct wmNDOFMotionData *ndof, float q[4]) * -- zooming * -- panning in rotationally-locked views */ -static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) { + ViewOpsData *vod = op->customdata; + if (event->type != NDOF_MOTION) return OPERATOR_CANCELLED; else { @@ -1074,6 +1076,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event rot[1] = rot[2] = 0.0; rot[3] = sin(angle); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + } else { float rot[4]; @@ -1088,6 +1091,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS) axis[1] = -axis[1]; + /* transform rotation axis from view to world coordinates */ mul_qt_v3(view_inv, axis); @@ -1100,7 +1104,22 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event /* apply rotation */ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - + + } + + /* rotate around custom center */ + if (vod && vod->use_dyn_ofs) { + float q1[4]; + + /* compute the post multiplication quat, to rotate the offset correctly */ + conjugate_qt_qt(q1, vod->oldquat); + mul_qt_qtqt(q1, q1, rv3d->viewquat); + + conjugate_qt(q1); /* conj == inv for unit quat */ + copy_v3_v3(rv3d->ofs, vod->ofs); + sub_v3_v3(rv3d->ofs, vod->dyn_ofs); + mul_qt_v3(q1, rv3d->ofs); + add_v3_v3(rv3d->ofs, vod->dyn_ofs); } } } @@ -1267,6 +1286,9 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) float axis[3]; #endif + /* inverse view */ + invert_qt_qt(view_inv, rv3d->viewquat); + if (U.ndof_flag & NDOF_PANX_INVERT_AXIS) pan_vec[0] = -lateral_sensitivity * ndof->tvec[0]; else @@ -1285,12 +1307,11 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) mul_v3_fl(pan_vec, speed * dt); /* transform motion from view to world coordinates */ - invert_qt_qt(view_inv, rv3d->viewquat); mul_qt_v3(view_inv, pan_vec); /* move center of view opposite of hand motion (this is camera mode, not object mode) */ sub_v3_v3(rv3d->ofs, pan_vec); - + if (U.ndof_flag & NDOF_TURNTABLE) { /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ float angle, rot[4]; @@ -1350,8 +1371,24 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) /* apply rotation */ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - + } + + /* rotate around custom center */ + if (vod && vod->use_dyn_ofs) { + float q1[4]; + + /* compute the post multiplication quat, to rotate the offset correctly */ + conjugate_qt_qt(q1, vod->oldquat); + mul_qt_qtqt(q1, q1, rv3d->viewquat); + + conjugate_qt(q1); /* conj == inv for unit quat */ + copy_v3_v3(rv3d->ofs, vod->ofs); + sub_v3_v3(rv3d->ofs, vod->dyn_ofs); + mul_qt_v3(q1, rv3d->ofs); + add_v3_v3(rv3d->ofs, vod->dyn_ofs); + } + } ED_view3d_camera_lock_sync(v3d, rv3d); @@ -1616,7 +1653,7 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) } -static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, const short zoom_invert) +static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const short viewzoom, const short zoom_invert) { float zfac = 1.0; short use_cam_zoom; @@ -1637,10 +1674,10 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, float fac; if (U.uiflag & USER_ZOOM_HORIZ) { - fac = (float)(x - vod->origx); + fac = (float)(vod->origx - x); } else { - fac = (float)(y - vod->origy); + fac = (float)(vod->origy - y); } if (zoom_invert) { @@ -2187,10 +2224,24 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, /* fix up zoom distance if needed */ if (rv3d->is_persp) { - if (size <= v3d->near * 1.5f) { - /* do not zoom closer than the near clipping plane */ - size = v3d->near * 1.5f; + float lens, sensor_size; + /* offset the view based on the lens */ + if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) { + CameraParams params; + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, v3d->camera); + + lens = params.lens; + sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); } + else { + lens = v3d->lens; + sensor_size = DEFAULT_SENSOR_WIDTH; + } + size = ED_view3d_radius_to_persp_dist(focallength_to_fov(lens, sensor_size), size / 2.0f) * VIEW3D_MARGIN; + + /* do not zoom closer than the near clipping plane */ + size = max_ff(size, v3d->near * 1.5f); } else { /* ortho */ if (size < 0.0001f) { @@ -2199,7 +2250,7 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, } else { /* adjust zoom so it looks nicer */ - size *= 0.7f; + size = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN; } } } diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 5aee90f0860..cddfae53f6f 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -369,8 +369,6 @@ static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event } /* store the original camera loc and rot */ - /* TODO. axis angle etc */ - fly->obtfm = BKE_object_tfm_backup(ob_back); BKE_object_where_is_calc(fly->scene, fly->v3d->camera); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index d8fcc7e12e7..79bf003a563 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -310,21 +310,14 @@ static char *view3d_modeselect_pup(Scene *scene) return (string); } - static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) { wmWindow *win = CTX_wm_window(C); - ToolSettings *ts = CTX_data_tool_settings(C); ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = NULL; - int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; + const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; PointerRNA props_ptr; - - if (obedit && obedit->type == OB_MESH) { - em = BMEdit_FromObject(obedit); - } + /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ switch (event) { @@ -336,42 +329,17 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) break; case B_SEL_VERT: - if (em) { - if (shift == 0 || em->selectmode == 0) - em->selectmode = SCE_SELECT_VERTEX; - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Vertex"); } break; case B_SEL_EDGE: - if (em) { - if (shift == 0 || em->selectmode == 0) { - if ((em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX) { - if (ctrl) EDBM_selectmode_convert(em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); - } - em->selectmode = SCE_SELECT_EDGE; - } - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Edge"); } break; case B_SEL_FACE: - if (em) { - if (shift == 0 || em->selectmode == 0) { - if (((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || - ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)) - { - if (ctrl) EDBM_selectmode_convert(em, (ts->selectmode ^ SCE_SELECT_FACE), SCE_SELECT_FACE); - } - em->selectmode = SCE_SELECT_FACE; - } - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Face"); } break; @@ -430,9 +398,15 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); - uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select - Shift-Click for multiple modes"); - uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select - Shift-Click for multiple modes"); - uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select - Shift-Click for multiple modes"); + uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Vertex select - Shift-Click for multiple modes"); + uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Edge select - Shift-Click for multiple modes, Ctrl-Click expands selection"); + uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"); } } diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index b928e060ca0..37607729d0d 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/editors/object/view3d_iterators.c +/** \file blender/editors/space_view3d/view3d_iterators.c * \ingroup spview3d */ diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 73f1563417c..6105b5e4eb5 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -274,8 +274,8 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, KM_ALT, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.viewport_shade"); - RNA_string_set(kmi->ptr, "value_1", "TEXTURED"); - RNA_string_set(kmi->ptr, "value_2", "SOLID"); + RNA_string_set(kmi->ptr, "value_1", "SOLID"); + RNA_string_set(kmi->ptr, "value_2", "TEXTURED"); /* selection*/ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 6ba05abae9a..34b983f83df 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -296,7 +296,7 @@ void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float r { float ray_end[3]; - ED_view3d_win_to_segment_clip(ar, v3d, mval, ray_start, ray_end); + ED_view3d_win_to_segment(ar, v3d, mval, ray_start, ray_end); sub_v3_v3v3(ray_normal, ray_end, ray_start); normalize_v3(ray_normal); } @@ -419,19 +419,7 @@ void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3]) normalize_v3(out); } -/** - * Calculate a 3d segment from 2d window coordinates. - * This ray_start is located at the viewpoint, ray_end is a far point. - * ray_start and ray_end are clipped by the view near and far limits - * so points along this line are always in view. - * In orthographic view all resulting segments will be parallel. - * \param ar The region (used for the window width and height). - * \param v3d The 3d viewport (used for near and far clipping range). - * \param mval The area relative 2d location (such as event->mval, converted into float[2]). - * \param ray_start The world-space starting point of the segment. - * \param ray_end The world-space end point of the segment. - */ -void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) +void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) { RegionView3D *rv3d = ar->regiondata; @@ -455,14 +443,46 @@ void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2] madd_v3_v3v3fl(ray_start, vec, rv3d->viewinv[2], 1000.0f); madd_v3_v3v3fl(ray_end, vec, rv3d->viewinv[2], -1000.0f); } +} + +/** + * Calculate a 3d segment from 2d window coordinates. + * This ray_start is located at the viewpoint, ray_end is a far point. + * ray_start and ray_end are clipped by the view near and far limits + * so points along this line are always in view. + * In orthographic view all resulting segments will be parallel. + * \param ar The region (used for the window width and height). + * \param v3d The 3d viewport (used for near and far clipping range). + * \param mval The area relative 2d location (such as event->mval, converted into float[2]). + * \param ray_start The world-space starting point of the segment. + * \param ray_end The world-space end point of the segment. + * \return success, FALSE if the segment is totally clipped. + */ +int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) +{ + RegionView3D *rv3d = ar->regiondata; + ED_view3d_win_to_segment(ar, v3d, mval, ray_start, ray_end); /* clipping */ if (rv3d->rflag & RV3D_CLIPPING) { + /* if the ray is totally clipped, + * restore the original values but return FALSE + * caller can choose what to do */ + float tray_start[3] = {UNPACK3(ray_start)}; + float tray_end[3] = {UNPACK3(ray_end)}; int a; for (a = 0; a < 4; a++) { - clip_line_plane(ray_start, ray_end, rv3d->clip[a]); + if (clip_line_plane(tray_start, tray_end, rv3d->clip[a]) == FALSE) { + return FALSE; + } } + + /* copy in clipped values */ + copy_v3_v3(ray_start, tray_start); + copy_v3_v3(ray_end, tray_end); } + + return TRUE; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 43626b058d6..cffa53b5dfb 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -221,7 +221,7 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, int select) } -/* object mode, EM_ prefix is confusing here, rename? */ +/* object mode, edbm_ prefix is confusing here, rename? */ static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select) { MVert *mv = me->mvert; @@ -237,8 +237,8 @@ static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select) } } } -/* object mode, EM_ prefix is confusing here, rename? */ +/* object mode, edbm_ prefix is confusing here, rename? */ static void edbm_backbuf_check_and_select_tfaces(Mesh *me, int select) { MPoly *mpoly = me->mpoly; @@ -1064,11 +1064,11 @@ static EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, PointerRNA * static int object_select_menu_exec(bContext *C, wmOperator *op) { int name_index = RNA_enum_get(op->ptr, "name"); - short extend = RNA_boolean_get(op->ptr, "extend"); + short toggle = RNA_boolean_get(op->ptr, "toggle"); short changed = 0; const char *name = object_mouse_select_menu_data[name_index].idname; - if (!extend) { + if (!toggle) { CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { if (base->flag & SELECT) { @@ -1125,7 +1125,7 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); ot->prop = prop; - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */ @@ -1141,7 +1141,7 @@ static void deselectall_except(Scene *scene, Base *b) /* deselect all except b } } -static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short extend) +static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short toggle) { short baseCount = 0; short ok; @@ -1207,7 +1207,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int PointerRNA ptr; WM_operator_properties_create(&ptr, "VIEW3D_OT_select_menu"); - RNA_boolean_set(&ptr, "extend", extend); + RNA_boolean_set(&ptr, "toggle", toggle); WM_operator_name_call(C, "VIEW3D_OT_select_menu", WM_OP_INVOKE_DEFAULT, &ptr); WM_operator_properties_free(&ptr); } @@ -1440,7 +1440,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese /* note; shift+alt goes to group-flush-selecting */ if (enumerate) { - basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend); + basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle); } else { base = startbase; @@ -1480,7 +1480,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese /* note; shift+alt goes to group-flush-selecting */ if (has_bones == 0 && enumerate) { - basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, extend); + basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle); } else { basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, has_bones); diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index d36b0085acb..bfeb56036e6 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -176,7 +176,7 @@ static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase) uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 15, uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL); but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb, NULL); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index c16f04f01f3..ef15c1e734e 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -247,9 +247,9 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera copy_qt_qt(rv3d->viewquat, sms.new_quat); rv3d->dist = sms.new_dist; v3d->lens = sms.new_lens; - } - ED_view3d_camera_lock_sync(v3d, rv3d); + ED_view3d_camera_lock_sync(v3d, rv3d); + } if (rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_copy(sa, ar); @@ -323,8 +323,14 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent if (rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_copy(CTX_wm_area(C), CTX_wm_region(C)); - + + /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, + * when switching camera in quad-view the other ortho views would zoom & reset. */ +#if 0 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); +#else + ED_region_tag_redraw(CTX_wm_region(C)); +#endif return OPERATOR_FINISHED; } @@ -1028,7 +1034,8 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL { View3D *v3d = sa->spacedata.first; Base *base; - float size = 0.0, min[3], max[3], box[3]; + float min[3], max[3], box[3]; + float size = 0.0f, size_persp = 0.0f, size_ortho = 0.0f; unsigned int locallay; int ok = FALSE; @@ -1068,7 +1075,13 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL box[1] = (max[1] - min[1]); box[2] = (max[2] - min[2]); size = MAX3(box[0], box[1], box[2]); - if (size <= 0.01f) size = 0.01f; + + /* do not zoom closer than the near clipping plane */ + size = max_ff(size, v3d->near * 1.5f); + + /* perspective size (we always switch out of camera view so no need to use its lens size) */ + size_persp = ED_view3d_radius_to_persp_dist(focallength_to_fov(v3d->lens, DEFAULT_SENSOR_WIDTH), size / 2.0f) * VIEW3D_MARGIN; + size_ortho = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN; } if (ok == TRUE) { @@ -1085,14 +1098,20 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region"); memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D)); - rv3d->ofs[0] = -(min[0] + max[0]) / 2.0f; - rv3d->ofs[1] = -(min[1] + max[1]) / 2.0f; - rv3d->ofs[2] = -(min[2] + max[2]) / 2.0f; + mid_v3_v3v3(v3d->cursor, min, max); + negate_v3_v3(rv3d->ofs, v3d->cursor); + + if (rv3d->persp == RV3D_CAMOB) { + rv3d->persp = RV3D_PERSP; + } - rv3d->dist = size; /* perspective should be a bit farther away to look nice */ - if (rv3d->persp == RV3D_ORTHO) - rv3d->dist *= 0.7f; + if (rv3d->persp != RV3D_ORTHO) { + rv3d->dist = size_persp; + } + else { + rv3d->dist = size_ortho; + } /* correction for window aspect ratio */ if (ar->winy > 2 && ar->winx > 2) { @@ -1100,12 +1119,6 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL if (asp < 1.0f) asp = 1.0f / asp; rv3d->dist *= asp; } - - if (rv3d->persp == RV3D_CAMOB) rv3d->persp = RV3D_PERSP; - - v3d->cursor[0] = -rv3d->ofs[0]; - v3d->cursor[1] = -rv3d->ofs[1]; - v3d->cursor[2] = -rv3d->ofs[2]; } } @@ -1511,7 +1524,7 @@ static void UNUSED_FUNCTION(view3d_align_axis_to_vector)(View3D *v3d, RegionView } } -float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]) +float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3]) { return (rv3d->persmat[3][3] + ( rv3d->persmat[0][3] * co[0] + @@ -1520,6 +1533,16 @@ float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]) ) * rv3d->pixsize; } +float ED_view3d_radius_to_persp_dist(const float angle, const float radius) +{ + return (radius / 2.0f) * fabsf(1.0f / cosf((((float)M_PI) - angle) / 2.0f)); +} + +float ED_view3d_radius_to_ortho_dist(const float lens, const float radius) +{ + return radius / (DEFAULT_SENSOR_WIDTH / lens); +} + /* view matrix properties utilities */ /* unused */ diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 05a4f6f4ce5..ec114bc3019 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blenloader ../../bmesh + ../../ikplugin ../../makesdna ../../makesrna ../../windowmanager diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript index dbf6179035c..9cf36a2d970 100644 --- a/source/blender/editors/transform/SConscript +++ b/source/blender/editors/transform/SConscript @@ -6,7 +6,7 @@ sources = env.Glob('*.c') incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../render/extern/include' -incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh' +incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh ../../ikplugin' defs = [] diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 245241763fd..6145fec7e51 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -526,6 +526,10 @@ static void viewRedrawPost(bContext *C, TransInfo *t) /* if autokeying is enabled, send notifiers that keyframes were added */ if (IS_AUTOKEY_ON(t->scene)) WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* redraw UV editor */ + if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); /* XXX temp, first hack to get auto-render in compositor work (ton) */ WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C)); @@ -1223,8 +1227,10 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case LEFTALTKEY: case RIGHTALTKEY: - if (t->spacetype == SPACE_SEQ) + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { t->flag |= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } break; default: @@ -1262,8 +1268,10 @@ int transformEvent(TransInfo *t, wmEvent *event) // break; case LEFTALTKEY: case RIGHTALTKEY: - if (t->spacetype == SPACE_SEQ) + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { t->flag &= ~T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } break; default: @@ -2419,6 +2427,8 @@ static void constraintSizeLim(TransInfo *t, TransData *td) bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT); bConstraintOb cob = {NULL}; bConstraint *con; + float size_sign[3], size_abs[3]; + int i; /* Make a temporary bConstraintOb for using these limit constraints * - they only care that cob->matrix is correctly set ;-) @@ -2432,8 +2442,14 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* Reset val if SINGLESIZE but using a constraint */ if (td->flag & TD_SINGLESIZE) return; + + /* separate out sign to apply back later */ + for (i = 0; i < 3; i++) { + size_sign[i] = signf(td->ext->size[i]); + size_abs[i] = fabsf(td->ext->size[i]); + } - size_to_mat4(cob.matrix, td->ext->size); + size_to_mat4(cob.matrix, size_abs); } /* Evaluate valid constraints */ @@ -2481,7 +2497,9 @@ static void constraintSizeLim(TransInfo *t, TransData *td) if (td->flag & TD_SINGLESIZE) return; + /* extrace scale from matrix and apply back sign */ mat4_to_size(td->ext->size, cob.matrix); + mul_v3_v3(td->ext->size, size_sign); } } } @@ -2852,11 +2870,21 @@ static void headerResize(TransInfo *t, float vec[3], char *str) (void)spos; } -#define SIGN(a) (a<-FLT_EPSILON ? 1 : a>FLT_EPSILON ? 2 : 3) -#define VECSIGNFLIP(a, b) ((SIGN(a[0]) & SIGN(b[0])) == 0 || (SIGN(a[1]) & SIGN(b[1])) == 0 || (SIGN(a[2]) & SIGN(b[2])) == 0) +/* FLT_EPSILON is too small [#29633], 0.0000001f starts to flip */ +#define TX_FLIP_EPS 0.00001f +BLI_INLINE int tx_sign(const float a) +{ + return (a < -TX_FLIP_EPS ? 1 : a > TX_FLIP_EPS ? 2 : 3); +} +BLI_INLINE int tx_vec_sign_flip(const float a[3], const float b[3]) +{ + return ((tx_sign(a[0]) & tx_sign(b[0])) == 0 || + (tx_sign(a[1]) & tx_sign(b[1])) == 0 || + (tx_sign(a[2]) & tx_sign(b[2])) == 0); +} /* smat is reference matrix, only scaled */ -static void TransMat3ToSize(float mat[][3], float smat[][3], float *size) +static void TransMat3ToSize(float mat[][3], float smat[][3], float size[3]) { float vec[3]; @@ -2868,9 +2896,9 @@ static void TransMat3ToSize(float mat[][3], float smat[][3], float *size) size[2] = normalize_v3(vec); /* first tried with dotproduct... but the sign flip is crucial */ - if (VECSIGNFLIP(mat[0], smat[0]) ) size[0] = -size[0]; - if (VECSIGNFLIP(mat[1], smat[1]) ) size[1] = -size[1]; - if (VECSIGNFLIP(mat[2], smat[2]) ) size[2] = -size[2]; + if (tx_vec_sign_flip(mat[0], smat[0]) ) size[0] = -size[0]; + if (tx_vec_sign_flip(mat[1], smat[1]) ) size[1] = -size[1]; + if (tx_vec_sign_flip(mat[2], smat[2]) ) size[2] = -size[2]; } @@ -3947,10 +3975,8 @@ void initShrinkFatten(TransInfo *t) } - int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3]; float distance; int i; char str[64]; @@ -3978,17 +4004,20 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = -distance; for (i = 0; i < t->total; i++, td++) { + float tdistance; /* temp dist */ if (td->flag & TD_NOACTION) break; if (td->flag & TD_SKIP) continue; - copy_v3_v3(vec, td->axismtx[2]); - mul_v3_fl(vec, distance); - mul_v3_fl(vec, td->factor); + /* get the final offset */ + tdistance = distance * td->factor; + if (td->ext && (t->flag & T_ALT_TRANSFORM)) { + tdistance *= td->ext->isize[0]; /* shell factor */ + } - add_v3_v3v3(td->loc, td->iloc, vec); + madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); } recalcData(t); @@ -4847,14 +4876,9 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo float dist = 0; float min_dist = FLT_MAX; - float up_p[3]; - float dw_p[3]; - for (i = 0; i < sld->totsv; i++, sv++) { /* Set length */ - add_v3_v3v3(up_p, sv->origvert.co, sv->upvec); - add_v3_v3v3(dw_p, sv->origvert.co, sv->downvec); - sv->edge_len = len_v3v3(dw_p, up_p); + sv->edge_len = len_v3v3(sv->upvec, sv->downvec); mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co); if (ED_view3d_project_float_global(t->ar, v_proj, v_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { @@ -5595,7 +5619,6 @@ static int doEdgeSlide(TransInfo *t, float perc) { SlideData *sld = t->customData; TransDataSlideVert *svlist = sld->sv, *sv; - float vec[3]; int i; sld->perc = perc; @@ -5603,6 +5626,7 @@ static int doEdgeSlide(TransInfo *t, float perc) if (sld->is_proportional == TRUE) { for (i = 0; i < sld->totsv; i++, sv++) { + float vec[3]; if (perc > 0.0f) { copy_v3_v3(vec, sv->upvec); mul_v3_fl(vec, perc); @@ -5620,20 +5644,29 @@ static int doEdgeSlide(TransInfo *t, float perc) * Implementation note, non proportional mode ignores the starting positions and uses only the * up/down verts, this could be changed/improved so the distance is still met but the verts are moved along * their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell + * + * \note len_v3v3(curr_sv->upvec, curr_sv->downvec) + * is the same as the distance between the original vert locations, same goes for the lines below. */ TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float curr_length_perc = len_v3v3(curr_sv->up->co, curr_sv->down->co) * - (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f); + const float curr_length_perc = curr_sv->edge_len * (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f); + + float down_co[3]; + float up_co[3]; for (i = 0; i < sld->totsv; i++, sv++) { - const float sv_length = len_v3v3(sv->up->co, sv->down->co); - const float fac = min_ff(sv_length, curr_length_perc) / sv_length; + if (sv->edge_len > FLT_EPSILON) { + const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len; - if (sld->flipped_vtx) { - interp_v3_v3v3(sv->v->co, sv->down->co, sv->up->co, fac); - } - else { - interp_v3_v3v3(sv->v->co, sv->up->co, sv->down->co, fac); + add_v3_v3v3(up_co, sv->origvert.co, sv->upvec); + add_v3_v3v3(down_co, sv->origvert.co, sv->downvec); + + if (sld->flipped_vtx) { + interp_v3_v3v3(sv->v->co, down_co, up_co, fac); + } + else { + interp_v3_v3v3(sv->v->co, up_co, down_co, fac); + } } } } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 1f9775821d1..bc959a772d6 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -197,6 +197,7 @@ typedef struct TransDataSlideVert { float edge_len; + /* add origvert.co to get the original locations */ float upvec[3], downvec[3]; int loop_nr; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 311cb5ee94d..947bdf53bee 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -150,8 +150,8 @@ static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3]) if (hasNumInput(&t->num)) { applyNumInput(&t->num, vec); - removeAspectRatio(t, vec); constraintNumInput(t, vec); + removeAspectRatio(t, vec); } /* autovalues is operator param, use that directly but not if snapping is forced */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f6b888d4881..51efa2b0e40 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -91,6 +91,7 @@ #include "BKE_tracking.h" #include "BKE_mask.h" +#include "BIK_api.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -773,6 +774,9 @@ static void pose_grab_with_ik_clear(Object *ob) if (con->type == CONSTRAINT_TYPE_KINEMATIC) { data = con->data; if (data->flag & CONSTRAINT_IK_TEMP) { + /* iTaSC needs clear for removed constraints */ + BIK_clear_data(ob->pose); + BLI_remlink(&pchan->constraints, con); MEM_freeN(con->data); MEM_freeN(con); @@ -839,7 +843,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) } else data->flag = CONSTRAINT_IK_TIP; - data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO; + data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS; copy_v3_v3(data->grabtarget, pchan->pose_tail); data->rootbone = 0; /* watch-it! has to be 0 here, since we're still on the same bone for the first time through the loop [#25885] */ @@ -933,6 +937,10 @@ static short pose_grab_with_ik(Object *ob) } } + /* iTaSC needs clear for new IK constraints */ + if (tot_ik) + BIK_clear_data(ob->pose); + return (tot_ik) ? 1 : 0; } @@ -1917,6 +1925,10 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx tx->size = vs->radius; td->val = vs->radius; } + else if (t->mode == TFM_SHRINKFATTEN) { + td->ext = tx; + tx->isize[0] = BM_vert_calc_shell_factor(eve); + } } static void createTransEditVerts(TransInfo *t) @@ -2029,7 +2041,11 @@ static void createTransEditVerts(TransInfo *t) else t->total = countsel; tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)"); - if (t->mode == TFM_SKIN_RESIZE) { + if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) { + /* warning, this is overkill, we only need 2 extra floats, + * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill + * since we may not use the 'alt' transform mode to maintain shell thickness, + * but with generic transform code its hard to lazy init vars */ tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "TransObData ext"); } @@ -2478,7 +2494,7 @@ int clipUVTransform(TransInfo *t, float *vec, int resize) max[0] = aspx; max[1] = aspy; for (a = 0, td = t->data; a < t->total; a++, td++) { - DO_MINMAX2(td->loc, min, max); + minmax_v2v2_v2(min, max, td->loc); } if (resize) { @@ -5029,9 +5045,10 @@ static void special_aftertrans_update__mask(bContext *C, TransInfo *t) if (t->scene->nodetree) { /* tracks can be used for stabilization nodes, * flush update for such nodes */ - //if (nodeUpdateID(t->scene->nodetree, &mask->id)) { + //if (nodeUpdateID(t->scene->nodetree, &mask->id)) + { WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id); - //} + } } /* TODO - dont key all masks... */ diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 0780b8f90b5..a3f45acc02e 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -744,7 +744,7 @@ static char axisBlendAngle(float angle) return (char)(255.0f * (angle - 5) / 15.0f); } -/* three colors can be set; +/* three colors can be set: * gray for ghosting * moving: in transform theme color * else the red/green/blue @@ -776,15 +776,13 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned c } break; case 'X': - col[0] = 220; + UI_GetThemeColor3ubv(TH_AXIS_X, col); break; case 'Y': - col[1] = 220; + UI_GetThemeColor3ubv(TH_AXIS_Y, col); break; case 'Z': - col[0] = 30; - col[1] = 30; - col[2] = 220; + UI_GetThemeColor3ubv(TH_AXIS_Z, col); break; default: BLI_assert(!"invalid axis arg"); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index a6fb7e7ed00..2d95e2ecdc6 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -408,9 +408,15 @@ static void initSnappingMode(TransInfo *t) t->tsnap.mode = ts->snap_node_mode; } + else if (t->spacetype == SPACE_IMAGE) { + /* force project off when not supported */ + t->tsnap.project = 0; + + t->tsnap.mode = ts->snap_uv_mode; + } else { /* force project off when not supported */ - if (t->spacetype == SPACE_IMAGE || ts->snap_mode != SCE_SNAP_MODE_FACE) + if (ts->snap_mode != SCE_SNAP_MODE_FACE) t->tsnap.project = 0; t->tsnap.mode = ts->snap_mode; diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index b73f5fa0869..0ec16ead35d 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -130,6 +130,9 @@ short hasNumInput(NumInput *n) return 0; } +/** + * \warning \a vec must be set beforehand otherwise we risk uninitialized vars. + */ void applyNumInput(NumInput *n, float *vec) { short i, j; diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c index fa39a52444b..1c32c01b8f0 100644 --- a/source/blender/editors/uvedit/uvedit_buttons.c +++ b/source/blender/editors/uvedit/uvedit_buttons.c @@ -94,14 +94,19 @@ static int uvedit_center(Scene *scene, BMEditMesh *em, Image *ima, float center[ return tot; } -static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *UNUSED(ima), float delta[2]) +static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *ima, float delta[2]) { BMFace *f; BMLoop *l; BMIter iter, liter; MLoopUV *luv; + MTexPoly *tf; BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { + tf = CustomData_bmesh_get(&em->bm->pdata, f->head.data, CD_MTEXPOLY); + if (!uvedit_face_visible_test(scene, ima, f, tf)) + continue; + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); if (uvedit_uv_select_test(em, scene, l)) { diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index e860d486ea3..a384c777aab 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -224,7 +224,9 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if (uvedit_face_visible_test(scene, previma, efa, tf)) { + if (uvedit_face_visible_test(scene, previma, efa, tf) && + (selected == TRUE || uvedit_face_select_test(scene, em, efa))) + { if (ima) { tf->tpage = ima; @@ -616,7 +618,7 @@ int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], f BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - DO_MINMAX2(luv->uv, r_min, r_max); + minmax_v2v2_v2(r_min, r_max, luv->uv); sel = 1; } } @@ -1327,7 +1329,7 @@ static void weld_align_uv(bContext *C, int tool) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - DO_MINMAX2(luv->uv, min, max); + minmax_v2v2_v2(min, max, luv->uv); } } } @@ -1553,7 +1555,170 @@ static void UV_OT_align(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on"); } +/* ******************** weld near operator **************** */ +typedef struct UVvert { + MLoopUV *uv_loop; + int weld; +} UVvert; + +static int remove_doubles_exec(bContext *C, wmOperator *op) +{ + const float threshold = RNA_float_get(op->ptr, "threshold"); + const int use_unselected = RNA_boolean_get(op->ptr, "use_unselected"); + + SpaceImage *sima; + Scene *scene; + Object *obedit; + Image *ima; + BMEditMesh *em; + MTexPoly *tf; + int uv_a_index; + int uv_b_index; + float *uv_a; + float *uv_b; + + BMIter iter, liter; + BMFace *efa; + BMLoop *l; + + sima = CTX_wm_space_image(C); + scene = CTX_data_scene(C); + obedit = CTX_data_edit_object(C); + em = BMEdit_FromObject(obedit); + ima = CTX_data_edit_image(C); + + if (use_unselected == FALSE) { + UVvert *vert_arr = NULL; + BLI_array_declare(vert_arr); + MLoopUV **loop_arr = NULL; + BLI_array_declare(loop_arr); + + /* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!uvedit_face_visible_test(scene, ima, efa, tf)) + continue; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (uvedit_uv_select_test(em, scene, l)) { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + UVvert vert; + vert.uv_loop = luv; + vert.weld = FALSE; + BLI_array_append(vert_arr, vert); + } + + } + } + + for (uv_a_index = 0; uv_a_index < BLI_array_count(vert_arr); uv_a_index++) { + if (vert_arr[uv_a_index].weld == FALSE) { + float uv_min[2]; + float uv_max[2]; + + BLI_array_empty(loop_arr); + BLI_array_append(loop_arr, vert_arr[uv_a_index].uv_loop); + + uv_a = vert_arr[uv_a_index].uv_loop->uv; + + copy_v2_v2(uv_max, uv_a); + copy_v2_v2(uv_min, uv_a); + + vert_arr[uv_a_index].weld = TRUE; + for (uv_b_index = uv_a_index + 1; uv_b_index < BLI_array_count(vert_arr); uv_b_index++) { + uv_b = vert_arr[uv_b_index].uv_loop->uv; + if ((vert_arr[uv_b_index].weld == FALSE) && + (len_manhattan_v2v2(uv_a, uv_b) < threshold)) + { + minmax_v2v2_v2(uv_max, uv_min, uv_b); + BLI_array_append(loop_arr, vert_arr[uv_b_index].uv_loop); + vert_arr[uv_b_index].weld = TRUE; + } + } + if (BLI_array_count(loop_arr)) { + float uv_mid[2]; + mid_v2_v2v2(uv_mid, uv_min, uv_max); + for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr); uv_b_index++) { + copy_v2_v2(loop_arr[uv_b_index]->uv, uv_mid); + } + } + } + } + + BLI_array_free(vert_arr); + BLI_array_free(loop_arr); + } + else { + /* selected -> unselected + * + * No need to use 'UVvert' here */ + MLoopUV **loop_arr = NULL; + BLI_array_declare(loop_arr); + MLoopUV **loop_arr_unselected = NULL; + BLI_array_declare(loop_arr_unselected); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!uvedit_face_visible_test(scene, ima, efa, tf)) + continue; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + if (uvedit_uv_select_test(em, scene, l)) { + BLI_array_append(loop_arr, luv); + } + else { + BLI_array_append(loop_arr_unselected, luv); + } + } + } + + for (uv_a_index = 0; uv_a_index < BLI_array_count(loop_arr); uv_a_index++) { + float dist_best = FLT_MAX, dist; + float *uv_best = NULL; + + uv_a = loop_arr[uv_a_index]->uv; + for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr_unselected); uv_b_index++) { + uv_b = loop_arr_unselected[uv_b_index]->uv; + dist = len_manhattan_v2v2(uv_a, uv_b); + if ((dist < threshold) && (dist < dist_best)) { + uv_best = uv_b; + dist_best = dist; + } + } + if (uv_best) { + copy_v2_v2(uv_a, uv_best); + } + } + + BLI_array_free(loop_arr); + BLI_array_free(loop_arr_unselected); + } + + uvedit_live_unwrap_update(sima, scene, obedit); + DAG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +static void UV_OT_remove_doubles(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Doubles UV"; + ot->description = "Selected UV vertices that are within a radius of each other are welded together"; + ot->idname = "UV_OT_remove_doubles"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = remove_doubles_exec; + ot->poll = ED_operator_uvedit; + + RNA_def_float(ot->srna, "threshold", 0.02f, 0.0f, 10.0f, + "Merge Distance", "Maximum distance between welded vertices", 0.0f, 1.0f); + RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices"); +} /* ******************** weld operator **************** */ static int weld_exec(bContext *C, wmOperator *UNUSED(op)) @@ -2504,10 +2669,12 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - if (select) + if (select) { uvedit_face_select_enable(scene, em, efa, FALSE); - else + } + else { uvedit_face_select_disable(scene, em, efa); + } } } } @@ -2529,7 +2696,10 @@ static int border_select_exec(bContext *C, wmOperator *op) MLoopUV *luv; rcti rect; rctf rectf; - int change, pinned, select, faces, extend; + int change, pinned, select, extend; + const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE); /* get rectangle from operator */ WM_operator_properties_border_to_rcti(op, &rect); @@ -2544,14 +2714,9 @@ static int border_select_exec(bContext *C, wmOperator *op) if (!extend) select_all_perform(scene, ima, em, SEL_DESELECT); - - if (ts->uv_flag & UV_SYNC_SELECTION) - faces = (ts->selectmode == SCE_SELECT_FACE); - else - faces = (ts->uv_selectmode == UV_SELECT_FACE); /* do actual selection */ - if (faces && !pinned) { + if (use_face_center && !pinned) { /* handle face selection mode */ float cent[2]; @@ -2572,8 +2737,9 @@ static int border_select_exec(bContext *C, wmOperator *op) } /* (de)selects all tagged faces and deals with sticky modes */ - if (change) + if (change) { uv_faces_do_sticky(sima, scene, obedit, select); + } } else { /* other selection modes */ @@ -2642,19 +2808,19 @@ static void UV_OT_select_border(wmOperatorType *ot) /* ******************** circle select operator **************** */ -static int select_uv_inside_ellipse(BMEditMesh *em, SpaceImage *UNUSED(sima), Scene *scene, int select, - float *offset, float *ell, BMLoop *l, MLoopUV *luv) +static int uv_inside_circle(const float uv[2], const float offset[2], const float ellipse[2]) { /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ - float x, y, r2, *uv; + float x, y; + x = (uv[0] - offset[0]) * ellipse[0]; + y = (uv[1] - offset[1]) * ellipse[1]; + return ((x * x + y * y) < 1.0f); +} - uv = luv->uv; - - x = (uv[0] - offset[0]) * ell[0]; - y = (uv[1] - offset[1]) * ell[1]; - - r2 = x * x + y * y; - if (r2 < 1.0f) { +static int select_uv_inside_ellipse(BMEditMesh *em, Scene *scene, const int select, + const float offset[2], const float ellipse[2], BMLoop *l, MLoopUV *luv) +{ + if (uv_inside_circle(luv->uv, offset, ellipse)) { if (select) uvedit_uv_select_enable(em, scene, l, FALSE); else uvedit_uv_select_disable(em, scene, l); return TRUE; @@ -2680,6 +2846,9 @@ static int circle_select_exec(bContext *C, wmOperator *op) float zoomx, zoomy, offset[2], ellipse[2]; int gesture_mode = RNA_int_get(op->ptr, "gesture_mode"); int change = FALSE; + const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE); /* get operator properties */ select = (gesture_mode == GESTURE_MODAL_SELECT); @@ -2698,10 +2867,32 @@ static int circle_select_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]); /* do selection */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - change |= select_uv_inside_ellipse(em, sima, scene, select, offset, ellipse, l, luv); + if (use_face_center) { + change = FALSE; + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(efa, BM_ELEM_TAG); + /* assume not touched */ + if ((select) != (uvedit_face_select_test(scene, em, efa))) { + float cent[2]; + uv_poly_center(em, efa, cent); + if (uv_inside_circle(cent, offset, ellipse)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + change = TRUE; + } + } + } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (change) { + uv_faces_do_sticky(sima, scene, obedit, select); + } + } + else { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + change |= select_uv_inside_ellipse(em, scene, select, offset, ellipse, l, luv); + } } } @@ -2743,12 +2934,16 @@ static void UV_OT_circle_select(wmOperatorType *ot) static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves, short select) { + SpaceImage *sima = CTX_wm_space_image(C); Image *ima = CTX_data_edit_image(C); ARegion *ar = CTX_wm_region(C); Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; BMEditMesh *em = BMEdit_FromObject(obedit); + const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE); BMIter iter, liter; @@ -2760,9 +2955,10 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov BLI_lasso_boundbox(&rect, mcords, moves); - if (ts->uv_selectmode == UV_SELECT_FACE) { /* Face Center Sel */ + if (use_face_center) { /* Face Center Sel */ change = FALSE; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(efa, BM_ELEM_TAG); /* assume not touched */ if ((select) != (uvedit_face_select_test(scene, em, efa))) { float cent[2]; @@ -2771,11 +2967,16 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov if (BLI_rcti_isect_pt_v(&rect, screen_uv) && BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { - uvedit_face_select_enable(scene, em, efa, FALSE); + BM_elem_flag_enable(efa, BM_ELEM_TAG); change = TRUE; } } } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (change) { + uv_faces_do_sticky(sima, scene, obedit, select); + } } else { /* Vert Sel */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -3232,7 +3433,7 @@ static int hide_exec(bContext *C, wmOperator *op) MTexPoly *tf; int swap = RNA_boolean_get(op->ptr, "unselected"); Image *ima = sima ? sima->image : NULL; - int facemode = (ts->uv_selectmode == UV_SELECT_FACE); + const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_hide(em, swap); @@ -3262,7 +3463,7 @@ static int hide_exec(bContext *C, wmOperator *op) if (hide) { /* note, a special case for edges could be used, * for now edges act like verts and get flushed */ - if (facemode) { + if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { /* check that every UV is selected */ if (bm_face_is_all_uv_sel(em->bm, efa, TRUE) == !swap) { @@ -3280,8 +3481,6 @@ static int hide_exec(bContext *C, wmOperator *op) } } if (!swap) uvedit_face_select_disable(scene, em, efa); - - } } else if (em->selectmode == SCE_SELECT_FACE) { @@ -3344,8 +3543,8 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) BMLoop *l; BMIter iter, liter; MLoopUV *luv; - int facemode = (ts->uv_selectmode == UV_SELECT_FACE); - int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; + const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); + const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and * confuse our checks on selected verts. */ @@ -3357,7 +3556,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } - if (facemode) { + if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_elem_flag_disable(efa, BM_ELEM_TAG); @@ -3776,6 +3975,7 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_seams_from_islands); WM_operatortype_append(UV_OT_mark_seam); WM_operatortype_append(UV_OT_weld); + WM_operatortype_append(UV_OT_remove_doubles); WM_operatortype_append(UV_OT_pin); WM_operatortype_append(UV_OT_average_islands_scale); diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 5b6125b558b..8703234122a 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -450,7 +450,7 @@ static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2]) INIT_MINMAX2(minv, maxv); for (v = chart->verts; v; v = v->nextlink) { - DO_MINMAX2(v->uv, minv, maxv); + minmax_v2v2_v2(minv, maxv, v->uv); } } @@ -3891,9 +3891,9 @@ static void p_smooth(PChart *chart) INIT_MINMAX2(fmin, fmax); - DO_MINMAX2(e1->vert->uv, fmin, fmax); - DO_MINMAX2(e2->vert->uv, fmin, fmax); - DO_MINMAX2(e3->vert->uv, fmin, fmax); + minmax_v2v2_v2(fmin, fmax, e1->vert->uv); + minmax_v2v2_v2(fmin, fmax, e2->vert->uv); + minmax_v2v2_v2(fmin, fmax, e3->vert->uv); bx1 = (int)((fmin[0] - minv[0]) * invmedian); by1 = (int)((fmin[1] - minv[1]) * invmedian); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index b1945c37048..4ca642690c4 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1072,17 +1072,23 @@ static int stitch_init(bContext *C, wmOperator *op) BMEditMesh *em; GHashIterator *ghi; UvEdge *all_edges; - StitchState *state = MEM_mallocN(sizeof(StitchState), "stitch state"); + StitchState *state; Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; + ARegion *ar = CTX_wm_region(C); Object *obedit = CTX_data_edit_object(C); - op->customdata = state; + if (!ar) + return 0; + + state = MEM_mallocN(sizeof(StitchState), "stitch state"); if (!state) return 0; + op->customdata = state; + /* initialize state */ state->use_limit = RNA_boolean_get(op->ptr, "use_limit"); state->limit_dist = RNA_float_get(op->ptr, "limit"); @@ -1091,7 +1097,7 @@ static int stitch_init(bContext *C, wmOperator *op) state->static_island = RNA_int_get(op->ptr, "static_island"); state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap"); state->clear_seams = RNA_boolean_get(op->ptr, "clear_seams"); - state->draw_handle = ED_region_draw_cb_activate(CTX_wm_region(C)->type, stitch_draw, NULL, REGION_DRAW_POST_VIEW); + state->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, NULL, REGION_DRAW_POST_VIEW); /* in uv synch selection, all uv's are visible */ if (ts->uv_flag & UV_SYNC_SELECTION) { state->element_map = EDBM_uv_element_map_create(state->em, 0, 1); @@ -1444,18 +1450,22 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event) } case PADENTER: case RETKEY: - if (stitch_process_data(stitch_state, scene, 1)) { - stitch_exit(C, op, 1); - return OPERATOR_FINISHED; + if (event->val == KM_PRESS) { + if (stitch_process_data(stitch_state, scene, 1)) { + stitch_exit(C, op, 1); + return OPERATOR_FINISHED; + } + else { + return stitch_cancel(C, op); + } } else { - return stitch_cancel(C, op); + return OPERATOR_PASS_THROUGH; } - /* Increase limit */ case PADPLUSKEY: case WHEELUPMOUSE: - if (event->alt) { + if (event->val == KM_PRESS && event->alt) { stitch_state->limit_dist += 0.01f; if (!stitch_process_data(stitch_state, scene, 0)) { return stitch_cancel(C, op); @@ -1468,7 +1478,7 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event) /* Decrease limit */ case PADMINUS: case WHEELDOWNMOUSE: - if (event->alt) { + if (event->val == KM_PRESS && event->alt) { stitch_state->limit_dist -= 0.01f; stitch_state->limit_dist = MAX2(0.01f, stitch_state->limit_dist); if (!stitch_process_data(stitch_state, scene, 0)) { diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index f615902eedf..1f3f21967f4 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -232,7 +232,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh BLI_srand(0); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first; + ScanFillVert *sf_vert = NULL, *sf_vert_last, *sf_vert_first; ScanFillFace *sf_tri; ParamKey key, vkeys[4]; ParamBool pin[4], select[4]; @@ -306,7 +306,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); - BLI_scanfill_calc_ex(&sf_ctx, TRUE, efa->no); + BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { int i; ls[0] = sf_tri->v1->tmp.p; @@ -1089,7 +1089,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - DO_MINMAX2(luv->uv, min, max); + minmax_v2v2_v2(min, max, luv->uv); } } @@ -1414,7 +1414,7 @@ static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf)) BMIter liter; MLoopUV *luv; float **uvs = NULL; - BLI_array_fixedstack_declare(uvs, BM_NGON_STACK_SIZE, efa->len, __func__); + BLI_array_fixedstack_declare(uvs, BM_DEFAULT_NGON_STACK_SIZE, efa->len, __func__); float dx; int i, mi; diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 97e8b756d08..c46230de8bf 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -110,7 +110,6 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data); GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int isdata); GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data); -GPUNodeLink *GPU_socket(GPUNodeStack *sock); GPUNodeLink *GPU_builtin(GPUBuiltin builtin); int GPU_link(GPUMaterial *mat, const char *name, ...); diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index f7ed9effc7a..9b8a86eac15 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -27,7 +27,6 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"), )) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index b4490e656f3..4432627ee7e 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -1148,15 +1148,6 @@ GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data) return link; } -GPUNodeLink *GPU_socket(GPUNodeStack *sock) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->socket= sock; - - return link; -} - GPUNodeLink *GPU_builtin(GPUBuiltin builtin) { GPUNodeLink *link = GPU_node_link_create(0); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7bd72430969..d466e59452b 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -318,7 +318,7 @@ static void gpu_make_repbind(Image *ima) { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf==NULL) return; @@ -333,6 +333,8 @@ static void gpu_make_repbind(Image *ima) if (ima->totbind>1) ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); + + BKE_image_release_ibuf(ima, ibuf, NULL); } static void gpu_clear_tpage(void) @@ -479,7 +481,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int return 0; /* check if we have a valid image buffer */ - ibuf= BKE_image_get_ibuf(ima, iuser); + ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf==NULL) return 0; @@ -574,6 +576,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (*bind != 0) { /* enable opengl drawing with textures */ glBindTexture(GL_TEXTURE_2D, *bind); + BKE_image_release_ibuf(ima, ibuf, NULL); return *bind; } @@ -635,6 +638,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (srgb_frect) MEM_freeN(srgb_frect); + BKE_image_release_ibuf(ima, ibuf, NULL); + return *bind; } @@ -722,8 +727,8 @@ int GPU_upload_dxt_texture(ImBuf *ibuf) GLint format = 0; int blocksize, height, width, i, size, offset = 0; - height = ibuf->x; - width = ibuf->y; + width = ibuf->x; + height = ibuf->y; if (GLEW_EXT_texture_compression_s3tc) { if (ibuf->dds_data.fourcc == FOURCC_DXT1) @@ -896,7 +901,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf || (!is_power_of_2_i(ibuf->x) || !is_power_of_2_i(ibuf->y)) || @@ -935,6 +940,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } + BKE_image_release_ibuf(ima, ibuf, NULL); return; } @@ -959,6 +965,8 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } void GPU_update_images_framechange(void) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index cef664437b7..7a0ac29c9ab 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -253,6 +253,9 @@ static void GPU_print_framebuffer_error(GLenum status, char err_out[256]) switch (status) { case GL_FRAMEBUFFER_COMPLETE_EXT: break; + case GL_INVALID_OPERATION: + err= "Invalid operation"; + break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: err= "Incomplete attachment"; break; @@ -754,6 +757,7 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err { GLenum status; GLenum attachment; + GLenum error; if (tex->depth) attachment = GL_DEPTH_ATTACHMENT_EXT; @@ -766,6 +770,14 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, tex->target, tex->bindcode, 0); + error = glGetError(); + + if (error == GL_INVALID_OPERATION) { + GPU_framebuffer_restore(); + GPU_print_framebuffer_error(error, err_out); + return 0; + } + if (tex->depth) { glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index ef73764753c..9c48f74bf5f 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1165,13 +1165,14 @@ static void do_material_tex(GPUShadeInput *shi) // resolve texture resolution if ( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) { - ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf= BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only if (ibuf) { ima_x= ibuf->x; ima_y= ibuf->y; aspect = ((float) ima_y) / ima_x; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } // The negate on norfac is done because the @@ -1496,6 +1497,16 @@ static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) return shr.combined; } +static GPUNodeLink *gpu_material_diffuse_bsdf(GPUMaterial *mat, Material *ma) +{ + static float roughness = 0.0f; + GPUNodeLink *outlink; + + GPU_link(mat, "node_bsdf_diffuse", GPU_uniform(&ma->r), GPU_uniform(&roughness), GPU_builtin(GPU_VIEW_NORMAL), &outlink); + + return outlink; +} + GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) { GPUMaterial *mat; @@ -1515,8 +1526,15 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) ntreeGPUMaterialNodes(ma->nodetree, mat); } else { - /* create material */ - outlink = GPU_blender_material(mat, ma); + if(BKE_scene_use_new_shading_nodes(scene)) { + /* create simple diffuse material instead of nodes */ + outlink = gpu_material_diffuse_bsdf(mat, ma); + } + else { + /* create blender material */ + outlink = GPU_blender_material(mat, ma); + } + GPU_material_output_link(mat, outlink); } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index b930058864c..9a238e979fa 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -4,6 +4,21 @@ float exp_blender(float f) return pow(2.71828182846, f); } +float compatible_pow(float x, float y) +{ + /* glsl pow doesn't accept negative x */ + if(x < 0.0) { + if(mod(-y, 2.0) == 0.0) + return pow(-x, y); + else + return -pow(-x, y); + } + else if(x == 0.0) + return 0.0; + + return pow(x, y); +} + void rgb_to_hsv(vec4 rgb, out vec4 outcol) { float cmax, cmin, h, s, v, cdelta; @@ -212,10 +227,17 @@ void math_atan(float val, out float outval) void math_pow(float val1, float val2, out float outval) { - if (val1 >= 0.0) - outval = pow(val1, val2); - else - outval = 0.0; + if (val1 >= 0.0) { + outval = compatible_pow(val1, val2); + } + else { + float val2_mod_1 = mod(abs(val2), 1.0); + + if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) + outval = compatible_pow(val1, floor(val2 + 0.5)); + else + outval = 0.0; + } } void math_log(float val1, float val2, out float outval) diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl index a86431bdd7a..574455e42b3 100644 --- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl @@ -10,3 +10,11 @@ void main() varnormal = normalize(gl_NormalMatrix * gl_Normal); gl_Position = gl_ProjectionMatrix * co; + // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA graphic cards. + // gl_ClipVertex works only on NVIDIA graphic cards so we have to check with + // __GLSL_CG_DATA_TYPES if a NVIDIA graphic card is used (Cg support). + // gl_ClipVerte is supported up to GLSL 1.20. + #ifdef __GLSL_CG_DATA_TYPES + gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; + #endif + diff --git a/source/blender/ikplugin/intern/ikplugin_api.c b/source/blender/ikplugin/intern/ikplugin_api.c index 08d2789451c..507d54d7526 100644 --- a/source/blender/ikplugin/intern/ikplugin_api.c +++ b/source/blender/ikplugin/intern/ikplugin_api.c @@ -79,12 +79,14 @@ static IKPlugin ikplugin_tab[] = { itasc_update_param, itasc_test_constraint, }, - #endif +#endif + + { NULL } }; static IKPlugin *get_plugin(bPose *pose) { - if (!pose || pose->iksolver < 0 || pose->iksolver >= (sizeof(ikplugin_tab) / sizeof(IKPlugin))) + if (!pose || pose->iksolver < 0 || pose->iksolver > (sizeof(ikplugin_tab) / sizeof(IKPlugin) - 2)) return NULL; return &ikplugin_tab[pose->iksolver]; diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index af15333ece5..ca81f4c915a 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -379,6 +379,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) copy_v3_v3(goalpos, goal[3]); copy_m3_m4(goalrot, goal); + normalize_m3(goalrot); /* same for pole vector target */ if (data->poletar) { @@ -433,7 +434,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) iktarget = iktree[target->tip]; - if (data->weight != 0.0f) { + if ((data->flag & CONSTRAINT_IK_POS) && data->weight != 0.0f) { if (poleconstrain) IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, polepos, data->poleangle, (poleangledata == data)); diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 5cf762af3e8..903080d5b79 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -1636,7 +1636,7 @@ static void execute_scene(Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, fl // compute constraint error for (i = ikscene->targets.size(); i > 0; --i) { IK_Target *iktarget = ikscene->targets[i - 1]; - if (!(iktarget->blenderConstraint->flag & CONSTRAINT_OFF)) { + if (!(iktarget->blenderConstraint->flag & CONSTRAINT_OFF) && iktarget->constraint) { unsigned int nvalues; const iTaSC::ConstraintValues *values; values = iktarget->constraint->getControlParameters(&nvalues); diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 5b64416c309..8dfdbd4fddc 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -821,6 +821,14 @@ static int ffmpeg_decode_video_frame(struct anim *anim) } if (rval == AVERROR_EOF) { + /* this sets size and data fields to zero, + which is necessary to decode the remaining data + in the decoder engine after EOF. It also prevents a memory + leak, since av_read_frame spills out a full size packet even + on EOF... (and: it's save to call on NULL packets) */ + + av_free_packet(&anim->next_packet); + anim->next_packet.size = 0; anim->next_packet.data = 0; diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index d20c6dec9d3..c8bc3f8ebb8 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -139,9 +139,19 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon if (ibuf->rect_float != 0 && bitspersample != 8) { /* don't use the float buffer to save 8 bpp picture to prevent color banding (there's no dithering algorithm behing the logImageSetDataRGBA function) */ - IMB_flipy(ibuf); - rvalue = (logImageSetDataRGBA(logImage, ibuf->rect_float, 1) == 0); - IMB_flipy(ibuf); + + fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); + + for (y = 0; y < ibuf->y; y++) { + float *dst_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x); + float *src_ptr = ibuf->rect_float + 4 * (y * ibuf->x); + + memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float)); + } + + rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0); + + MEM_freeN(fbuf); } else { if (ibuf->rect == 0) diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index 9926d8c8562..3049a5be514 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -188,7 +188,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t } else { if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n", - (uintptr_t)header.fileHeader.magic_num, byteStuff); + (unsigned long)header.fileHeader.magic_num, byteStuff); logImageClose(cineon); return 0; } diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index aedce52a7bf..4c9b5e620dd 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -457,7 +457,7 @@ LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPer } /* Header should be rounded to next 8k block - 6044 = 8092 - sizeof(DpxMainHeader) */ + * 6044 = 8092 - sizeof(DpxMainHeader) */ memset(&pad, 0, 6044); if (fwrite(&pad, 6044, 1, dpx->file) == 0) { if (verbose) printf("DPX: Couldn't write image header\n"); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 6581987aed7..1c68a466ade 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -164,7 +164,7 @@ typedef struct ColormanageProcessor { * but they holds indexes of all transformations and color spaces, not * their names. * - * This helps avoid extra colorsmace / display / view lookup without + * This helps avoid extra colorspace / display / view lookup without * requiring to pass all variables which affects on display buffer * to color management cache system and keeps calls small and nice. */ @@ -890,7 +890,7 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) { ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace); - if (colorspace->is_data) { + if (colorspace && colorspace->is_data) { ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; return; } @@ -1083,7 +1083,7 @@ void IMB_colormanagement_check_is_data(ImBuf *ibuf, const char *name) { ColorSpace *colorspace = colormanage_colorspace_get_named(name); - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1095,7 +1095,7 @@ void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name) ibuf->float_colorspace = colorspace; - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1107,7 +1107,7 @@ void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name) ibuf->rect_colorspace = colorspace; - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -2385,7 +2385,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const ColorManagedDisplaySettings *display_settings, int xmin, int ymin, int xmax, int ymax, int update_orig_byte_buffer) { - if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) { + if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) { /* update byte buffer created by legacy color management */ unsigned char *rect = (unsigned char *) ibuf->rect; @@ -2465,7 +2465,8 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag } display_space = display_transform_get_colorspace(applied_view_settings, display_settings); - cm_processor->is_data_result = display_space->is_data; + if (display_space) + cm_processor->is_data_result = display_space->is_data; cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device, applied_view_settings->exposure, applied_view_settings->gamma); diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index 9b90b744b67..7e5a1e504b8 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -147,7 +147,7 @@ struct BlockDXT3 struct AlphaBlockDXT5 { // uint64 unions do not compile on all platforms - /* +#if 0 union { struct { uint64 alpha0 : 8; // 8 @@ -171,26 +171,26 @@ struct AlphaBlockDXT5 }; uint64 u; }; - */ +#endif uint64 u; - uint8 alpha0() const { return u & 0xffLL; }; - uint8 alpha1() const { return (u >> 8) & 0xffLL; }; - uint8 bits0() const { return (u >> 16) & 0x7LL; }; - uint8 bits1() const { return (u >> 19) & 0x7LL; }; - uint8 bits2() const { return (u >> 22) & 0x7LL; }; - uint8 bits3() const { return (u >> 25) & 0x7LL; }; - uint8 bits4() const { return (u >> 28) & 0x7LL; }; - uint8 bits5() const { return (u >> 31) & 0x7LL; }; - uint8 bits6() const { return (u >> 34) & 0x7LL; }; - uint8 bits7() const { return (u >> 37) & 0x7LL; }; - uint8 bits8() const { return (u >> 40) & 0x7LL; }; - uint8 bits9() const { return (u >> 43) & 0x7LL; }; - uint8 bitsA() const { return (u >> 46) & 0x7LL; }; - uint8 bitsB() const { return (u >> 49) & 0x7LL; }; - uint8 bitsC() const { return (u >> 52) & 0x7LL; }; - uint8 bitsD() const { return (u >> 55) & 0x7LL; }; - uint8 bitsE() const { return (u >> 58) & 0x7LL; }; - uint8 bitsF() const { return (u >> 61) & 0x7LL; }; + uint8 alpha0() const { return u & 0xffLL; } + uint8 alpha1() const { return (u >> 8) & 0xffLL; } + uint8 bits0() const { return (u >> 16) & 0x7LL; } + uint8 bits1() const { return (u >> 19) & 0x7LL; } + uint8 bits2() const { return (u >> 22) & 0x7LL; } + uint8 bits3() const { return (u >> 25) & 0x7LL; } + uint8 bits4() const { return (u >> 28) & 0x7LL; } + uint8 bits5() const { return (u >> 31) & 0x7LL; } + uint8 bits6() const { return (u >> 34) & 0x7LL; } + uint8 bits7() const { return (u >> 37) & 0x7LL; } + uint8 bits8() const { return (u >> 40) & 0x7LL; } + uint8 bits9() const { return (u >> 43) & 0x7LL; } + uint8 bitsA() const { return (u >> 46) & 0x7LL; } + uint8 bitsB() const { return (u >> 49) & 0x7LL; } + uint8 bitsC() const { return (u >> 52) & 0x7LL; } + uint8 bitsD() const { return (u >> 55) & 0x7LL; } + uint8 bitsE() const { return (u >> 58) & 0x7LL; } + uint8 bitsF() const { return (u >> 61) & 0x7LL; } void evaluatePalette(uint8 alpha[8]) const; void evaluatePalette8(uint8 alpha[8]) const; diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp index ee7a0ebb2f7..05821b27ca6 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -140,10 +140,10 @@ static void FlipDXT5BlockFull(uint8_t *block) unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]); // swap lines 0 and 1 in line_0_1. unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | - ((line_0_1 & 0xfff000) >> 12); + ((line_0_1 & 0xfff000) >> 12); // swap lines 2 and 3 in line_2_3. unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) | - ((line_2_3 & 0xfff000) >> 12); + ((line_2_3 & 0xfff000) >> 12); block[2] = line_3_2 & 0xff; block[3] = (line_3_2 & 0xff00) >> 8; @@ -162,7 +162,7 @@ static void FlipDXT5BlockHalf(uint8_t *block) // See layout above. unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | - ((line_0_1 & 0xfff000) >> 12); + ((line_0_1 & 0xfff000) >> 12); block[2] = line_1_0 & 0xff; block[3] = (line_1_0 & 0xff00) >> 8; block[4] = (line_1_0 & 0xff0000) >> 8; diff --git a/source/blender/imbuf/intern/dds/SConscript b/source/blender/imbuf/intern/dds/SConscript index d5a613f5981..475d21135aa 100644 --- a/source/blender/imbuf/intern/dds/SConscript +++ b/source/blender/imbuf/intern/dds/SConscript @@ -3,16 +3,17 @@ Import ('env') source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp', 'FlipDXT.cpp'] -incs = ['.', - '../../', - '../..', +incs = [ + '.', '..', + '../..', '../../../makesdna', '../../../blenkernel', '../../../blenlib', 'intern/include', '#/intern/guardedalloc', - '#/intern/utfconv'] + '#/intern/utfconv' + ] defs = ['WITH_DDS'] diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h index 7fed4ca89e7..a1ac49b58da 100644 --- a/source/blender/imbuf/intern/dds/Stream.h +++ b/source/blender/imbuf/intern/dds/Stream.h @@ -35,7 +35,7 @@ struct Stream unsigned char *mem; // location in memory unsigned int size; // size unsigned int pos; // current position - Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {}; + Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {} unsigned int seek(unsigned int p); }; diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 55c1b02e90b..f049c404e2d 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -196,7 +196,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, { float tmp[4]; int x, y; - DitherContext *di; + DitherContext *di = NULL; /* we need valid profiles */ BLI_assert(profile_to != IB_PROFILE_NONE); @@ -583,23 +583,23 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w if (is_data) { /* exception for non-color data, just copy float */ IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, - w, h, w, ibuf->x); + ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, + w, h, w, ibuf->x); /* and do color space conversion to byte */ IMB_buffer_byte_from_float(rect_byte, rect_float, - 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, - w, h, ibuf->x, w); + 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + w, h, ibuf->x, w); } else { IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, - w, h, w, ibuf->x); + ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, + w, h, w, ibuf->x); /* XXX: need to convert to image buffer's rect space */ IMB_buffer_byte_from_float(rect_byte, buffer, - 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, - w, h, ibuf->x, w); + 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, + w, h, ibuf->x, w); } /* ensure user flag is reset */ diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 57fbce710a1..a185c4ee3e0 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -43,6 +43,7 @@ #include "BLI_utildefines.h" #include "BLI_threads.h" #include "BLI_listbase.h" +#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -95,132 +96,15 @@ static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float ** *outF = ibuf->rect_float + offset; } -/************************************************************************** - * INTERPOLATIONS - * - * Reference and docs: - * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms - ***************************************************************************/ - -/* BICUBIC Interpolation functions - * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation - * function assumes out to be zero'ed, only does RGBA */ - -static float P(float k) -{ - float p1, p2, p3, p4; - p1 = MAX2(k + 2.0f, 0); - p2 = MAX2(k + 1.0f, 0); - p3 = MAX2(k, 0); - p4 = MAX2(k - 1.0f, 0); - return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); -} - - -#if 0 -/* older, slower function, works the same as above */ -static float P(float k) -{ - return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f)); -} -#endif +/* BICUBIC Interpolation */ void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - int i, j, n, m, x1, y1; - unsigned char *dataI; - float a, b, w, wx, wy[4], outR, outG, outB, outA, *dataF; - - /* sample area entirely outside image? */ - if (ceil(u) < 0 || floor(u) > in->x - 1 || ceil(v) < 0 || floor(v) > in->y - 1) { - return; - } - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - i = (int)floor(u); - j = (int)floor(v); - a = u - i; - b = v - j; - - outR = outG = outB = outA = 0.0f; - -/* Optimized and not so easy to read */ - - /* avoid calling multiple times */ - wy[0] = P(b - (-1)); - wy[1] = P(b - 0); - wy[2] = P(b - 1); - wy[3] = P(b - 2); - - for (n = -1; n <= 2; n++) { - x1 = i + n; - CLAMP(x1, 0, in->x - 1); - wx = P(n - a); - for (m = -1; m <= 2; m++) { - y1 = j + m; - CLAMP(y1, 0, in->y - 1); - /* normally we could do this */ - /* w = P(n-a) * P(b-m); */ - /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ - w = wx * wy[m + 1]; - - if (outF) { - dataF = in->rect_float + in->x * y1 * 4 + 4 * x1; - outR += dataF[0] * w; - outG += dataF[1] * w; - outB += dataF[2] * w; - outA += dataF[3] * w; - } - if (outI) { - dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - outR += dataI[0] * w; - outG += dataI[1] * w; - outB += dataI[2] * w; - outA += dataI[3] * w; - } - } - } - -/* Done with optimized part */ - -#if 0 - /* older, slower function, works the same as above */ - for (n = -1; n <= 2; n++) { - for (m = -1; m <= 2; m++) { - x1 = i + n; - y1 = j + m; - if (x1 > 0 && x1 < in->x && y1 > 0 && y1 < in->y) { - if (do_float) { - dataF = in->rect_float + in->x * y1 * 4 + 4 * x1; - outR += dataF[0] * P(n - a) * P(b - m); - outG += dataF[1] * P(n - a) * P(b - m); - outB += dataF[2] * P(n - a) * P(b - m); - outA += dataF[3] * P(n - a) * P(b - m); - } - if (do_rect) { - dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - outR += dataI[0] * P(n - a) * P(b - m); - outG += dataI[1] * P(n - a) * P(b - m); - outB += dataI[2] * P(n - a) * P(b - m); - outA += dataI[3] * P(n - a) * P(b - m); - } - } - } - } -#endif - - if (outI) { - outI[0] = (int)outR; - outI[1] = (int)outG; - outI[2] = (int)outB; - outI[3] = (int)outA; - } if (outF) { - outF[0] = outR; - outF[1] = outG; - outF[2] = outB; - outF[3] = outA; + BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); + } + else { + BLI_bicubic_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v); } } @@ -239,77 +123,14 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in bicubic_interpolation_color(in, outI, outF, u, v); } -/* function assumes out to be zero'ed, only does RGBA */ /* BILINEAR INTERPOLATION */ void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - float *row1, *row2, *row3, *row4, a, b; - unsigned char *row1I, *row2I, *row3I, *row4I; - float a_b, ma_b, a_mb, ma_mb; - float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - unsigned char emptyI[4] = {0, 0, 0, 0}; - int y1, y2, x1, x2; - - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - x1 = (int)floor(u); - x2 = (int)ceil(u); - y1 = (int)floor(v); - y2 = (int)ceil(v); - - /* sample area entirely outside image? */ - if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) { - return; - } - if (outF) { - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1 = empty; - else row1 = in->rect_float + in->x * y1 * 4 + 4 * x1; - - if (x1 < 0 || y2 > in->y - 1) row2 = empty; - else row2 = in->rect_float + in->x * y2 * 4 + 4 * x1; - - if (x2 > in->x - 1 || y1 < 0) row3 = empty; - else row3 = in->rect_float + in->x * y1 * 4 + 4 * x2; - - if (x2 > in->x - 1 || y2 > in->y - 1) row4 = empty; - else row4 = in->rect_float + in->x * y2 * 4 + 4 * x2; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - outF[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - outF[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - outF[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - outF[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); } - if (outI) { - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1I = emptyI; - else row1I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - - if (x1 < 0 || y2 > in->y - 1) row2I = emptyI; - else row2I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x1; - - if (x2 > in->x - 1 || y1 < 0) row3I = emptyI; - else row3I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x2; - - if (x2 > in->x - 1 || y2 > in->y - 1) row4I = emptyI; - else row4I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x2; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - /* need to add 0.5 to avoid rounding down (causes darken with the smear brush) - * tested with white images and this should not wrap back to zero */ - outI[0] = (ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]) + 0.5f; - outI[1] = (ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]) + 0.5f; - outI[2] = (ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]) + 0.5f; - outI[3] = (ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]) + 0.5f; + else { + BLI_bilinear_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v); } } diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 5dda33dfd62..277f50bcdbc 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -872,7 +872,7 @@ static void index_rebuild_ffmpeg_proc_decoded_frame( context->frameno = floor((pts - context->start_pts) * context->pts_time_base * - context->frame_rate + 0.5f); + context->frame_rate + 0.5); /* decoding starts *always* on I-Frames, * so: P-Frames won't work, even if all the @@ -912,6 +912,8 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, AVPacket next_packet; uint64_t stream_size; + memset(&next_packet, 0, sizeof(AVPacket)); + in_frame = avcodec_alloc_frame(); stream_size = avio_size(context->iFormatCtx->pb); @@ -959,12 +961,13 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, * according to ffmpeg docs using 0-size packets. * * At least, if we haven't already stopped... */ + + /* this creates the 0-size packet and prevents a memory leak. */ + av_free_packet(&next_packet); + if (!*stop) { int frame_finished; - next_packet.size = 0; - next_packet.data = 0; - do { frame_finished = 0; diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index 692ba3c49ea..3a2bf99c75c 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -41,7 +41,7 @@ #include "openjpeg.h" -#define JP2_FILEHEADER_SIZE 14 +// #define JP2_FILEHEADER_SIZE 14 /* UNUSED */ static char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A}; static char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00}; @@ -387,8 +387,8 @@ BLI_INLINE int DOWNSAMPLE_FLOAT_TO_16BIT(const float _val) /* * 2048x1080 (2K) at 24 fps or 48 fps, or 4096x2160 (4K) at 24 fps; 3x12 bits per pixel, XYZ color space * - * - In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the imager is used - * - In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the imager is used + * - In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the image is used + * - In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the image is used */ /* ****************************** COPIED FROM image_to_j2k.c */ diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 61275a8937c..758617bdd48 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -235,19 +235,19 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t */ #define INPUT_BYTE(cinfo, V, action) \ MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) /* As above, but read two bytes interpreted as an unsigned 16-bit integer. * V should be declared unsigned int or perhaps INT32. */ #define INPUT_2BYTES(cinfo, V, action) \ MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo, action); \ - bytes_in_buffer--; \ - V += GETJOCTET(*next_input_byte++); ) + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo, action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) static boolean @@ -348,25 +348,12 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla g = *buffer++; b = *buffer++; k = *buffer++; - - k = 255 - k; - r -= k; - if (r & 0xffffff00) { - if (r < 0) r = 0; - else r = 255; - } - g -= k; - if (g & 0xffffff00) { - if (g < 0) g = 0; - else g = 255; - } - b -= k; - if (b & 0xffffff00) { - if (b < 0) b = 0; - else b = 255; - } - - rect[3] = 255 - k; + + r = (r * k) / 255; + g = (g * k) / 255; + b = (b * k) / 255; + + rect[3] = 255; rect[2] = b; rect[1] = g; rect[0] = r; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 60c6e184070..da7b31cc2ba 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -72,21 +72,6 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include -#if defined(_WIN32) && !defined(FREE_WINDOWS) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else #include #include #include @@ -100,7 +85,6 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include #include #include -#endif using namespace Imf; using namespace Imath; @@ -881,7 +865,7 @@ void IMB_exr_close(void *handle) /* get a substring from the end of the name, separated by '.' */ static int imb_exr_split_token(const char *str, const char *end, const char **token) { - int maxlen = end - str; + ptrdiff_t maxlen = end - str; int len = 0; while (len < maxlen && *(end - len - 1) != '.') { len++; @@ -1183,7 +1167,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char frameBuffer.insert(exr_rgba_channelname(file, "B"), Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride)); - /* 1.0 is fill value, this still neesd to be assigned even when (is_alpha == 0) */ + /* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */ frameBuffer.insert(exr_rgba_channelname(file, "A"), Slice(Imf::FLOAT, (char *) (first + 3), xstride, ystride, 1, 1, 1.0f)); diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h index 78071975c72..376d2401b1c 100644 --- a/source/blender/imbuf/intern/openexr/openexr_multi.h +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -35,10 +35,10 @@ /* experiment with more advanced exr api */ -/* Note: as for now openexr only supports 32 chars in channel names. - * This api also supports max 8 channels per pass now. easy to fix! */ -#define EXR_LAY_MAXNAME 51 -#define EXR_PASS_MAXNAME 11 +/* XXX layer+pass name max 64? */ +/* This api also supports max 8 channels per pass now. easy to fix! */ +#define EXR_LAY_MAXNAME 64 +#define EXR_PASS_MAXNAME 64 #define EXR_TOT_MAXNAME 64 #define EXR_PASS_MAXCHAN 8 diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index 7262656d4e8..21fa878c08a 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -33,25 +33,25 @@ #include "openexr_multi.h" -void * IMB_exr_get_handle (void) {return NULL;} -void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void *IMB_exr_get_handle (void) {return NULL;} +void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } -int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} -int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} -void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } +int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} +int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} +void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } -void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } -void IMB_exr_read_channels (void *handle) { (void)handle; } -void IMB_exr_write_channels (void *handle) { (void)handle; } -void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } -void IMB_exrtile_clear_channels (void *handle) { (void)handle; } +void IMB_exr_read_channels (void *handle) { (void)handle; } +void IMB_exr_write_channels (void *handle) { (void)handle; } +void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } +void IMB_exrtile_clear_channels (void *handle) { (void)handle; } -void IMB_exr_multilayer_convert (void *handle, void *base, - void * (*addlayer)(void *base, const char *str), - void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) - { - (void)handle; (void)base; (void)addlayer; (void)addpass; - } +void IMB_exr_multilayer_convert (void *handle, void *base, + void * (*addlayer)(void *base, const char *str), + void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) +{ + (void)handle; (void)base; (void)addlayer; (void)addpass; +} -void IMB_exr_close (void *handle) { (void)handle; } +void IMB_exr_close (void *handle) { (void)handle; } diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 72cec0e3749..03ed1bb8008 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -65,7 +65,6 @@ #define BLU 2 #define EXP 3 #define COLXS 128 -#define STR_MAX 540 typedef unsigned char RGBE[4]; typedef float fCOLOR[3]; diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 5669a4cc45d..be20c80bdec 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -176,7 +176,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags) ImBuf *ibuf; int file; char filepath_tx[IB_FILENAME_SIZE]; - char colorspace[IM_MAX_SPACE]; + char colorspace[IM_MAX_SPACE] = "\0"; imb_cache_filename(filepath_tx, filepath, flags); diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 8e072361583..d2b0645cf93 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -587,7 +587,7 @@ void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, i { if (!ibuf) return; buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display, - x1, y1, x2, y2); + x1, y1, x2, y2); } diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 527f334d6a4..1e701b8d615 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -331,13 +331,13 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) for (y = ibuf2->y; y > 0; y--) { p2f = p1f + (ibuf1->x << 2); for (x = ibuf2->x; x > 0; x--) { - destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); - destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); - destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); - destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); - p1f += 8; - p2f += 8; - destf += 4; + destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); + destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); + destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); + destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); + p1f += 8; + p2f += 8; + destf += 4; } p1f = p2f; if (ibuf1->x & 1) p1f += 4; @@ -1467,10 +1467,10 @@ struct ImBuf *IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int return ibuf; } - if (newx < ibuf->x) if (newx) scaledownx(ibuf, newx); - if (newy < ibuf->y) if (newy) scaledowny(ibuf, newy); - if (newx > ibuf->x) if (newx) scaleupx(ibuf, newx); - if (newy > ibuf->y) if (newy) scaleupy(ibuf, newy); + if (newx && (newx < ibuf->x)) scaledownx(ibuf, newx); + if (newy && (newy < ibuf->y)) scaledowny(ibuf, newy); + if (newx && (newx > ibuf->x)) scaleupx(ibuf, newx); + if (newy && (newy > ibuf->y)) scaleupy(ibuf, newy); return(ibuf); } diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index fe138a71a4a..42fb0c79b62 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -228,16 +228,27 @@ static int isqtime(const char *name) #ifdef WITH_FFMPEG +#ifdef _MSC_VER +#define va_copy(dst, src) ((dst) = (src)) +#endif + /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-format-attribute" +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-format-attribute" +#endif static char ffmpeg_last_error[1024]; static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) { if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) { - size_t n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg); + size_t n; + va_list arg2; + + va_copy(arg2, arg); + + n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg2); /* strip trailing \n */ ffmpeg_last_error[n - 1] = '\0'; @@ -249,7 +260,9 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_lis } } -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif void IMB_ffmpeg_init(void) { diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index d8d1ad78451..f227af78dab 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -372,7 +372,7 @@ typedef enum ePose_Flags { /* bPose->iksolver and bPose->ikparam->iksolver */ typedef enum ePose_IKSolverType { - IKSOLVER_LEGACY = 0, + IKSOLVER_STANDARD = 0, IKSOLVER_ITASC = 1 } ePose_IKSolverType; diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 3cf84648ea6..deb9902c35d 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -201,8 +201,8 @@ typedef struct Curve { float twist_smooth, smallcaps_scale; int pathlen; - short pad, totcol; - short flag, bevresol; + short bevresol, totcol; + int flag; float width, ext1, ext2; /* default */ @@ -269,6 +269,7 @@ typedef struct Curve { #define CU_PATH_RADIUS 4096 /* make use of the path radius if this is enabled (default for new curves) */ #define CU_DEFORM_FILL 8192 /* fill 2d curve after deformation */ #define CU_FILL_CAPS 16384 /* fill bevel caps */ +#define CU_MAP_TAPER 32768 /* map taper object to bevelled area */ /* twist mode */ #define CU_TWIST_Z_UP 0 diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 100968e7257..b64fc08a47a 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -41,6 +41,7 @@ typedef struct bGPDspoint { float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */ float pressure; /* pressure of input device (from 0 to 1) at this point */ + float time; /* seconds since start of stroke */ } bGPDspoint; /* Grease-Pencil Annotations - 'Stroke' @@ -49,12 +50,14 @@ typedef struct bGPDspoint { */ typedef struct bGPDstroke { struct bGPDstroke *next, *prev; - bGPDspoint *points; /* array of data-points for stroke */ + void *pad; /* keep 4 pointers at the beginning, padding for 'inittime' is tricky 64/32bit */ int totpoints; /* number of data-points in array */ short thickness; /* thickness of stroke (currently not used) */ short flag; /* various settings about this stroke */ + + double inittime; /* Init time of stroke */ } bGPDstroke; /* bGPDstroke->flag */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index c9e929ce41b..3875a0d5799 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -76,6 +76,7 @@ typedef enum ModifierType { eModifierType_Remesh = 41, eModifierType_Skin = 42, eModifierType_LaplacianSmooth = 43, + eModifierType_Triangulate = 44, NUM_MODIFIER_TYPES } ModifierType; @@ -665,7 +666,8 @@ typedef struct ShrinkwrapModifierData { float keepDist; /* distance offset to keep from mesh/projection point */ short shrinkType; /* shrink type projection */ short shrinkOpts; /* shrink options */ - char projAxis; /* axis to project over */ + float projLimit; /* limit the projection ray cast */ + char projAxis; /* axis to project over */ /* * if using projection over vertex normal this controls the @@ -674,7 +676,7 @@ typedef struct ShrinkwrapModifierData { */ char subsurfLevels; - char pad[6]; + char pad[2]; } ShrinkwrapModifierData; @@ -1113,11 +1115,23 @@ enum { MOD_SKIN_SMOOTH_SHADING = 1 }; +/* Triangulate modifier */ + +typedef struct TriangulateModifierData { + ModifierData modifier; + int flag; + int pad; +} TriangulateModifierData; + +enum { + MOD_TRIANGULATE_BEAUTY = (1 << 0), +}; + /* Smooth modifier flags */ #define MOD_LAPLACIANSMOOTH_X (1<<1) #define MOD_LAPLACIANSMOOTH_Y (1<<2) #define MOD_LAPLACIANSMOOTH_Z (1<<3) -#define MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION (1<<4) +#define MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME (1 << 4) typedef struct LaplacianSmoothModifierData { ModifierData modifier; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index c73ba87754f..a05ff66e683 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -118,7 +118,8 @@ typedef struct bNodeSocket { #define SOCK_BOOLEAN 4 #define SOCK_MESH 5 #define SOCK_INT 6 -#define NUM_SOCKET_TYPES 7 /* must be last! */ +#define SOCK_STRING 7 +#define NUM_SOCKET_TYPES 8 /* must be last! */ /* socket side (input/output) */ #define SOCK_IN 1 @@ -293,7 +294,8 @@ typedef struct bNodeTree { void (*progress)(void *, float progress); void (*stats_draw)(void *, char *str); int (*test_break)(void *); - void *tbh, *prh, *sdh; + void (*update_draw)(void *); + void *tbh, *prh, *sdh, *udh; } bNodeTree; @@ -353,6 +355,11 @@ typedef struct bNodeSocketValueRGBA { float value[4]; } bNodeSocketValueRGBA; +typedef struct bNodeSocketValueString { + int subtype; + int pad; + char value[1024]; /* 1024 = FILEMAX */ +} bNodeSocketValueString; /* data structs, for node->storage */ enum { @@ -716,6 +723,17 @@ typedef struct NodeShaderScript { IDProperty *prop; } NodeShaderScript; +typedef struct NodeShaderTangent { + int direction_type; + int axis; + char uv_map[64]; +} NodeShaderTangent; + +typedef struct NodeShaderNormalMap { + int space; + char uv_map[64]; +} NodeShaderNormalMap; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 @@ -800,6 +818,20 @@ typedef struct NodeShaderScript { #define SHD_PROJ_FLAT 0 #define SHD_PROJ_BOX 1 +/* tangent */ +#define SHD_TANGENT_RADIAL 0 +#define SHD_TANGENT_UVMAP 1 + +/* tangent */ +#define SHD_TANGENT_AXIS_X 0 +#define SHD_TANGENT_AXIS_Y 1 +#define SHD_TANGENT_AXIS_Z 2 + +/* normal map space */ +#define SHD_NORMAL_MAP_TANGENT 0 +#define SHD_NORMAL_MAP_OBJECT 1 +#define SHD_NORMAL_MAP_WORLD 2 + /* blur node */ #define CMP_NODE_BLUR_ASPECT_NONE 0 #define CMP_NODE_BLUR_ASPECT_Y 1 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 29f6499986c..89328c33674 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -297,22 +297,19 @@ typedef struct ObHook { typedef struct DupliObject { struct DupliObject *next, *prev; struct Object *ob; - unsigned int origlay; - int index; + unsigned int origlay, pad; float mat[4][4], omat[4][4]; float orco[3], uv[2]; short type; /* from Object.transflag */ char no_draw, animated; - /* Lowest-level particle index. - * Note: This is needed for particle info in shaders. - * Otherwise dupli groups in particle systems would override the - * index value from higher dupli levels. Would be nice to have full generic access - * to all dupli levels somehow, but for now this should cover most use-cases. - */ - int particle_index; - int pad; + /* persistent identifier for a dupli object, for inter-frame matching of + * objects with motion blur, or inter-update matching for syncing */ + int persistent_id[8]; /* MAX_DUPLI_RECUR */ + + /* particle this dupli was generated from */ + struct ParticleSystem *particle_system; } DupliObject; /* **************** OBJECT ********************* */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1479d5268ed..1599b71d832 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1009,7 +1009,7 @@ typedef struct ToolSettings { /* Transform */ char snap_mode, snap_node_mode; - char pad3; + char snap_uv_mode; short snap_flag, snap_target; short proportional, prop_mode; char proportional_objects; /* proportional edit, object mode */ @@ -1187,11 +1187,13 @@ typedef struct Scene { /* Use the same flag for autothreads */ #define R_FIXED_THREADS 0x80000 -#define R_SPEED 0x100000 -#define R_SSS 0x200000 -#define R_NO_OVERWRITE 0x400000 /* skip existing files */ -#define R_TOUCH 0x800000 /* touch files before rendering */ -#define R_SIMPLIFY 0x1000000 +#define R_SPEED 0x100000 +#define R_SSS 0x200000 +#define R_NO_OVERWRITE 0x400000 /* skip existing files */ +#define R_TOUCH 0x800000 /* touch files before rendering */ +#define R_SIMPLIFY 0x1000000 +#define R_EDGE_FRS 0x2000000 /* R_EDGE reserved for Freestyle */ +#define R_PERSISTENT_DATA 0x4000000 /* keep data around for re-render */ /* seq_flag */ #define R_SEQ_GL_PREV 1 @@ -1327,46 +1329,46 @@ typedef struct Scene { #define TESTBASE(v3d, base) ( \ ((base)->flag & SELECT) && \ ((base)->lay & v3d->lay) && \ - (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) ) + (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define TESTBASELIB(v3d, base) ( \ ((base)->flag & SELECT) && \ ((base)->lay & v3d->lay) && \ - ((base)->object->id.lib==NULL) && \ - (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) ) + ((base)->object->id.lib == NULL) && \ + (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define TESTBASELIB_BGMODE(v3d, scene, base) ( \ ((base)->flag & SELECT) && \ ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \ - ((base)->object->id.lib==NULL) && \ - (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) ) + ((base)->object->id.lib == NULL) && \ + (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define BASE_EDITABLE_BGMODE(v3d, scene, base) ( \ ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \ - ((base)->object->id.lib==NULL) && \ - (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0)) + ((base)->object->id.lib == NULL) && \ + (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define BASE_SELECTABLE(v3d, base) ( \ (base->lay & v3d->lay) && \ - (base->object->restrictflag & (OB_RESTRICT_SELECT|OB_RESTRICT_VIEW))==0 ) + (base->object->restrictflag & (OB_RESTRICT_SELECT | OB_RESTRICT_VIEW)) == 0) #define BASE_VISIBLE(v3d, base) ( \ (base->lay & v3d->lay) && \ - (base->object->restrictflag & OB_RESTRICT_VIEW)==0 ) + (base->object->restrictflag & OB_RESTRICT_VIEW) == 0) #define FIRSTBASE scene->base.first #define LASTBASE scene->base.last #define BASACT (scene->basact) -#define OBACT (BASACT? BASACT->object: NULL) +#define OBACT (BASACT ? BASACT->object: NULL) #define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL) #define V3D_CAMERA_SCENE(scene, v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : (scene)->camera) -#define CFRA (scene->r.cfra) -#define SUBFRA (scene->r.subframe) -#define SFRA (scene->r.sfra) -#define EFRA (scene->r.efra) -#define PRVRANGEON (scene->r.flag & SCER_PRV_RANGE) -#define PSFRA ((PRVRANGEON) ? (scene->r.psfra) : (scene->r.sfra)) -#define PEFRA ((PRVRANGEON) ? (scene->r.pefra) : (scene->r.efra)) -#define FRA2TIME(a) ((((double) scene->r.frs_sec_base) * (double)(a)) / (double)scene->r.frs_sec) -#define TIME2FRA(a) ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base) -#define FPS (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base) +#define CFRA (scene->r.cfra) +#define SUBFRA (scene->r.subframe) +#define SFRA (scene->r.sfra) +#define EFRA (scene->r.efra) +#define PRVRANGEON (scene->r.flag & SCER_PRV_RANGE) +#define PSFRA ((PRVRANGEON) ? (scene->r.psfra) : (scene->r.sfra)) +#define PEFRA ((PRVRANGEON) ? (scene->r.pefra) : (scene->r.efra)) +#define FRA2TIME(a) ((((double) scene->r.frs_sec_base) * (double)(a)) / (double)scene->r.frs_sec) +#define TIME2FRA(a) ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base) +#define FPS (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base) /* base->flag is in DNA_object_types.h */ @@ -1444,9 +1446,9 @@ typedef struct Scene { /* Paint.flags */ typedef enum { - PAINT_SHOW_BRUSH = (1<<0), - PAINT_FAST_NAVIGATE = (1<<1), - PAINT_SHOW_BRUSH_ON_SURFACE = (1<<2), + PAINT_SHOW_BRUSH = (1 << 0), + PAINT_FAST_NAVIGATE = (1 << 1), + PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2), } PaintFlags; /* Sculpt.flags */ @@ -1598,4 +1600,4 @@ typedef enum SculptFlags { } #endif -#endif +#endif /* __DNA_SCENE_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h index cf26dae402d..6ce883905d4 100644 --- a/source/blender/makesdna/DNA_text_types.h +++ b/source/blender/makesdna/DNA_text_types.h @@ -44,15 +44,6 @@ typedef struct TextLine { int len, blen; /* blen unused */ } TextLine; -typedef struct TextMarker { - struct TextMarker *next, *prev; - - int lineno, start, end, pad1; /* line number and start/end character indices */ - - int group, flags; /* see BKE_text.h for flag defines */ - unsigned char color[4], pad[4]; /* draw color of the marker */ -} TextMarker; - typedef struct Text { ID id; @@ -63,7 +54,6 @@ typedef struct Text { ListBase lines; TextLine *curl, *sell; int curc, selc; - ListBase markers; char *undo_buf; int undo_pos, undo_len; @@ -78,7 +68,6 @@ typedef struct Text { /* text flags */ #define TXT_ISDIRTY 0x0001 -#define TXT_DEPRECATED 0x0004 /* deprecated ISTMP flag */ #define TXT_ISMEM 0x0004 #define TXT_ISEXT 0x0008 #define TXT_ISSCRIPT 0x0010 /* used by space handler scriptlinks */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 9c80d30bca4..12819303b26 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -163,7 +163,7 @@ typedef struct MovieTrackingSettings { /* ** reconstruction settings ** */ int keyframe1 DNA_DEPRECATED, - keyframe2 DNA_DEPRECATED; /* two keyframes for reconstrution initialization + keyframe2 DNA_DEPRECATED; /* two keyframes for reconstruction initialization * were moved to per-tracking object settings */ @@ -228,7 +228,7 @@ typedef struct MovieTrackingObject { MovieTrackingReconstruction reconstruction; /* reconstruction data for this object */ /* reconstruction options */ - int keyframe1, keyframe2; /* two keyframes for reconstrution initialization */ + int keyframe1, keyframe2; /* two keyframes for reconstruction initialization */ } MovieTrackingObject; typedef struct MovieTrackingStats { diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 2256968da56..2e2f65dbec7 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -162,7 +162,8 @@ typedef struct ThemeUI { char iconfile[256]; // FILE_MAXFILE length float icon_alpha; - float pad; + /* Axis Colors */ + char xaxis[4], yaxis[4], zaxis[4]; } ThemeUI; /* try to put them all in one, if needed a special struct can be created as well @@ -417,9 +418,11 @@ typedef struct UserDef { float ndof_sensitivity; /* overall sensitivity of 3D mouse */ float ndof_orbit_sensitivity; - float pad4; int ndof_flag; /* flags for 3D mouse */ + short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */ + short pad4; + float glalphaclip; short autokey_mode; /* autokeying mode */ @@ -597,7 +600,7 @@ typedef enum eOpenGL_RenderingOptions { /* backwards compatibilty in do_versions! */ USER_DISABLE_MIPMAP = (1 << 2), USER_DISABLE_VBO = (1 << 3), - USER_DISABLE_AA = (1 << 4), + /* USER_DISABLE_AA = (1 << 4), */ /* DEPRECATED */ } eOpenGL_RenderingOptions; /* wm draw method */ @@ -702,6 +705,17 @@ typedef enum eCompute_Device_Type { USER_COMPUTE_DEVICE_CUDA = 2, } eCompute_Device_Type; + +typedef enum eMultiSample_Type { + USER_MULTISAMPLE_NONE = 0, + USER_MULTISAMPLE_2 = 2, + USER_MULTISAMPLE_4 = 4, + USER_MULTISAMPLE_8 = 8, + USER_MULTISAMPLE_16 = 16, +} eMultiSample_Type; + + + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index bef5e5cc161..fa0b313a120 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -1001,7 +1001,7 @@ static int make_structDNA(char *baseDirectory, FILE *file) /* FOR DEBUG */ if (debugSDNA > 1) { int a, b; -/* short *elem; */ + /* short *elem; */ short num_types; printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs); diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 5f667db4425..0e5f9c5fa5f 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -148,6 +148,7 @@ extern StructRNA RNA_CompositorNodeLevels; extern StructRNA RNA_CompositorNodeLumaMatte; extern StructRNA RNA_CompositorNodeMapUV; extern StructRNA RNA_CompositorNodeMapValue; +extern StructRNA RNA_CompositorNodeMapRange; extern StructRNA RNA_CompositorNodeMath; extern StructRNA RNA_CompositorNodeMask; extern StructRNA RNA_CompositorNodeMixRGB; @@ -525,7 +526,6 @@ extern StructRNA RNA_TextBox; extern StructRNA RNA_TextCharacterFormat; extern StructRNA RNA_TextCurve; extern StructRNA RNA_TextLine; -extern StructRNA RNA_TextMarker; extern StructRNA RNA_Texture; extern StructRNA RNA_TextureNode; extern StructRNA RNA_TextureNodeBricks; @@ -862,6 +862,7 @@ int RNA_path_resolve_full(PointerRNA *ptr, const char *path, char *RNA_path_from_ID_to_struct(PointerRNA *ptr); char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop); +char *RNA_path_from_ID_python(struct ID *id); /* Quick name based property access * @@ -1053,6 +1054,11 @@ __attribute__ ((format(printf, 1, 2))) #endif ; +/* Equals test (skips pointers and collections) */ + +int RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop); +int RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b); + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 7c4ce3d18d7..6fa53f4e029 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -80,13 +80,15 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F const char *name_override, int close_prototype); /* helpers */ -#define WRITE_COMMA { \ +#define WRITE_COMMA \ + { \ if (!first) \ fprintf(f, ", "); \ first = 0; \ } (void)0 -#define WRITE_PARAM(param) { \ +#define WRITE_PARAM(param) \ + { \ WRITE_COMMA; \ fprintf(f, param); \ } @@ -1221,6 +1223,89 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property return func; } +static char *rna_def_property_lookup_string_func(FILE *f, StructRNA *srna, PropertyRNA *prop, PropertyDefRNA *dp, + const char *manualfunc, const char *item_type) +{ + char *func; + StructRNA *item_srna, *item_name_base; + PropertyRNA *item_name_prop; + const int namebuflen = 1024; + + if (prop->flag & PROP_IDPROPERTY && manualfunc == NULL) + return NULL; + + if (!manualfunc) { + if (!dp->dnastructname || !dp->dnaname) + return NULL; + + /* only supported for collection items with name properties */ + item_srna = rna_find_struct(item_type); + if (item_srna && item_srna->nameproperty) { + item_name_prop = item_srna->nameproperty; + item_name_base = item_srna; + while (item_name_base->base && item_name_base->base->nameproperty == item_name_prop) + item_name_base = item_name_base->base; + } + else + return NULL; + } + + func = rna_alloc_function_name(srna->identifier, rna_safe_id(prop->identifier), "lookup_string"); + + fprintf(f, "int %s(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)\n", func); + fprintf(f, "{\n"); + + if (manualfunc) { + fprintf(f, " return %s(ptr, key, r_ptr);\n", manualfunc); + fprintf(f, "}\n\n"); + return func; + } + + /* XXX extern declaration could be avoid by including RNA_blender.h, but this has lots of unknown + * DNA types in functions, leading to conflicting function signatures. + */ + fprintf(f, " extern int %s_%s_length(PointerRNA *);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " extern void %s_%s_get(PointerRNA *, char *);\n\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + + fprintf(f, " int found= 0;\n"); + fprintf(f, " CollectionPropertyIterator iter;\n"); + fprintf(f, " char namebuf[%d];\n", namebuflen); + fprintf(f, " char *name;\n\n"); + + fprintf(f, " %s_%s_begin(&iter, ptr);\n\n", srna->identifier, rna_safe_id(prop->identifier)); + + fprintf(f, " while (iter.valid) {\n"); + fprintf(f, " int namelen = %s_%s_length(&iter.ptr);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (namelen < %d) {\n", namebuflen); + fprintf(f, " %s_%s_get(&iter.ptr, namebuf);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (strcmp(namebuf, key) == 0) {\n"); + fprintf(f, " found = 1;\n"); + fprintf(f, " *r_ptr = iter.ptr;\n"); + fprintf(f, " break;\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, " else {\n"); + fprintf(f, " name = MEM_mallocN(namelen+1, \"name string\");\n"); + fprintf(f, " %s_%s_get(&iter.ptr, name);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (strcmp(name, key) == 0) {\n"); + fprintf(f, " MEM_freeN(name);\n\n"); + fprintf(f, " found = 1;\n"); + fprintf(f, " *r_ptr = iter.ptr;\n"); + fprintf(f, " break;\n"); + fprintf(f, " }\n"); + fprintf(f, " else\n"); + fprintf(f, " MEM_freeN(name);\n"); + fprintf(f, " }\n"); + fprintf(f, " %s_%s_next(&iter);\n", srna->identifier, rna_safe_id(prop->identifier)); + fprintf(f, " }\n"); + fprintf(f, " %s_%s_end(&iter);\n\n", srna->identifier, rna_safe_id(prop->identifier)); + + fprintf(f, " return found;\n"); + fprintf(f, "}\n\n"); + + return func; +} + static char *rna_def_property_next_func(FILE *f, StructRNA *srna, PropertyRNA *prop, PropertyDefRNA *UNUSED(dp), const char *manualfunc) { @@ -1401,6 +1486,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; const char *nextfunc = (const char *)cprop->next; + const char *item_type = (const char *)cprop->item_type; if (dp->dnatype && strcmp(dp->dnatype, "ListBase") == 0) { /* pass */ @@ -1424,6 +1510,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) cprop->end = (void *)rna_def_property_end_func(f, srna, prop, dp, (const char *)cprop->end); cprop->lookupint = (void *)rna_def_property_lookup_int_func(f, srna, prop, dp, (const char *)cprop->lookupint, nextfunc); + cprop->lookupstring = (void *)rna_def_property_lookup_string_func(f, srna, prop, dp, + (const char *)cprop->lookupstring, item_type); if (!(prop->flag & PROP_IDPROPERTY)) { if (!cprop->begin) { @@ -3169,6 +3257,8 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const fprintf(f, "#include \n\n"); fprintf(f, "#include \n\n"); + fprintf(f, "#include \"MEM_guardedalloc.h\"\n\n"); + fprintf(f, "#include \"DNA_ID.h\"\n"); fprintf(f, "#include \"DNA_scene_types.h\"\n"); @@ -3579,10 +3669,10 @@ static void rna_generate_header_class_cpp(StructDefRNA *ds, FILE *f) fprintf(f, "class %s : public %s {\n", srna->identifier, (srna->base) ? srna->base->identifier : "Pointer"); fprintf(f, "public:\n"); fprintf(f, "\t%s(const PointerRNA &ptr_arg) :\n\t\t%s(ptr_arg)", srna->identifier, - (srna->base) ? srna->base->identifier : "Pointer"); + (srna->base) ? srna->base->identifier : "Pointer"); for (dp = ds->cont.properties.first; dp; dp = dp->next) if (rna_is_collection_prop(dp->prop)) - fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); + fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); fprintf(f, "\n\t\t{}\n\n"); for (dp = ds->cont.properties.first; dp; dp = dp->next) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 1fe46342819..488dbffc3db 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -46,6 +46,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" +#include "BKE_idcode.h" #include "BKE_idprop.h" #include "BKE_main.h" #include "BKE_report.h" @@ -1224,10 +1225,10 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA if (prop->translation_context) nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name); else - nitem[i].name = BLF_gettext(nitem[i].name); + nitem[i].name = BLF_pgettext(NULL, nitem[i].name); } if (nitem[i].description) - nitem[i].description = BLF_gettext(nitem[i].description); + nitem[i].description = BLF_pgettext(NULL, nitem[i].description); } *item = nitem; @@ -2551,7 +2552,10 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) pprop = (PointerPropertyRNA *)prop; /* for groups, data is idprop itself */ - return rna_pointer_inherit_refine(ptr, pprop->type, idprop); + if (pprop->typef) + return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop); + else + return rna_pointer_inherit_refine(ptr, pprop->type, idprop); } else if (pprop->get) { return pprop->get(ptr); @@ -4011,12 +4015,15 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee BLI_assert(haystack->type == IDP_GROUP); link.up = parent_link; + /* always set both name and index, + * else a stale value might get used */ link.name = NULL; link.index = -1; for (i = 0, iter = haystack->data.group.first; iter; iter = iter->next, i++) { if (needle == iter) { /* found! */ link.name = iter->name; + link.index = -1; path = rna_idp_path_create(&link); break; } @@ -4026,6 +4033,7 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee PointerRNA child_ptr = RNA_pointer_get(ptr, iter->name); if (child_ptr.type) { link.name = iter->name; + link.index = -1; if ((path = rna_idp_path(&child_ptr, iter, needle, &link))) { break; } @@ -4143,16 +4151,32 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) path = BLI_sprintfN(is_rna ? "%s.%s" : "%s[\"%s\"]", ptrpath, propname); MEM_freeN(ptrpath); } - else { + else if (RNA_struct_is_ID(ptr->type)) { if (is_rna) path = BLI_strdup(propname); else path = BLI_sprintfN("[\"%s\"]", propname); } + else { + path = NULL; + } return path; } +/** + * Get the ID as a python representation, eg: + * bpy.data.foo["bar"] + */ +char *RNA_path_from_ID_python(ID *id) +{ + char id_esc[(sizeof(id->name) - 2) * 2]; + + BLI_strescape(id_esc, id->name + 2, sizeof(id_esc)); + + return BLI_sprintfN("bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id_esc); +} + /* Quick name based property access */ int RNA_boolean_get(PointerRNA *ptr, const char *name) @@ -5714,7 +5738,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i /* get the length of the array to work with */ len = RNA_property_array_length(ptr, prop); - fromlen = RNA_property_array_length(ptr, prop); + fromlen = RNA_property_array_length(fromptr, prop); if (len != fromlen) return 0; @@ -5828,3 +5852,146 @@ void _RNA_warning(const char *format, ...) } #endif } + +int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop) +{ + /* get the length of the array to work with */ + int len = RNA_property_array_length(a, prop); + int fromlen = RNA_property_array_length(b, prop); + + if (len != fromlen) + return 0; + + /* get and set the default values as appropriate for the various types */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: { + if (len) { + int fixed_a[16], fixed_b[16]; + int *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_b; + + RNA_property_boolean_get_array(a, prop, array_a); + RNA_property_boolean_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(int) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + int value = RNA_property_boolean_get(a, prop); + return value == RNA_property_boolean_get(b, prop); + } + } + + case PROP_INT: { + if (len) { + int fixed_a[16], fixed_b[16]; + int *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_b; + + RNA_property_int_get_array(a, prop, array_a); + RNA_property_int_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(int) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + int value = RNA_property_int_get(a, prop); + return value == RNA_property_int_get(b, prop); + } + } + + case PROP_FLOAT: { + if (len) { + float fixed_a[16], fixed_b[16]; + float *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(float) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(float) * len, "RNA equals"): fixed_b; + + RNA_property_float_get_array(a, prop, array_a); + RNA_property_float_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(float) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + float value = RNA_property_float_get(a, prop); + return value == RNA_property_float_get(b, prop); + } + } + + case PROP_ENUM: { + int value = RNA_property_enum_get(a, prop); + return value == RNA_property_enum_get(b, prop); + } + + case PROP_STRING: { + char fixed_a[128], fixed_b[128]; + int len_a, len_b; + char *value_a = RNA_property_string_get_alloc(a, prop, fixed_a, sizeof(fixed_a), &len_a); + char *value_b = RNA_property_string_get_alloc(b, prop, fixed_b, sizeof(fixed_b), &len_b); + int equals = strcmp(value_a, value_b) == 0; + + if (value_a != fixed_a) MEM_freeN(value_a); + if (value_b != fixed_b) MEM_freeN(value_b); + + return equals; + } + + default: + break; + } + + return 1; +} + +int RNA_struct_equals(PointerRNA *a, PointerRNA *b) +{ + CollectionPropertyIterator iter; +// CollectionPropertyRNA *citerprop; /* UNUSED */ + PropertyRNA *iterprop; + int equals = 1; + + if (a == NULL && b == NULL) + return 1; + else if (a == NULL || b == NULL) + return 0; + else if (a->type != b->type) + return 0; + + iterprop = RNA_struct_iterator_property(a->type); +// citerprop = (CollectionPropertyRNA *)rna_ensure_property(iterprop); /* UNUSED */ + + RNA_property_collection_begin(a, iterprop, &iter); + for (; iter.valid; RNA_property_collection_next(&iter)) { + PropertyRNA *prop = iter.ptr.data; + + if (!RNA_property_equals(a, b, prop)) { + equals = 0; + break; + } + } + RNA_property_collection_end(&iter); + + return equals; +} + diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index ba1aca2baba..1f9503f1cc9 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -46,9 +46,13 @@ #ifdef RNA_RUNTIME -#include "ED_keyframing.h" +#include "BLI_math_base.h" + #include "BKE_fcurve.h" +#include "ED_keyframing.h" + + static void rna_ActionGroup_channels_next(CollectionPropertyIterator *iter) { ListBaseIterator *internal = iter->internal; @@ -191,8 +195,7 @@ static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min, bAction *act = (bAction *)ptr->data; *min = 0; - *max = BLI_countlist(&act->markers) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&act->markers) - 1); } diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index b1fdfccd0be..b653289e44d 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -973,13 +973,13 @@ static void rna_def_sound_actuator(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 2); RNA_def_property_range(prop, 0.0, 2.0); RNA_def_property_ui_text(prop, "Volume", "Initial volume of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_LOGIC, NULL); prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_range(prop, -12.0, 12.0, 1, 2); RNA_def_property_ui_text(prop, "Pitch", "Pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_LOGIC, NULL); /* floats - 3D Parameters */ diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index ce884fa4ecc..7229dddf6d6 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -54,6 +54,8 @@ EnumPropertyItem keyingset_path_grouping_items[] = { #ifdef RNA_RUNTIME +#include "BLI_math_base.h" + #include "BKE_animsys.h" #include "BKE_fcurve.h" #include "BKE_nla.h" @@ -296,6 +298,43 @@ static void rna_ksPath_RnaPath_set(PointerRNA *ptr, const char *value) /* ****************************** */ +static void rna_KeyingSet_name_set(PointerRNA *ptr, const char *value) +{ + KeyingSet *ks = (KeyingSet *)ptr->data; + + /* update names of corresponding groups if name changes */ + if (strcmp(ks->name, value)) { + KS_Path *ksp; + + for (ksp = ks->paths.first; ksp; ksp = ksp->next) { + if ((ksp->groupmode == KSP_GROUP_KSNAME) && (ksp->id)) { + AnimData *adt = BKE_animdata_from_id(ksp->id); + + /* TODO: NLA strips? */ + if (adt && adt->action) { + bActionGroup *agrp; + + /* lazy check - should really find the F-Curve for the affected path and check its group + * but this way should be faster and work well for most cases, as long as there are no + * conflicts + */ + for (agrp = adt->action->groups.first; agrp; agrp = agrp->next) { + if (strcmp(ks->name, agrp->name) == 0) { + /* there should only be one of these in the action, so can stop... */ + BLI_strncpy(agrp->name, value, sizeof(agrp->name)); + break; + } + } + } + } + } + } + + /* finally, update name to new value */ + BLI_strncpy(ks->name, value, sizeof(ks->name)); +} + + static int rna_KeyingSet_active_ksPath_editable(PointerRNA *ptr) { KeyingSet *ks = (KeyingSet *)ptr->data; @@ -334,8 +373,7 @@ static void rna_KeyingSet_active_ksPath_index_range(PointerRNA *ptr, int *min, i KeyingSet *ks = (KeyingSet *)ptr->data; *min = 0; - *max = BLI_countlist(&ks->paths) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&ks->paths) - 1); } static PointerRNA rna_KeyingSet_typeinfo_get(PointerRNA *ptr) @@ -430,7 +468,7 @@ static void rna_NlaTrack_remove(AnimData *adt, bContext *C, ReportList *reports, NlaTrack *track = track_ptr->data; if (BLI_findindex(&adt->nla_tracks, track) == -1) { - BKE_reportf(reports, RPT_ERROR, "NlaTrack '%s' can't be removed", track->name); + BKE_reportf(reports, RPT_ERROR, "NlaTrack '%s' cannot be removed", track->name); return; } @@ -721,19 +759,20 @@ static void rna_def_keyingset(BlenderRNA *brna) srna = RNA_def_struct(brna, "KeyingSet", NULL); RNA_def_struct_ui_text(srna, "Keying Set", "Settings that should be keyframed together"); - /* Id/Label. */ + /* Id/Label */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "idname"); RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP); RNA_def_property_ui_text(prop, "ID Name", KEYINGSET_IDNAME_DOC); - RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL); +/* RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL); */ /* NOTE: disabled, as ID name shouldn't be editable */ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_KeyingSet_name_set"); RNA_def_property_ui_text(prop, "UI Name", ""); RNA_def_struct_ui_icon(srna, ICON_KEYINGSET); RNA_def_struct_name_property(srna, prop); -/* RNA_def_property_update(prop, NC_SCENE|ND_KEYINGSET|NA_RENAME, NULL);*/ + RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL); prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATE); RNA_def_property_string_sdna(prop, NULL, "description"); diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 8e45da50e9b..3da718afd1c 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -80,6 +80,8 @@ EnumPropertyItem boidruleset_type_items[] = { #ifdef RNA_RUNTIME +#include "BLI_math_base.h" + #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_particle.h" @@ -157,8 +159,7 @@ static void rna_BoidState_active_boid_rule_index_range(PointerRNA *ptr, int *min { BoidState *state = (BoidState *)ptr->data; *min = 0; - *max = BLI_countlist(&state->rules) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&state->rules) - 1); } static int rna_BoidState_active_boid_rule_index_get(PointerRNA *ptr) @@ -224,8 +225,7 @@ static void rna_BoidSettings_active_boid_state_index_range(PointerRNA *ptr, int { BoidSettings *boids = (BoidSettings *)ptr->data; *min = 0; - *max = BLI_countlist(&boids->states) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&boids->states) - 1); } static int rna_BoidSettings_active_boid_state_index_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index e96ed4f38d3..7bdebd620ee 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -146,8 +146,8 @@ static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM(br->mtex.brush_map_mode, - MTEX_MAP_MODE_VIEW, - MTEX_MAP_MODE_TILED); + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_TILED); } static int rna_SculptCapabilities_has_persistence_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index f534864e65a..5752fd318c7 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -503,6 +503,10 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain) BKE_movieclip_reload(clip); + /* all sequencers for now, we don't know which scenes are using this clip as a strip */ + BKE_sequencer_cache_cleanup(); + BKE_sequencer_preprocessed_cache_cleanup(); + WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, &clip->id); WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, &clip->id); } diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 7b6b629ca82..30a9bfd81f6 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -614,7 +614,7 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); - RNA_def_property_range(prop, 1, 10000); + RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Iterations", "Maximum number of solving iterations"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 35699c6ef3f..21aed20ccc3 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -242,16 +242,14 @@ static void rna_Curve_material_index_range(PointerRNA *ptr, int *min, int *max, { Curve *cu = (Curve *)ptr->id.data; *min = 0; - *max = cu->totcol - 1; - *max = MAX2(0, *max); + *max = max_ii(0, cu->totcol - 1); } static void rna_Curve_active_textbox_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { Curve *cu = (Curve *)ptr->id.data; *min = 0; - *max = cu->totbox - 1; - *max = MAX2(0, *max); + *max = max_ii(0, cu->totbox - 1); } @@ -1424,6 +1422,11 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Fill Caps", "Fill caps for beveled curves"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); + prop = RNA_def_property(srna, "use_map_taper", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_MAP_TAPER); + RNA_def_property_ui_text(prop, "Map Taper", "Map effect of taper object on actually beveled curve"); + RNA_def_property_update(prop, 0, "rna_Curve_update_data"); + /* texture space */ prop = RNA_def_property(srna, "use_auto_texspace", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "texflag", CU_AUTOSPACE); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index f8af2427827..9fedbee41ff 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -113,7 +113,7 @@ static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void rna_Image_free_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -187,8 +187,12 @@ static EnumPropertyItem *rna_Image_source_itemf(bContext *UNUSED(C), PointerRNA static int rna_Image_file_format_get(PointerRNA *ptr) { Image *image = (Image *)ptr->data; - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); - return BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); + int imtype = BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0); + + BKE_image_release_ibuf(image, ibuf, NULL); + + return imtype; } static void rna_Image_file_format_set(PointerRNA *ptr, int value) @@ -199,12 +203,13 @@ static void rna_Image_file_format_set(PointerRNA *ptr, int value) int ftype = BKE_imtype_to_ftype(value); #if 0 - ibuf = BKE_image_get_ibuf(image, NULL); + ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf) ibuf->ftype = ftype; #endif /* to be safe change all buffer file types */ + /* TODO: this is never threadsafe */ for (ibuf = image->ibufs.first; ibuf; ibuf = ibuf->next) { ibuf->ftype = ftype; } @@ -237,7 +242,7 @@ static void rna_Image_size_get(PointerRNA *ptr, int *values) values[1] = 0; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static void rna_Image_resolution_get(PointerRNA *ptr, float *values) @@ -256,7 +261,7 @@ static void rna_Image_resolution_get(PointerRNA *ptr, float *values) values[1] = 0; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static void rna_Image_resolution_set(PointerRNA *ptr, const float *values) @@ -271,7 +276,7 @@ static void rna_Image_resolution_set(PointerRNA *ptr, const float *values) ibuf->ppm[1] = values[1]; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static int rna_Image_depth_get(PointerRNA *ptr) @@ -290,7 +295,7 @@ static int rna_Image_depth_get(PointerRNA *ptr) else planes = ibuf->planes; - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); return planes; } @@ -317,7 +322,7 @@ static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY else length[0] = 0; - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return length[0]; } @@ -343,7 +348,7 @@ static void rna_Image_pixels_get(PointerRNA *ptr, float *values) } } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) @@ -369,7 +374,7 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } #else diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index cb5c515ce1f..686e6c80f1d 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -99,7 +99,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports IMB_freeImBuf(write_ibuf); } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); } else { BKE_report(reports, RPT_ERROR, "Scene not in context, could not get save parameters"); @@ -108,7 +108,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports static void rna_Image_save(Image *image, ReportList *reports) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf) { char filename[FILE_MAX]; BLI_strncpy(filename, image->name, sizeof(filename)); @@ -136,11 +136,13 @@ static void rna_Image_save(Image *image, ReportList *reports) else { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); } + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_pack(Image *image, ReportList *reports, int as_png) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { BKE_report(reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG"); @@ -153,6 +155,8 @@ static void rna_Image_pack(Image *image, ReportList *reports, int as_png) image->packedfile = newPackedFile(reports, image->name, ID_BLEND_PATH(G.main, &image->id)); } } + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_unpack(Image *image, ReportList *reports, int method) @@ -177,7 +181,7 @@ static void rna_Image_reload(Image *image) static void rna_Image_update(Image *image, ReportList *reports) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf == NULL) { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); @@ -188,6 +192,8 @@ static void rna_Image_update(Image *image, ReportList *reports) IMB_rect_from_float(ibuf); ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_scale(Image *image, ReportList *reports, int width, int height) @@ -206,10 +212,11 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int if (*bind) return error; - ibuf = BKE_image_get_ibuf(image, NULL); + ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf == NULL || ibuf->rect == NULL) { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); + BKE_image_release_ibuf(image, ibuf, NULL); return (int)GL_INVALID_OPERATION; } @@ -238,6 +245,8 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int image->bindcode = 0; } + BKE_image_release_ibuf(image, ibuf, NULL); + return error; } diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 9d63e0e687d..af39500442d 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -421,7 +421,7 @@ static void rna_def_lamp(BlenderRNA *brna) /* textures */ rna_def_mtex_common(brna, srna, "rna_Lamp_mtex_begin", "rna_Lamp_active_texture_get", - "rna_Lamp_active_texture_set", NULL, "LampTextureSlot", "LampTextureSlots", "rna_Lamp_update"); + "rna_Lamp_active_texture_set", NULL, "LampTextureSlot", "LampTextureSlots", "rna_Lamp_draw_update"); } static void rna_def_lamp_falloff(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 56caa254a59..3f23a376ea3 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -158,8 +158,7 @@ static void rna_Mask_layer_active_index_range(PointerRNA *ptr, int *min, int *ma Mask *mask = (Mask *)ptr->id.data; *min = 0; - *max = mask->masklay_tot - 1; - *max = MAX2(0, *max); + *max = max_ii(0, mask->masklay_tot - 1); *softmin = *min; *softmax = *max; diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 9232ae098ea..1221b84372c 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -2121,13 +2121,13 @@ void rna_def_mtex_common(BlenderRNA *brna, StructRNA *srna, const char *begin, RNA_def_property_editable_func(prop, activeeditable); RNA_def_property_pointer_funcs(prop, activeget, activeset, NULL, NULL); RNA_def_property_ui_text(prop, "Active Texture", "Active texture slot being displayed"); - RNA_def_property_update(prop, 0, update); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, update); prop = RNA_def_property(srna, "active_texture_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "texact"); RNA_def_property_range(prop, 0, MAX_MTEX - 1); RNA_def_property_ui_text(prop, "Active Texture Index", "Index of active texture slot"); - RNA_def_property_update(prop, 0, update); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, update); } #endif diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index f0b84332d07..287995e0aa6 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -1010,8 +1010,7 @@ static void rna_MeshPoly_material_index_range(PointerRNA *ptr, int *min, int *ma { Mesh *me = rna_mesh(ptr); *min = 0; - *max = me->totcol - 1; - *max = MAX2(0, *max); + *max = max_ii(0, me->totcol - 1); } static int rna_MeshVertex_index_get(PointerRNA *ptr) @@ -2810,7 +2809,7 @@ static void rna_def_mesh(BlenderRNA *brna) prop = RNA_def_property(srna, "skin_vertices", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer"); RNA_def_property_collection_funcs(prop, "rna_Mesh_skin_vertices_begin", NULL, NULL, NULL, - "rna_Mesh_skin_vertices_length", NULL, NULL, NULL); + "rna_Mesh_skin_vertices_length", NULL, NULL, NULL); RNA_def_property_struct_type(prop, "MeshSkinVertexLayer"); RNA_def_property_ui_text(prop, "Skin Vertices", "All skin vertices"); rna_def_skin_vertices(brna, prop); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 8eca7162d39..a2b0945fb46 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -78,6 +78,7 @@ EnumPropertyItem modifier_type_items[] = { {eModifierType_Skin, "SKIN", ICON_MOD_SKIN, "Skin", ""}, {eModifierType_Solidify, "SOLIDIFY", ICON_MOD_SOLIDIFY, "Solidify", ""}, {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""}, + {eModifierType_Triangulate, "TRIANGULATE", ICON_MOD_TRIANGULATE, "Triangulate", ""}, {0, "", 0, N_("Deform"), ""}, {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""}, {eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""}, @@ -213,6 +214,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_SkinModifier; case eModifierType_LaplacianSmooth: return &RNA_LaplacianSmoothModifier; + case eModifierType_Triangulate: + return &RNA_TriangulateModifier; default: return &RNA_Modifier; } @@ -481,8 +484,7 @@ static void rna_MultiresModifier_level_range(PointerRNA *ptr, int *min, int *max MultiresModifierData *mmd = (MultiresModifierData *)ptr->data; *min = 0; - *max = mmd->totlvl; /* intentionally _not_ -1 */ - *max = MAX2(0, *max); + *max = max_ii(0, mmd->totlvl); /* intentionally _not_ -1 */ } static int rna_MultiresModifier_external_get(PointerRNA *ptr) @@ -1815,7 +1817,7 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "use_volume_preserve", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME); RNA_def_property_ui_text(prop, "Preserve Volume", "Apply volume preservation after smooth"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); @@ -2205,6 +2207,7 @@ static void rna_def_modifier_smoke(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_smoke_type_items); RNA_def_property_ui_text(prop, "Type", ""); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_Smoke_set_type"); } @@ -2401,6 +2404,13 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Offset", "Distance to keep from the target"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "project_limit", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "projLimit"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Project Limit", "Limit the distance used for projection (zero disables)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_project_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS); RNA_def_property_ui_text(prop, "X", ""); @@ -3355,6 +3365,22 @@ static void rna_def_modifier_skin(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_triangulate(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "TriangulateModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Triangulate Modifier", "Triangulate Mesh"); + RNA_def_struct_sdna(srna, "TriangulateModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE); + + prop = RNA_def_property(srna, "use_beauty", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_TRIANGULATE_BEAUTY); + RNA_def_property_ui_text(prop, "Beauty Subdivide", "Subdivide across shortest diagonal"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); +} + void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -3462,6 +3488,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_remesh(brna); rna_def_modifier_skin(brna); rna_def_modifier_laplaciansmooth(brna); + rna_def_modifier_triangulate(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index ece5c82f747..1da9a450c2c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -92,6 +92,7 @@ EnumPropertyItem node_socket_type_items[] = { {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, {SOCK_MESH, "MESH", 0, "Mesh", ""}, {SOCK_INT, "INT", 0, "Int", ""}, + {SOCK_STRING, "STRING", 0, "String", ""}, {0, NULL, 0, NULL, NULL} }; @@ -192,6 +193,10 @@ EnumPropertyItem prop_wave_items[] = { SUBTYPE(FLOAT, Float, TIME, Time) \ SUBTYPE(FLOAT, Float, DISTANCE, Distance) +#define NODE_DEFINE_SUBTYPES_STRING \ + SUBTYPE(STRING, String, NONE, None) \ + SUBTYPE(STRING, String, FILEPATH, Filepath) + #define NODE_DEFINE_SUBTYPES_VECTOR \ SUBTYPE(VECTOR, Vector, NONE, None) \ SUBTYPE(VECTOR, Vector, TRANSLATION, Translation) \ @@ -204,7 +209,8 @@ EnumPropertyItem prop_wave_items[] = { #define NODE_DEFINE_SUBTYPES \ NODE_DEFINE_SUBTYPES_INT \ NODE_DEFINE_SUBTYPES_FLOAT \ - NODE_DEFINE_SUBTYPES_VECTOR + NODE_DEFINE_SUBTYPES_STRING \ + NODE_DEFINE_SUBTYPES_VECTOR \ #ifdef RNA_RUNTIME @@ -214,6 +220,7 @@ EnumPropertyItem prop_wave_items[] = { #include "ED_node.h" +#include "RE_engine.h" #include "RE_pipeline.h" #include "DNA_scene_types.h" @@ -292,6 +299,9 @@ static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr) case SOCK_VECTOR: NODE_DEFINE_SUBTYPES_VECTOR break; + case SOCK_STRING: + NODE_DEFINE_SUBTYPES_STRING + break; case SOCK_RGBA: return &RNA_NodeSocketRGBA; case SOCK_SHADER: @@ -1124,6 +1134,22 @@ static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, int create) return nss->prop; } +static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + + if (engine_type && engine_type->update_script_node) { + /* auto update node */ + RenderEngine *engine = RE_engine_create(engine_type); + engine_type->update_script_node(engine, ntree, node); + RE_engine_free(engine); + } + + node_update(bmain, scene, ntree, node); +} + #else static EnumPropertyItem prop_image_layer_items[] = { @@ -1166,7 +1192,7 @@ static EnumPropertyItem node_glossy_items[] = { static EnumPropertyItem node_script_mode_items[] = { {NODE_SCRIPT_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"}, - {NODE_SCRIPT_EXTERNAL, "EXTERNAL", 0, "External", "Use external .osl or oso file"}, + {NODE_SCRIPT_EXTERNAL, "EXTERNAL", 0, "External", "Use external .osl or .oso file"}, {0, NULL, 0, NULL, NULL} }; @@ -1195,7 +1221,7 @@ typedef struct NodeInfo { static NodeInfo nodes[MaxNodes]; static void reg_node(int ID, int category, const char *enum_name, const char *struct_name, - const char *base_name, const char *ui_name, const char *ui_desc) + const char *base_name, const char *ui_name, const char *ui_desc) { NodeInfo *ni = nodes + ID; @@ -1275,6 +1301,14 @@ static void alloc_node_type_items(EnumPropertyItem *items, int category) item++; + item->value = NODE_FRAME; + item->identifier = "FRAME"; + item->icon = 0; + item->name = "Frame"; + item->description = ""; + + item++; + /* NOTE!, increase 'count' when adding items here */ memset(item, 0, sizeof(EnumPropertyItem)); @@ -1842,6 +1876,67 @@ static void def_glossy(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_sh_normal_map(StructRNA *srna) +{ + static EnumPropertyItem prop_space_items[] = { + {SHD_NORMAL_MAP_TANGENT, "TANGENT", 0, "Tangent Space", "Tangent space normal mapping"}, + {SHD_NORMAL_MAP_OBJECT, "OBJECT", 0, "Object Space", "Object space normal mapping"}, + {SHD_NORMAL_MAP_WORLD, "WORLD", 0, "World Space", "World space normal mapping"}, + {0, NULL, 0, NULL, NULL} + }; + + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeShaderNormalMap", "storage"); + + prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_space_items); + RNA_def_property_ui_text(prop, "Space", "Space of the input normal"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "uv_map", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "UV Map", "UV Map for tangent space maps"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "bNode", NULL); +} + +static void def_sh_tangent(StructRNA *srna) +{ + static EnumPropertyItem prop_direction_type_items[] = { + {SHD_TANGENT_RADIAL, "RADIAL", 0, "Radial", "Radial tangent around the X, Y or Z axis"}, + {SHD_TANGENT_UVMAP, "UV_MAP", 0, "UV Map", "Tangent from UV map"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem prop_axis_items[] = { + {SHD_TANGENT_AXIS_X, "X", 0, "X", "X axis"}, + {SHD_TANGENT_AXIS_Y, "Y", 0, "Y", "Y axis"}, + {SHD_TANGENT_AXIS_Z, "Z", 0, "Z", "Z axis"}, + {0, NULL, 0, NULL, NULL} + }; + + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeShaderTangent", "storage"); + + prop = RNA_def_property(srna, "direction_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_direction_type_items); + RNA_def_property_ui_text(prop, "Direction", "Method to use for the tangent"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_axis_items); + RNA_def_property_ui_text(prop, "Axis", "Axis for radial tangents"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "uv_map", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "UV Map", "UV Map for tangent generated from UV"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "bNode", NULL); +} + static void def_sh_script(StructRNA *srna) { FunctionRNA *func; @@ -1852,14 +1947,14 @@ static void def_sh_script(StructRNA *srna) RNA_def_property_struct_type(prop, "Text"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_ui_text(prop, "Script", "Internal shader script to define the shader"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update"); RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage"); RNA_def_struct_idprops_func(srna, "rna_ShaderNodeScript_idprops"); prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); RNA_def_property_ui_text(prop, "File Path", "Shader script path"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update"); prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeScript_mode_set", NULL); @@ -1869,11 +1964,12 @@ static void def_sh_script(StructRNA *srna) prop = RNA_def_property(srna, "use_auto_update", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SCRIPT_AUTO_UPDATE); - RNA_def_property_ui_text(prop, "Auto Update", "Automatically updates the shader when the .osl file changes - external scripts only"); + RNA_def_property_ui_text(prop, "Auto Update", + "Automatically update the shader when the .osl file changes (external scripts only)"); prop = RNA_def_property(srna, "bytecode", PROP_STRING, PROP_NONE); - RNA_def_property_string_funcs(prop, "rna_ShaderNodeScript_bytecode_get", - "rna_ShaderNodeScript_bytecode_length", "rna_ShaderNodeScript_bytecode_set"); + RNA_def_property_string_funcs(prop, "rna_ShaderNodeScript_bytecode_get", "rna_ShaderNodeScript_bytecode_length", + "rna_ShaderNodeScript_bytecode_set"); RNA_def_property_ui_text(prop, "Bytecode", "Compile bytecode for shader script node"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -2103,6 +2199,16 @@ static void def_cmp_map_value(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_map_range(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); + RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_cmp_vector_blur(StructRNA *srna) { PropertyRNA *prop; @@ -4464,6 +4570,20 @@ static void rna_def_node_socket_subtype(BlenderRNA *brna, int type, int subtype, RNA_def_property_ui_text(prop, "Default Value", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); break; + case SOCK_STRING: + RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value"); + + prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "subtype"); + RNA_def_property_enum_items(prop, subtype_items); + RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); + + prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_FILEPATH); + RNA_def_property_string_sdna(prop, NULL, "value"); + RNA_def_property_ui_text(prop, "Default Value", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); + break; } /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */ @@ -4531,18 +4651,22 @@ static void rna_def_node(BlenderRNA *brna) prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SELECT); RNA_def_property_ui_text(prop, "Select", ""); + RNA_def_property_update(prop, NC_NODE | NA_SELECTED, NULL); prop = RNA_def_property(srna, "show_options", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_OPTIONS); RNA_def_property_ui_text(prop, "Show Options", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "show_preview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_PREVIEW); RNA_def_property_ui_text(prop, "Show Preview", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_HIDDEN); RNA_def_property_ui_text(prop, "Hide", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_MUTED); diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index c45c9b71442..14cdbc6cf7d 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -65,12 +65,14 @@ DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LA DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" ) DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" ) DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" ) +DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" ) DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "" ) DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" ) DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass Bsdf", "" ) +DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BSDF_REFRACTION", BsdfRefraction, "Refraction Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet Bsdf", "" ) @@ -82,7 +84,9 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" ) DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) -DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", BumpNode, "Bump", "" ) +DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", Bump, "Bump", "" ) +DefNode( ShaderNode, SH_NODE_NORMAL_MAP, def_sh_normal_map, "NORMAL_MAP", NormalMap, "Normal Map", "" ) +DefNode( ShaderNode, SH_NODE_TANGENT, def_sh_tangent, "TANGENT", Tangent, "Tangent", "" ) DefNode( ShaderNode, SH_NODE_SCRIPT, def_sh_script, "SCRIPT", Script, "Script", "" ) DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" ) @@ -110,6 +114,7 @@ DefNode( CompositorNode, CMP_NODE_ALPHAOVER, def_cmp_alpha_over, "ALPHA DefNode( CompositorNode, CMP_NODE_BLUR, def_cmp_blur, "BLUR", Blur, "Blur", "" ) DefNode( CompositorNode, CMP_NODE_FILTER, def_cmp_filter, "FILTER", Filter, "Filter", "" ) DefNode( CompositorNode, CMP_NODE_MAP_VALUE, def_cmp_map_value, "MAP_VALUE", MapValue, "Map Value", "" ) +DefNode( CompositorNode, CMP_NODE_MAP_RANGE, def_cmp_map_range, "MAP_RANGE", MapRange, "Map Range", "" ) DefNode( CompositorNode, CMP_NODE_TIME, def_time, "TIME", Time, "Time", "" ) DefNode( CompositorNode, CMP_NODE_VECBLUR, def_cmp_vector_blur, "VECBLUR", VecBlur, "Vector Blur", "" ) DefNode( CompositorNode, CMP_NODE_SEPRGBA, 0, "SEPRGBA", SepRGBA, "Separate RGBA", "" ) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 10f361ef1bd..1d08ea97b79 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -94,6 +94,15 @@ static EnumPropertyItem parent_type_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem dupli_items[] = { + {0, "NONE", 0, "None", ""}, + {OB_DUPLIFRAMES, "FRAMES", 0, "Frames", "Make copy of object for every frame"}, + {OB_DUPLIVERTS, "VERTS", 0, "Verts", "Duplicate child objects on all vertices"}, + {OB_DUPLIFACES, "FACES", 0, "Faces", "Duplicate child objects on all faces"}, + {OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing"}, + {0, NULL, 0, NULL, NULL} +}; + static EnumPropertyItem collision_bounds_items[] = { {OB_BOUND_BOX, "BOX", 0, "Box", ""}, {OB_BOUND_SPHERE, "SPHERE", 0, "Sphere", ""}, @@ -547,8 +556,7 @@ static void rna_Object_active_vertex_group_index_range(PointerRNA *ptr, int *min Object *ob = (Object *)ptr->id.data; *min = 0; - *max = BLI_countlist(&ob->defbase) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&ob->defbase) - 1); } void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index) @@ -658,7 +666,7 @@ static void rna_Object_active_material_index_range(PointerRNA *ptr, int *min, in { Object *ob = (Object *)ptr->id.data; *min = 0; - *max = MAX2(ob->totcol - 1, 0); + *max = max_ii(ob->totcol - 1, 0); } /* returns active base material */ @@ -684,8 +692,7 @@ static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int * { Object *ob = (Object *)ptr->id.data; *min = 0; - *max = BLI_countlist(&ob->particlesystem) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&ob->particlesystem) - 1); } static int rna_Object_active_particle_system_index_get(PointerRNA *ptr) @@ -1421,6 +1428,12 @@ int rna_Camera_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) return ((Object *)value.id.data)->type == OB_CAMERA; } +int rna_DupliObject_index_get(PointerRNA *ptr) +{ + DupliObject *dob = (DupliObject *)ptr->data; + return dob->persistent_id[0]; +} + #else static int rna_matrix_dimsize_4x4[] = {4, 4}; @@ -1639,21 +1652,23 @@ static void rna_def_object_game_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed"); + /* Character physics */ prop = RNA_def_property(srna, "step_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "step_height"); - RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_range(prop, 0.01, 1.0); RNA_def_property_ui_text(prop, "Step Height", "Maximum height of steps the character can run over"); prop = RNA_def_property(srna, "jump_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "jump_speed"); RNA_def_property_range(prop, 0.0, 1000.0); - RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping (with the Motion actuator)"); + RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping"); prop = RNA_def_property(srna, "fall_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fall_speed"); RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall"); + /* Collision Masks */ prop = RNA_def_property(srna, "collision_group", PROP_BOOLEAN, PROP_LAYER_MEMBER); RNA_def_property_boolean_sdna(prop, NULL, "col_group", 1); RNA_def_property_array(prop, OB_MAX_COL_MASKS); @@ -2013,15 +2028,7 @@ static void rna_def_object(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem dupli_items[] = { - {0, "NONE", 0, "None", ""}, - {OB_DUPLIFRAMES, "FRAMES", 0, "Frames", "Make copy of object for every frame"}, - {OB_DUPLIVERTS, "VERTS", 0, "Verts", "Duplicate child objects on all vertices"}, - {OB_DUPLIFACES, "FACES", 0, "Faces", "Duplicate child objects on all faces"}, - {OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing"}, - {0, NULL, 0, NULL, NULL} - }; - + /* XXX: this RNA enum define is currently duplicated for objects, * since there is some text here which is not applicable */ static EnumPropertyItem prop_rotmode_items[] = { @@ -2168,7 +2175,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_Object_active_material_index_get", "rna_Object_active_material_index_set", "rna_Object_active_material_index_range"); RNA_def_property_ui_text(prop, "Active Material Index", "Index of active material slot"); - RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, NULL); /* transform */ prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION); @@ -2655,25 +2662,31 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Hide", "Don't show dupli object in viewport or render"); prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "index"); + RNA_def_property_int_funcs(prop, "rna_DupliObject_index_get", NULL, NULL); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Index", "Index in the lowest-level dupli list"); - - prop = RNA_def_property(srna, "particle_index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "particle_index"); + + prop = RNA_def_property(srna, "persistent_id", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Particle Index", "Index in the lowest-level particle dupli list"); + RNA_def_property_ui_text(prop, "Persistent ID", "Persistent identifier for inter-frame matching of objects with motion blur"); + + prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Particle System", "Particle system that this dupli object was instanced from"); prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_float_sdna(prop, NULL, "orco"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space"); prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "uv"); RNA_def_property_array(prop, 2); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space"); + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, dupli_items); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object"); } static void rna_def_object_base(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index f47b864d25a..6d7187da7d9 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -51,6 +51,9 @@ static EnumPropertyItem effector_shape_items[] = { #ifdef RNA_RUNTIME +#include "BLI_math_base.h" + + /* type specific return values only used from functions */ static EnumPropertyItem curve_shape_items[] = { {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""}, @@ -239,8 +242,7 @@ static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min, for (pid = pidlist.first; pid; pid = pid->next) { if (pid->cache == cache) { - *max = BLI_countlist(pid->ptcaches) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(pid->ptcaches) - 1); break; } } diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 9ba2a062791..6825d3d781d 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -530,8 +530,7 @@ static void rna_ParticleSystem_active_particle_target_index_range(PointerRNA *pt { ParticleSystem *psys = (ParticleSystem *)ptr->data; *min = 0; - *max = BLI_countlist(&psys->targets) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&psys->targets) - 1); } static int rna_ParticleSystem_active_particle_target_index_get(PointerRNA *ptr) @@ -670,8 +669,7 @@ static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min { ParticleSettings *part = (ParticleSettings *)ptr->id.data; *min = 0; - *max = BLI_countlist(&part->dupliweights) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&part->dupliweights) - 1); } static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index c29537378dd..5c90fb8787c 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -381,13 +381,7 @@ static void rna_PoseChannel_bone_group_index_range(PointerRNA *ptr, int *min, in bPose *pose = (ob) ? ob->pose : NULL; *min = 0; - - if (pose) { - *max = BLI_countlist(&pose->agroups) - 1; - *max = MAX2(0, *max); - } - else - *max = 0; + *max = pose ? max_ii(0, BLI_countlist(&pose->agroups) - 1) : 0; } static PointerRNA rna_Pose_active_bone_group_get(PointerRNA *ptr) @@ -419,8 +413,7 @@ static void rna_Pose_active_bone_group_index_range(PointerRNA *ptr, int *min, in bPose *pose = (bPose *)ptr->data; *min = 0; - *max = BLI_countlist(&pose->agroups) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&pose->agroups) - 1); } #if 0 @@ -682,7 +675,7 @@ static void rna_def_bone_group(BlenderRNA *brna) } static EnumPropertyItem prop_iksolver_items[] = { - {IKSOLVER_LEGACY, "LEGACY", 0, "Legacy", "Original IK solver"}, + {IKSOLVER_STANDARD, "LEGACY", 0, "Standard", "Original IK solver"}, {IKSOLVER_ITASC, "ITASC", 0, "iTaSC", "Multi constraint, stateful IK solver"}, {0, NULL, 0, NULL, NULL} }; @@ -1133,7 +1126,7 @@ static void rna_def_pose_itasc(BlenderRNA *brna) prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "numiter"); - RNA_def_property_range(prop, 1.f, 1000.f); + RNA_def_property_range(prop, 0, 1000); RNA_def_property_ui_text(prop, "Iterations", "Maximum number of iterations for convergence in case of reiteration"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update"); @@ -1228,8 +1221,7 @@ static void rna_def_pose_ikparam(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "iksolver"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_items(prop, prop_iksolver_items); - RNA_def_property_ui_text(prop, "IK Solver", - "IK solver for which these parameters are defined, 0 for Legacy, 1 for iTaSC"); + RNA_def_property_ui_text(prop, "IK Solver", "IK solver for which these parameters are defined"); } /* pose.bone_groups */ @@ -1292,8 +1284,7 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "iksolver"); RNA_def_property_enum_funcs(prop, NULL, "rna_Pose_ik_solver_set", NULL); RNA_def_property_enum_items(prop, prop_iksolver_items); - RNA_def_property_ui_text(prop, "IK Solver", - "Selection of IK solver for IK chain, current choice is 0 for Legacy, 1 for iTaSC"); + RNA_def_property_ui_text(prop, "IK Solver", "Selection of IK solver for IK chain"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_ik_solver_update"); prop = RNA_def_property(srna, "ik_param", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 69bb1cc98ff..6f3a483cf7e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -145,6 +145,11 @@ EnumPropertyItem snap_node_element_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem snap_uv_element_items[] = { + {SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"}, + {SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"}, + {0, NULL, 0, NULL, NULL} +}; /* workaround for duplicate enums, * have each enum line as a defne then conditionally set it or not @@ -1002,8 +1007,7 @@ static void rna_RenderSettings_active_layer_index_range(PointerRNA *ptr, int *mi RenderData *rd = (RenderData *)ptr->data; *min = 0; - *max = BLI_countlist(&rd->layers) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&rd->layers) - 1); } static PointerRNA rna_RenderSettings_active_layer_get(PointerRNA *ptr) @@ -1124,6 +1128,12 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) } } +static char *rna_SceneRenderLayer_path(PointerRNA *ptr) +{ + SceneRenderLayer *srl = (SceneRenderLayer*)ptr->data; + return BLI_sprintfN("render.layers[\"%s\"]", srl->name); +} + static int rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr)) { return (BLI_countlist(&R_engines) > 1); @@ -1255,6 +1265,12 @@ static void rna_Scene_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr rna_Scene_use_simplify_update(bmain, scene, ptr); } +static void rna_Scene_use_persistent_data_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr)) +{ + if (!(scene->r.mode & R_PERSISTENT_DATA)) + RE_FreePersistentData(); +} + static int rna_Scene_use_audio_get(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->data; @@ -1631,6 +1647,13 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, snap_node_element_items); RNA_def_property_ui_text(prop, "Snap Node Element", "Type of element to snap to"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + /* image editor uses own set of snap modes */ + prop = RNA_def_property(srna, "snap_uv_element", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "snap_uv_mode"); + RNA_def_property_enum_items(prop, snap_uv_element_items); + RNA_def_property_ui_text(prop, "Snap UV Element", "Type of element to snap to"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ prop = RNA_def_property(srna, "snap_target", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "snap_target"); @@ -2770,6 +2793,7 @@ static void rna_def_scene_render_layer(BlenderRNA *brna) srna = RNA_def_struct(brna, "SceneRenderLayer", NULL); RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer"); RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS); + RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path"); rna_def_render_layer_common(srna, 1); } @@ -3126,7 +3150,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "Audio volume"); - RNA_def_property_translation_context(prop, "Audio"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); #endif @@ -3949,6 +3973,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_sequencer_gl_preview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_GL_PREV); RNA_def_property_ui_text(prop, "Sequencer OpenGL", ""); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update"); #if 0 /* see R_SEQ_GL_REND comment */ prop = RNA_def_property(srna, "use_sequencer_gl_render", PROP_BOOLEAN, PROP_NONE); @@ -4037,6 +4062,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", R_SIMPLE_NO_TRIANGULATE); RNA_def_property_ui_text(prop, "Skip Quad to Triangles", "Disable non-planar quads being triangulated"); + /* persistent data */ + prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mode", R_PERSISTENT_DATA); + RNA_def_property_ui_text(prop, "Persistent Data", "Keep render data around for faster re-renders"); + RNA_def_property_update(prop, 0, "rna_Scene_use_persistent_data_update"); + /* Scene API */ RNA_api_scene_render(srna); } @@ -4541,7 +4572,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "audio.volume"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "Audio volume"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_SCENE, NULL); RNA_def_property_float_funcs(prop, NULL, "rna_Scene_volume_set", NULL); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 63253153699..012767b5845 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -62,12 +62,16 @@ static void rna_Scene_frame_set(Scene *scene, int frame, float subframe) BKE_scene_update_for_newframe(G.main, scene, (1 << 20) - 1); BKE_scene_camera_switch_update(scene); - /* cant use NC_SCENE|ND_FRAME because this causes wm_event_do_notifiers to call - * BKE_scene_update_for_newframe which will loose any un-keyed changes [#24690] */ - /* WM_main_add_notifier(NC_SCENE|ND_FRAME, scene); */ - - /* instead just redraw the views */ - WM_main_add_notifier(NC_WINDOW, NULL); + /* don't do notifier when we're rendering, avoid some viewport crashes + * redrawing while the data is being modified for render */ + if (!G.is_rendering) { + /* cant use NC_SCENE|ND_FRAME because this causes wm_event_do_notifiers to call + * BKE_scene_update_for_newframe which will loose any un-keyed changes [#24690] */ + /* WM_main_add_notifier(NC_SCENE|ND_FRAME, scene); */ + + /* instead just redraw the views */ + WM_main_add_notifier(NC_WINDOW, NULL); + } } static void rna_Scene_update_tagged(Scene *scene) diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index c2fa64698e4..18a9b9683f8 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1875,7 +1875,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "volume"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -1883,7 +1883,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 962a92223eb..2b2e8d97499 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -598,7 +598,7 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *UNUS alpha = ibuf && (ibuf->channels == 4); zbuf = ibuf && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1)); - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); if (alpha && zbuf) return draw_channels_items; @@ -678,7 +678,7 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); WM_main_add_notifier(NC_IMAGE, sima->image); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } /* Space Text Editor */ @@ -2976,10 +2976,9 @@ static void rna_def_space_node(BlenderRNA *brna) {SNODE_USE_ALPHA, "COLOR_ALPHA", ICON_IMAGE_RGB_ALPHA, "Color and Alpha", "Draw image with RGB colors and alpha transparency"}, {SNODE_SHOW_ALPHA, "ALPHA", ICON_IMAGE_ALPHA, "Alpha", "Draw alpha transparency channel"}, - /* XXX, we could use better icons here */ - {SNODE_SHOW_R, "RED", ICON_COLOR, "Red", ""}, - {SNODE_SHOW_G, "GREEN", ICON_COLOR, "Green", ""}, - {SNODE_SHOW_B, "BLUE", ICON_COLOR, "Blue", ""}, + {SNODE_SHOW_R, "RED", ICON_COLOR_RED, "Red", ""}, + {SNODE_SHOW_G, "GREEN", ICON_COLOR_GREEN, "Green", ""}, + {SNODE_SHOW_B, "BLUE", ICON_COLOR_BLUE, "Blue", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c index a160aaf94e2..139582104ee 100644 --- a/source/blender/makesrna/intern/rna_speaker.c +++ b/source/blender/makesrna/intern/rna_speaker.c @@ -152,7 +152,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "volume"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "How loud the sound is"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ @@ -160,7 +160,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_pitch_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c index e46373b250c..b1637ef4c8a 100644 --- a/source/blender/makesrna/intern/rna_text.c +++ b/source/blender/makesrna/intern/rna_text.c @@ -129,49 +129,6 @@ static void rna_def_text_line(BlenderRNA *brna) RNA_def_property_update(prop, NC_TEXT | NA_EDITED, NULL); } -static void rna_def_text_marker(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "TextMarker", NULL); - RNA_def_struct_ui_text(srna, "Text Marker", "Marker highlighting a portion of text in a Text datablock"); - - prop = RNA_def_property(srna, "line", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "lineno"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Line", "Line in which the marker is located"); - - prop = RNA_def_property(srna, "character_index_start", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "start"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Start", "Start position of the marker in the line"); - - prop = RNA_def_property(srna, "character_index_end", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "end"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "End", "Start position of the marker in the line"); - - prop = RNA_def_property(srna, "group", PROP_INT, PROP_UNSIGNED); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_range(prop, 0, (int)0xFFFF); - RNA_def_property_ui_text(prop, "Group", ""); - - prop = RNA_def_property(srna, "is_temporary", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flags", TMARK_TEMP); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Temporary", "Marker is temporary"); - - prop = RNA_def_property(srna, "use_edit_all", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flags", TMARK_EDITALL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Edit All", "Edit all markers of the same group as one"); - - prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); - RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Color", "Color to display the marker with"); -} - static void rna_def_text(BlenderRNA *brna) { StructRNA *srna; @@ -241,17 +198,12 @@ static void rna_def_text(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Selection End Character", "Index of character after end of selection in the selection end line"); - prop = RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE); - RNA_def_property_struct_type(prop, "TextMarker"); - RNA_def_property_ui_text(prop, "Markers", "Text markers highlighting part of the text"); - RNA_api_text(srna); } void RNA_def_text(BlenderRNA *brna) { rna_def_text_line(brna); - rna_def_text_marker(brna); rna_def_text(brna); } diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index e77c5d13a6b..bdf9fa4e436 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -46,6 +46,9 @@ #include "BKE_node.h" +#include "WM_api.h" +#include "WM_types.h" + EnumPropertyItem texture_filter_items[] = { {TXF_BOX, "BOX", 0, "Box", ""}, {TXF_EWA, "EWA", 0, "EWA", ""}, @@ -110,9 +113,6 @@ EnumPropertyItem blend_type_items[] = { #include "ED_node.h" -#include "WM_api.h" -#include "WM_types.h" - static StructRNA *rna_Texture_refine(struct PointerRNA *ptr) { Tex *tex = (Tex *)ptr->data; @@ -233,6 +233,7 @@ void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN break; case ID_LA: WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id); + WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, id); break; case ID_BR: WM_main_add_notifier(NC_BRUSH, id); @@ -263,19 +264,24 @@ char *rna_TextureSlot_path(PointerRNA *ptr) * may be used multiple times in the same stack */ if (ptr->id.data) { - PointerRNA id_ptr; - PropertyRNA *prop; - - /* find the 'textures' property of the ID-struct */ - RNA_id_pointer_create(ptr->id.data, &id_ptr); - prop = RNA_struct_find_property(&id_ptr, "texture_slots"); - - /* get an iterator for this property, and try to find the relevant index */ - if (prop) { - int index = RNA_property_collection_lookup_index(&id_ptr, prop, ptr); - - if (index >= 0) - return BLI_sprintfN("texture_slots[%d]", index); + if (GS(((ID *)ptr->id.data)->name) == ID_BR) { + return BLI_strdup("texture_slot"); + } + else { + PointerRNA id_ptr; + PropertyRNA *prop; + + /* find the 'textures' property of the ID-struct */ + RNA_id_pointer_create(ptr->id.data, &id_ptr); + prop = RNA_struct_find_property(&id_ptr, "texture_slots"); + + /* get an iterator for this property, and try to find the relevant index */ + if (prop) { + int index = RNA_property_collection_lookup_index(&id_ptr, prop, ptr); + + if (index >= 0) + return BLI_sprintfN("texture_slots[%d]", index); + } } } @@ -602,7 +608,7 @@ static void rna_def_mtex(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Texture"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Texture", "Texture datablock used by this texture slot"); - RNA_def_property_update(prop, 0, "rna_TextureSlot_update"); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlot_update"); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_TextureSlot_name_get", "rna_TextureSlot_name_length", NULL); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 51b50f78e66..4aefaf991d2 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -120,8 +120,7 @@ static void rna_tracking_active_object_index_range(PointerRNA *ptr, int *min, in MovieClip *clip = (MovieClip *)ptr->id.data; *min = 0; - *max = clip->tracking.tot_object - 1; - *max = MAX2(0, *max); + *max = max_ii(0, clip->tracking.tot_object - 1); } static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr) @@ -263,8 +262,7 @@ static void rna_tracking_stabTracks_active_index_range(PointerRNA *ptr, int *min MovieClip *clip = (MovieClip *)ptr->id.data; *min = 0; - *max = clip->tracking.stabilization.tot_track - 1; - *max = MAX2(0, *max); + *max = max_ii(0, clip->tracking.stabilization.tot_track - 1); } static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) @@ -452,7 +450,7 @@ static void rna_trackingObject_remove(MovieTracking *tracking, ReportList *repor { MovieTrackingObject *object = object_ptr->data; if (BKE_tracking_object_delete(tracking, object) == FALSE) { - BKE_reportf(reports, RPT_ERROR, "MovieTracking '%s' can't be removed", object->name); + BKE_reportf(reports, RPT_ERROR, "MovieTracking '%s' cannot be removed", object->name); return; } @@ -579,13 +577,16 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_float_default(prop, 0.001f); RNA_def_property_range(prop, 0, FLT_MAX); - RNA_def_property_ui_text(prop, "Success Threshold", "Threshold value of reconstruction error which is still considered successful"); + RNA_def_property_ui_text(prop, "Success Threshold", + "Threshold value of reconstruction error which is still considered successful"); /* use fallback reconstruction */ prop = RNA_def_property(srna, "use_fallback_reconstruction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "reconstruction_flag", TRACKING_USE_FALLBACK_RECONSTRUCTION); - RNA_def_property_ui_text(prop, "Use Fallback", "Use fallback reconstruction algorithm in cases main reconstruction algorithm failed. Could give better solution with bad tracks"); + RNA_def_property_ui_text(prop, "Use Fallback", + "Use fallback reconstruction algorithm in cases main reconstruction algorithm failed " + "(could give better solution with bad tracks)"); /* intrinsics refinement during bundle adjustment */ prop = RNA_def_property(srna, "refine_intrinsics", PROP_ENUM, PROP_NONE); @@ -636,7 +637,8 @@ static void rna_def_trackingSettings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_tripod_solver", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "motion_flag", TRACKING_MOTION_TRIPOD); - RNA_def_property_ui_text(prop, "Tripod Motion", "Use special solver to track a stable camera position, such as a tripod"); + RNA_def_property_ui_text(prop, "Tripod Motion", + "Use special solver to track a stable camera position, such as a tripod"); /* default_limit_frames */ prop = RNA_def_property(srna, "default_frames_limit", PROP_INT, PROP_NONE); @@ -676,7 +678,9 @@ static void rna_def_trackingSettings(BlenderRNA *brna) /* default_use_brute */ prop = RNA_def_property(srna, "use_default_mask", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_MASK); - RNA_def_property_ui_text(prop, "Use Mask", "Use a grease pencil datablock as a mask to use only specified areas of pattern when tracking"); + RNA_def_property_ui_text(prop, "Use Mask", + "Use a grease pencil datablock as a mask to use only specified areas of pattern " + "when tracking"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); /* default_use_normalization */ @@ -1013,7 +1017,9 @@ static void rna_def_trackingTrack(BlenderRNA *brna) /* use_brute */ prop = RNA_def_property(srna, "use_mask", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_MASK); - RNA_def_property_ui_text(prop, "Use Mask", "Use a grease pencil datablock as a mask to use only specified areas of pattern when tracking"); + RNA_def_property_ui_text(prop, "Use Mask", + "Use a grease pencil datablock as a mask to use only specified areas of pattern " + "when tracking"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); /* use_normalization */ @@ -1460,7 +1466,8 @@ static void rna_def_trackingDopesheet(BlenderRNA *brna) {TRACKING_DOPE_SORT_NAME, "NAME", 0, "Name", "Sort channels by their names"}, {TRACKING_DOPE_SORT_LONGEST, "LONGEST", 0, "Longest", "Sort channels by longest tracked segment"}, {TRACKING_DOPE_SORT_TOTAL, "TOTAL", 0, "Total", "Sort channels by overall amount of tracked segments"}, - {TRACKING_DOPE_SORT_AVERAGE_ERROR, "AVERAGE_ERROR", 0, "Average Error", "Sort channels by average reprojection error of tracks after solve"}, + {TRACKING_DOPE_SORT_AVERAGE_ERROR, "AVERAGE_ERROR", 0, "Average Error", + "Sort channels by average reprojection error of tracks after solve"}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 2a8f1b90d4e..548539e3395 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -390,7 +390,7 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_int(func, "active_layer", 0, 0, INT_MAX, "Active Layer", "", 0, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); - func = RNA_def_function(srna, "template_color_wheel", "uiTemplateColorWheel"); + func = RNA_def_function(srna, "template_color_picker", "uiTemplateColorPicker"); RNA_def_function_ui_description(func, "Item. A color wheel widget to pick colors"); api_ui_item_rna_common(func); RNA_def_boolean(func, "value_slider", 0, "", "Display the value slider to the right of the color wheel"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 415d5308d85..7be34c398ae 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -395,7 +395,7 @@ static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), P int a; if (devices) { - for (a = 0; devices[a].name; a++) { + for (a = 0; devices[a].identifier[0]; a++) { tmp.value = devices[a].value; tmp.identifier = devices[a].identifier; tmp.name = devices[a].name; @@ -770,6 +770,25 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) prop = RNA_def_property(srna, "icon_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Icon Alpha", "Transparency of icons in the interface, to reduce contrast"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + /* axis */ + prop = RNA_def_property(srna, "axis_x", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "xaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "X Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "axis_y", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "yaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Y Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "axis_z", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "zaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Z Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_space_generic(BlenderRNA *brna) @@ -2999,6 +3018,15 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem multi_sample_levels[] = { + {USER_MULTISAMPLE_NONE, "NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"}, + {USER_MULTISAMPLE_2, "2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_4, "4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_8, "8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_16, "16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample (requires restart)"}, + {0, NULL, 0, NULL, NULL} + }; + #if 0 /* hardcoded here, could become dynamic somehow */ /* locale according to http://www.roseindia.net/tutorials/I18N/locales-list.shtml */ @@ -3143,6 +3171,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_enum_items(prop, color_picker_types); RNA_def_property_enum_sdna(prop, NULL, "color_picker_type"); RNA_def_property_ui_text(prop, "Color Picker Type", "Different styles of displaying the color picker widget"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "use_preview_images", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS); @@ -3207,10 +3236,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) /* this isn't essential but nice to check if VBO draws any differently */ RNA_def_property_update(prop, NC_WINDOW, NULL); +#if 0 prop = RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_AA); RNA_def_property_ui_text(prop, "Anti-aliasing", "Use anti-aliasing for the 3D view (may impact redraw performance)"); +#endif prop = RNA_def_property(srna, "anisotropic_filter", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter"); @@ -3292,6 +3323,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased"); RNA_def_property_update(prop, 0, "rna_userdef_text_update"); + /* Full scene anti-aliasing */ + prop = RNA_def_property(srna, "multi_sample", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples"); + RNA_def_property_enum_items(prop, multi_sample_levels); + RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart"); + #ifdef WITH_CYCLES prop = RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE); RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); @@ -3421,10 +3458,10 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE); RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation"); /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ - + /* 3D view */ prop = RNA_def_property(srna, "ndof_view_rotate_method", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "ndof_flag"); RNA_def_property_enum_items(prop, ndof_view_rotation_items); RNA_def_property_ui_text(prop, "NDOF View Rotation", "Rotation style in the viewport"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index e5f44644f7a..f83410e7cc1 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -555,7 +555,7 @@ static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value) if (value.data == NULL) return; - /* exception: can't set screens inside of area/region handers */ + /* exception: can't set screens inside of area/region handlers */ win->newscreen = value.data; } @@ -563,8 +563,8 @@ static void rna_Window_screen_update(bContext *C, PointerRNA *ptr) { wmWindow *win = (wmWindow *)ptr->data; - /* exception: can't set screens inside of area/region handers, and must - * use context so notifier gets to the right window */ + /* exception: can't set screens inside of area/region handlers, + * and must use context so notifier gets to the right window */ if (win->newscreen) { WM_event_add_notifier(C, NC_SCREEN | ND_SCREENBROWSE, win->newscreen); win->newscreen = NULL; diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 116e07073cd..b7895cc0e2d 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -158,7 +158,7 @@ static void rna_KeyMap_item_remove(wmKeyMap *km, ReportList *reports, PointerRNA wmKeyMapItem *kmi = kmi_ptr->data; if (WM_keymap_remove_item(km, kmi) == FALSE) { - BKE_reportf(reports, RPT_ERROR, "KeyMapItem '%s' can't be removed from '%s'", kmi->idname, km->idname); + BKE_reportf(reports, RPT_ERROR, "KeyMapItem '%s' cannot be removed from '%s'", kmi->idname, km->idname); return; } @@ -195,7 +195,7 @@ static void rna_KeyConfig_remove(wmWindowManager *wm, ReportList *reports, Point wmKeyConfig *keyconf = keyconf_ptr->data; if (WM_keyconfig_remove(wm, keyconf) == FALSE) { - BKE_reportf(reports, RPT_ERROR, "KeyConfig '%s' can't be removed", keyconf->idname); + BKE_reportf(reports, RPT_ERROR, "KeyConfig '%s' cannot be removed", keyconf->idname); return; } diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner.py b/source/blender/makesrna/rna_cleanup/rna_cleaner.py index 0231e57fcfd..8b4b10c490e 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 """ This script is used to help cleaning RNA api. diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py b/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py index 75851105991..17ea5f9b0bd 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 import sys diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 3a7066ff41a..cf3bb05849a 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -94,6 +94,7 @@ set(SRC intern/MOD_weightvgedit.c intern/MOD_weightvgmix.c intern/MOD_weightvgproximity.c + intern/MOD_triangulate.c MOD_modifiertypes.h intern/MOD_boolean_util.h diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index a4817ff775d..290ba193567 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -76,6 +76,7 @@ extern ModifierTypeInfo modifierType_DynamicPaint; extern ModifierTypeInfo modifierType_Remesh; extern ModifierTypeInfo modifierType_Skin; extern ModifierTypeInfo modifierType_LaplacianSmooth; +extern ModifierTypeInfo modifierType_Triangulate; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 7219038b087..7ab3a5df531 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -58,7 +58,7 @@ static void initData(ModifierData *md) { ArmatureModifierData *amd = (ArmatureModifierData *) md; - amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP; + amd->deformflag = ARM_DEF_VGROUP; } static void copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index b9dd37ac50c..3ca2c364345 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -178,14 +178,14 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, amd->merge_dist, dupe_op, "geom"); BMO_op_exec(bm, &find_op); - + i = 0; - BMO_ITER (ele, &oiter, bm, dupe_op, "geom", BM_ALL) { + BMO_ITER (ele, &oiter, dupe_op->slots_in, "geom", BM_ALL) { BM_elem_index_set(ele, i); /* set_dirty */ i++; } - BMO_ITER (ele, &oiter, bm, dupe_op, "newout", BM_ALL) { + BMO_ITER (ele, &oiter, dupe_op->slots_out, "geom.out", BM_ALL) { BM_elem_index_set(ele, i); /* set_dirty */ i++; } @@ -197,7 +197,7 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, index_map = MEM_callocN(sizeof(int) * (*index_map_length), "index_map"); /*element type argument doesn't do anything here*/ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); index_map[BM_elem_index_get(v)] = BM_elem_index_get(v2) + 1; @@ -218,9 +218,10 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], const ArrayModifierData *amd, BMOperator *dupe_op, - const char *dupe_slot_name, + BMOpSlot dupe_op_slot_args[BMO_OP_MAX_SLOTS], const char *dupe_slot_name, BMOperator *weld_op) { + const int is_input = (dupe_op->slots_in == dupe_op_slot_args); BMVert *v, *v2, *v3; BMIter iter; @@ -234,14 +235,27 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], BMOIter oiter; BMOperator find_op; + BMOpSlot *slot_targetmap; BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "find_doubles verts=%Hv dist=%f keep_verts=%s", + is_input ? /* ugh */ + "find_doubles verts=%Hv dist=%f keep_verts=%s" : + "find_doubles verts=%Hv dist=%f keep_verts=%S", BM_ELEM_TAG, amd->merge_dist, dupe_op, dupe_slot_name); /* append the dupe's geom to the findop input verts */ - BMO_slot_buffer_append(&find_op, "verts", dupe_op, dupe_slot_name); + if (is_input) { + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_op, slots_in, dupe_slot_name); + } + else if (dupe_op->slots_out == dupe_op_slot_args) { + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_op, slots_out, dupe_slot_name); + } + else { + BLI_assert(0); + } /* transform and tag verts */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -253,15 +267,17 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], BMO_op_exec(bm, &find_op); + slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap"); + /* add new merge targets to weld operator */ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); /* check in case the target vertex (v2) is already marked * for merging */ - while ((v3 = BMO_slot_map_ptr_get(bm, weld_op, "targetmap", v2))) { + while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(bm, weld_op, "targetmap", v, v2); + BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2); } BMO_op_finish(bm, &find_op); @@ -286,6 +302,7 @@ static void merge_first_last(BMesh *bm, BMOperator find_op; BMOIter oiter; BMVert *v, *v2; + BMOpSlot *slot_targetmap; BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "find_doubles verts=%s dist=%f keep_verts=%s", @@ -293,14 +310,16 @@ static void merge_first_last(BMesh *bm, dupe_first, "geom"); /* append the last dupe's geom to the findop input verts */ - BMO_slot_buffer_append(&find_op, "verts", dupe_last, "newout"); + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_last, slots_out, "geom.out"); BMO_op_exec(bm, &find_op); /* add new merge targets to weld operator */ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap"); + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); - BMO_slot_map_ptr_insert(bm, weld_op, "targetmap", v, v2); + BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2); } BMO_op_finish(bm, &find_op); @@ -325,6 +344,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, int *indexMap = NULL; DerivedMesh *start_cap = NULL, *end_cap = NULL; MVert *src_mvert; + BMOpSlot *slot_targetmap = NULL; /* for weldop */ /* need to avoid infinite recursion here */ if (amd->start_cap && amd->start_cap != ob) @@ -408,13 +428,17 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, * cleaner way to do this. One possibility: a "mirror" BMOp would * certainly help by compressing it all into one top-level BMOp that * executes a lot of second-level BMOps. */ + BM_mesh_elem_toolflags_ensure(bm); BMO_push(bm, NULL); bmesh_edit_begin(bm, 0); - if (amd->flags & MOD_ARR_MERGE) + if (amd->flags & MOD_ARR_MERGE) { BMO_op_init(bm, &weld_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(weld_op.slots_in, "targetmap"); + } + BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "duplicate geom=%avef"); first_dupe_op = dupe_op; @@ -422,18 +446,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, for (j = 0; j < count - 1; j++) { BMVert *v, *v2, *v3; BMOpSlot *geom_slot; - BMOpSlot *newout_slot; + BMOpSlot *geom_out_slot; BMOIter oiter; if (j != 0) { BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "duplicate geom=%s", &old_dupe_op, "newout"); + "duplicate geom=%S", &old_dupe_op, "geom.out"); } BMO_op_exec(bm, &dupe_op); - geom_slot = BMO_slot_get(&dupe_op, "geom"); - newout_slot = BMO_slot_get(&dupe_op, "newout"); + geom_slot = BMO_slot_get(dupe_op.slots_in, "geom"); + geom_out_slot = BMO_slot_get(dupe_op.slots_out, "geom.out"); if ((amd->flags & MOD_ARR_MERGEFINAL) && j == 0) { int first_geom_bytes = sizeof(BMVert *) * geom_slot->len; @@ -445,7 +469,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, } /* apply transformation matrix */ - BMO_ITER (v, &oiter, bm, &dupe_op, "newout", BM_VERT) { + BMO_ITER (v, &oiter, dupe_op.slots_out, "geom.out", BM_VERT) { mul_m4_v3(offset, v->co); } @@ -464,17 +488,17 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, for (i = 0; i < index_len; i++) { if (!indexMap[i]) continue; - /* merge v (from 'newout') into v2 (from old 'geom') */ - v = _E(newout_slot, i - geom_slot->len); + /* merge v (from 'geom.out') into v2 (from old 'geom') */ + v = _E(geom_out_slot, i - geom_slot->len); v2 = _E(geom_slot, indexMap[i] - 1); /* check in case the target vertex (v2) is already marked * for merging */ - while ((v3 = BMO_slot_map_ptr_get(bm, &weld_op, "targetmap", v2))) { + while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(bm, &weld_op, "targetmap", v, v2); + BMO_slot_map_elem_insert(&weld_op, slot_targetmap, v, v2); } #undef _E @@ -510,14 +534,15 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, float startoffset[4][4]; invert_m4_m4(startoffset, offset); bm_merge_dm_transform(bm, start_cap, startoffset, amd, - &first_dupe_op, "geom", &weld_op); + &first_dupe_op, first_dupe_op.slots_in, "geom", &weld_op); } if (end_cap) { float endoffset[4][4]; mult_m4_m4m4(endoffset, offset, final_offset); bm_merge_dm_transform(bm, end_cap, endoffset, amd, - &dupe_op, count == 1 ? "geom" : "newout", &weld_op); + &dupe_op, (count == 1) ? dupe_op.slots_in : dupe_op.slots_out, + (count == 1) ? "geom" : "geom.out", &weld_op); } } /* done capping */ diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 3e3bcb73491..59befe4db05 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -92,20 +92,15 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) #ifdef USE_BM_BEVEL_OP_AS_MOD -#define EDGE_MARK 1 - /* BMESH_TODO * - * this bevel calls the operator which is missing many of the options - * which the bevel modifier in trunk has. + * this bevel calls the new bevel code (added since 2.64) + * which is missing many of the options which the bevel modifier from 2.4x has. * - no vertex bevel * - no weight bevel * * These will need to be added to the bmesh operator. - * - campbell - * - * note: this code is very close to MOD_edgesplit.c. - * note: if 0'd code from trunk included below. + * - campbell */ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), DerivedMesh *dm, @@ -116,22 +111,20 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), BMIter iter; BMEdge *e; BevelModifierData *bmd = (BevelModifierData *) md; - float threshold = cos((bmd->bevel_angle + 0.00001f) * M_PI / 180.0f); + const float threshold = cosf((bmd->bevel_angle + 0.00001f) * (float)M_PI / 180.0f); + const int segments = 16; /* XXX */ bm = DM_to_bmesh(dm); - BM_mesh_normals_update(bm, FALSE); - BMO_push(bm, NULL); - if (bmd->lim_flags & BME_BEVEL_ANGLE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* check for 1 edge having 2 face users */ - BMLoop *l1, *l2; - if ((l1 = e->l) && - (l2 = e->l->radial_next) != l1) - { - if (dot_v3v3(l1->f->no, l2->f->no) < threshold) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(e, &l_a, &l_b)) { + if (dot_v3v3(l_a->f->no, l_b->f->no) < threshold) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); } } } @@ -139,18 +132,23 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), else { /* crummy, is there a way just to operator on all? - campbell */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); + if (BM_edge_is_manifold(e)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + } } } - BMO_op_callf(bm, BMO_FLAG_DEFAULTS, - "bevel geom=%fe percent=%f use_even=%b use_dist=%b", - EDGE_MARK, bmd->value, (bmd->flags & BME_BEVEL_EVEN) != 0, (bmd->flags & BME_BEVEL_DIST) != 0); - BMO_pop(bm); + BM_mesh_bevel(bm, bmd->value, segments); result = CDDM_from_bmesh(bm, TRUE); + + BLI_assert(bm->toolflagpool == NULL); /* make sure we never alloc'd this */ BM_mesh_free(bm); + CDDM_calc_normals(result); + return result; } diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index dc29e59d549..28cdfa810fa 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -145,12 +145,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) { for (i = 0; i < vert_tot; i++) { - vweights[i] = 1.0f - defvert_find_weight(&dvert[i], defgrp_index); + const float f = 1.0f - defvert_find_weight(&dvert[i], defgrp_index); + vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX; } } else { for (i = 0; i < vert_tot; i++) { - vweights[i] = defvert_find_weight(&dvert[i], defgrp_index); + const float f = defvert_find_weight(&dvert[i], defgrp_index); + vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX; } } } @@ -186,6 +188,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* update for display only */ dmd->face_count = bm->totface; result = CDDM_from_bmesh(bm, FALSE); + BLI_assert(bm->toolflagpool == NULL); /* make sure we never alloc'd this */ BM_mesh_free(bm); #ifdef USE_TIMEIT diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 21717d07fef..ec81c5ce699 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -67,8 +67,7 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj float threshold = cosf((emd->split_angle + 0.00001f) * (float)M_PI / 180.0f); bm = DM_to_bmesh(dm); - - BMO_push(bm, NULL); + BM_mesh_elem_toolflags_ensure(bm); if (emd->flags & MOD_EDGESPLIT_FROMANGLE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { @@ -103,8 +102,6 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "split_edges edges=%fe", EDGE_MARK); - - BMO_pop(bm); /* BM_mesh_validate(bm); */ /* for troubleshooting */ diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 92ad6faa3ce..1298d281de8 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -205,7 +205,8 @@ static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFa return df; } -#define SET_VERTS(a, b, c, d) { \ +#define SET_VERTS(a, b, c, d) \ + { \ v[0] = mf->v##a; uv[0] = a - 1; \ v[1] = mf->v##b; uv[1] = b - 1; \ v[2] = mf->v##c; uv[2] = c - 1; \ diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index 47523286229..13d409dc941 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -426,7 +426,11 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams) { int displaymode = 0; - int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */ + + int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */ + /* why start with 0 as start frame?? Animations + time are frozen for frame 0 anyway. (See physics_fluid.c for that. - DG */ + /* If we start with frame 0, we need to remap all animation channels, too, because they will all be 1 frame late if using frame-1! - DG */ + char targetFile[FILE_MAX]; FluidsimSettings *fss = fluidmd->fss; DerivedMesh *dm = NULL; diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 6f6589d4d14..266226040a3 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -199,7 +199,7 @@ static void init_data(ModifierData *md) smd->lambda = 0.00001f; smd->lambda_border = 0.00005f; smd->repeat = 1; - smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION; + smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME; smd->defgrp_name[0] = '\0'; } @@ -511,7 +511,7 @@ static void validate_solution(LaplacianSystem *sys, short flag) float leni, lene; float vini, vend; float *vi1, *vi2, ve1[3], ve2[3]; - if (flag & MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION) { + if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); } for (i = 0; i < sys->numEdges; i++) { @@ -545,7 +545,7 @@ static void validate_solution(LaplacianSystem *sys, short flag) } } } - if (flag & MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION) { + if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vend = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); volume_preservation(sys, vini, vend, flag); } diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 8a4d70da6e8..a73d52a0a63 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -249,14 +249,14 @@ static int build_hull(SkinOutput *so, Frame **frames, int totframe) } /* Apply face attributes to hull output */ - BMO_ITER (f, &oiter, bm, &op, "geomout", BM_FACE) { + BMO_ITER (f, &oiter, op.slots_out, "geom.out", BM_FACE) { if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; } /* Mark interior frames */ - BMO_ITER (v, &oiter, bm, &op, "interior_geom", BM_VERT) { + BMO_ITER (v, &oiter, op.slots_out, "geom_interior.out", BM_VERT) { for (i = 0; i < totframe; i++) { Frame *frame = frames[i]; @@ -309,7 +309,7 @@ static int build_hull(SkinOutput *so, Frame **frames, int totframe) /* Check if removing triangles above will create wire triangles, * mark them too */ - BMO_ITER (e, &oiter, bm, &op, "geomout", BM_EDGE) { + BMO_ITER (e, &oiter, op.slots_out, "geom.out", BM_EDGE) { int is_wire = TRUE; BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { @@ -537,6 +537,7 @@ static int connection_node_mat(float mat[3][3], int v, const MeshElemMap *emap, /* Get axis and angle to rotate frame by */ angle = angle_normalized_v3v3(ine[0], oute[0]) / 2.0f; cross_v3_v3v3(axis, ine[0], oute[0]); + normalize_v3(axis); /* Build frame matrix (don't care about X axis here) */ copy_v3_v3(mat[0], ine[0]); @@ -644,8 +645,8 @@ typedef struct { } EdgeStackElem; static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat, - const MeshElemMap *emap, const MEdge *medge, - const MVertSkin *vs, const MVert *mvert) + const MeshElemMap *emap, const MEdge *medge, + const MVertSkin *vs, const MVert *mvert) { EdgeStackElem stack_elem; float axis[3], angle; @@ -673,7 +674,7 @@ static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat, /* If parent is a branch node, start a new edge chain */ if (parent_is_branch) { calc_edge_mat(emat[e].mat, mvert[parent_v].co, - mvert[v].co); + mvert[v].co); } else { /* Build edge matrix guided by parent matrix */ @@ -940,18 +941,18 @@ static void add_poly(SkinOutput *so, BLI_assert(v3 != v4); BLI_assert(v1 && v2 && v3); - edges[0] = BM_edge_create(so->bm, v1, v2, NULL, TRUE); - edges[1] = BM_edge_create(so->bm, v2, v3, NULL, TRUE); + edges[0] = BM_edge_create(so->bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE); + edges[1] = BM_edge_create(so->bm, v2, v3, NULL, BM_CREATE_NO_DOUBLE); if (v4) { - edges[2] = BM_edge_create(so->bm, v3, v4, NULL, TRUE); - edges[3] = BM_edge_create(so->bm, v4, v1, NULL, TRUE); + edges[2] = BM_edge_create(so->bm, v3, v4, NULL, BM_CREATE_NO_DOUBLE); + edges[3] = BM_edge_create(so->bm, v4, v1, NULL, BM_CREATE_NO_DOUBLE); } else { - edges[2] = BM_edge_create(so->bm, v3, v1, NULL, TRUE); + edges[2] = BM_edge_create(so->bm, v3, v1, NULL, BM_CREATE_NO_DOUBLE); edges[3] = NULL; } - f = BM_face_create(so->bm, verts, edges, v4 ? 4 : 3, TRUE); + f = BM_face_create(so->bm, verts, edges, v4 ? 4 : 3, BM_CREATE_NO_DOUBLE); if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; @@ -959,12 +960,12 @@ static void add_poly(SkinOutput *so, static void connect_frames(SkinOutput *so, BMVert *frame1[4], - BMVert *frame2[4]) +BMVert *frame2[4]) { BMVert *q[4][4] = {{frame2[0], frame2[1], frame1[1], frame1[0]}, - {frame2[1], frame2[2], frame1[2], frame1[1]}, - {frame2[2], frame2[3], frame1[3], frame1[2]}, - {frame2[3], frame2[0], frame1[0], frame1[3]}}; + {frame2[1], frame2[2], frame1[2], frame1[1]}, + {frame2[2], frame2[3], frame1[3], frame1[2]}, + {frame2[3], frame2[0], frame1[0], frame1[3]}}; float p[3], no[3]; int i, swap; @@ -995,7 +996,7 @@ static void output_frames(BMesh *bm, f = &sn->frames[i]; for (j = 0; j < 4; j++) { if (!f->merge[j].frame) { - BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL); + BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL, 0); if (input_dvert) { MDeformVert *dv; @@ -1079,17 +1080,20 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n, BMOperator op; BMIter iter; int i; + BMOpSlot *slot_targetmap; shortest_edge = BM_face_find_shortest_loop(f)->e; BMO_op_initf(bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); + /* Note: could probably calculate merges in one go to be * faster */ v_safe = shortest_edge->v1; v_merge = shortest_edge->v2; mid_v3_v3v3(v_safe->co, v_safe->co, v_merge->co); - BMO_slot_map_ptr_insert(bm, &op, "targetmap", v_merge, v_safe); + BMO_slot_map_elem_insert(&op, slot_targetmap, v_merge, v_safe); BMO_op_exec(bm, &op); BMO_op_finish(bm, &op); @@ -1215,6 +1219,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BMOIter oiter; BMOperator op; int i, best_order[4]; + BMOpSlot *slot_targetmap; BLI_assert(split_face->len >= 3); @@ -1228,7 +1233,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f /* Update split face (should only be one new face created * during extrusion) */ split_face = NULL; - BMO_ITER (f, &oiter, bm, &op, "faceout", BM_FACE) { + BMO_ITER (f, &oiter, op.slots_out, "faces.out", BM_FACE) { BLI_assert(!split_face); split_face = f; } @@ -1246,7 +1251,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BM_elem_flag_enable(longest_edge, BM_ELEM_TAG); BMO_op_callf(bm, BMO_FLAG_DEFAULTS, - "subdivide_edges edges=%he numcuts=%i quadcornertype=%i", + "subdivide_edges edges=%he cuts=%i quad_corner_type=%i", BM_ELEM_TAG, 1, SUBD_STRAIGHT_CUT); } else if (split_face->len > 4) { @@ -1280,9 +1285,9 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BM_face_kill(bm, split_face); BMO_op_init(bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); for (i = 0; i < 4; i++) { - BMO_slot_map_ptr_insert(bm, &op, "targetmap", - verts[i], frame->verts[best_order[i]]); + BMO_slot_map_elem_insert(&op, slot_targetmap, verts[i], frame->verts[best_order[i]]); } BMO_op_exec(bm, &op); BMO_op_finish(bm, &op); @@ -1304,7 +1309,7 @@ static void skin_hole_detach_partially_attached_frame(BMesh *bm, Frame *frame) /* Detach everything */ for (i = 0; i < totattached; i++) { BMVert **av = &frame->verts[attached[i]]; - (*av) = BM_vert_create(bm, (*av)->co, *av); + (*av) = BM_vert_create(bm, (*av)->co, *av, 0); } } @@ -1354,24 +1359,6 @@ static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2]) add_poly(so, quad[0], quad[1], quad[2], quad[3]); } -/* Returns the number of faces that are adjacent to both f1 and f2 */ -static int BM_face_share_face_count(BMFace *f1, BMFace *f2) -{ - BMIter iter1, iter2; - BMEdge *e; - BMFace *f; - int count = 0; - - BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { - if (f != f1 && f != f2 && BM_face_share_edge_count(f, f2)) - count++; - } - } - - return count; -} - static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) { BMIter iter; @@ -1434,7 +1421,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) * share a border with another face, output as a quad */ if (!BM_elem_flag_test(adj[0], BM_ELEM_TAG) && !BM_elem_flag_test(adj[1], BM_ELEM_TAG) && - !BM_face_share_face_count(adj[0], adj[1])) + !BM_face_share_face_check(adj[0], adj[1])) { add_quad_from_tris(so, e, adj); BM_elem_flag_enable(adj[0], BM_ELEM_TAG); diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index cc77d73a736..75e54d77b15 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -207,9 +207,10 @@ BLI_INLINE void madd_v3v3short_fl(float r[3], const short a[3], const float f) r[2] += (float)a[2] * f; } -static DerivedMesh *applyModifier(ModifierData *md, Object *ob, - DerivedMesh *dm, - ModifierApplyFlag UNUSED(flag)) +static DerivedMesh *applyModifier( + ModifierData *md, Object *ob, + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) { int i; DerivedMesh *result; @@ -749,6 +750,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, CDDM_calc_normals(result); } + if (numFaces == 0 && numEdges != 0) { + modifier_setError(md, "Faces needed for useful output"); + } + return result; } diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c new file mode 100644 index 00000000000..645fd5eb2cf --- /dev/null +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -0,0 +1,144 @@ +/* + * ***** 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): Antony Riakiotakis + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/modifiers/intern/MOD_triangulate.c + * \ingroup modifiers + */ + +#include "DNA_object_types.h" + +#include "BLI_utildefines.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_modifier.h" +#include "BKE_tessmesh.h" + +/* triangulation modifier, directly calls the bmesh operator */ + +static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int flag) +{ + DerivedMesh *result; + BMesh *bm; + int total_edges, i; + MEdge *me; + + bm = DM_to_bmesh(dm); + + BM_mesh_elem_toolflags_ensure(bm); + BMO_push(bm, NULL); + + BMO_op_callf(bm, BMO_FLAG_DEFAULTS, + "triangulate faces=%af use_beauty=%b", + (flag & MOD_TRIANGULATE_BEAUTY)); + BMO_pop(bm); + + result = CDDM_from_bmesh(bm, FALSE); + BM_mesh_free(bm); + + total_edges = result->getNumEdges(result); + me = CDDM_get_edges(result); + + /* force drawing of all edges (seems to be omitted in CDDM_from_bmesh) */ + for (i = 0; i < total_edges; i++, me++) + me->flag |= ME_EDGEDRAW | ME_EDGERENDER; + + CDDM_calc_normals(result); + + return result; +} + + +static void initData(ModifierData *md) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + + /* Enable in editmode by default */ + md->mode |= eModifierMode_Editmode; + tmd->flag = MOD_TRIANGULATE_BEAUTY; +} + + +static void copyData(ModifierData *md, ModifierData *target) +{ + TriangulateModifierData *smd = (TriangulateModifierData *) md; + TriangulateModifierData *tsmd = (TriangulateModifierData *) target; + + *tsmd = *smd; +} + +static DerivedMesh *applyModifierEM(ModifierData *md, + Object *UNUSED(ob), + struct BMEditMesh *UNUSED(em), + DerivedMesh *dm) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + DerivedMesh *result; + if (!(result = triangulate_dm(dm, tmd->flag))) { + return dm; + } + + return result; +} + +static DerivedMesh *applyModifier(ModifierData *md, + Object *UNUSED(ob), + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + DerivedMesh *result; + if (!(result = triangulate_dm(dm, tmd->flag))) { + return dm; + } + + return result; +} + +ModifierTypeInfo modifierType_Triangulate = { + /* name */ "Triangulate", + /* structName */ "TriangulateModifierData", + /* structSize */ sizeof(TriangulateModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_SupportsMapping | + eModifierTypeFlag_EnableInEditmode | + eModifierTypeFlag_AcceptsCVs, + + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ applyModifierEM, + /* initData */ initData, + /* requiredDataMask */ NULL, //requiredDataMask, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 3b769a30994..a27d5e5e03b 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -278,5 +278,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(Remesh); INIT_TYPE(Skin); INIT_TYPE(LaplacianSmooth); + INIT_TYPE(Triangulate); #undef INIT_TYPE } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 323a534c989..141a3680df2 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -84,6 +84,7 @@ set(SRC composite/nodes/node_composite_lummaMatte.c composite/nodes/node_composite_mapUV.c composite/nodes/node_composite_mapValue.c + composite/nodes/node_composite_mapRange.c composite/nodes/node_composite_math.c composite/nodes/node_composite_mask.c composite/nodes/node_composite_mixrgb.c @@ -122,7 +123,6 @@ set(SRC composite/nodes/node_composite_pixelate.c composite/node_composite_tree.c - composite/node_composite_util.c shader/nodes/node_shader_camera.c shader/nodes/node_shader_common.c @@ -145,36 +145,40 @@ set(SRC shader/nodes/node_shader_valToRgb.c shader/nodes/node_shader_value.c shader/nodes/node_shader_vectMath.c + shader/nodes/node_shader_add_shader.c + shader/nodes/node_shader_ambient_occlusion.c shader/nodes/node_shader_attribute.c shader/nodes/node_shader_background.c shader/nodes/node_shader_bsdf_anisotropic.c shader/nodes/node_shader_bsdf_diffuse.c - shader/nodes/node_shader_bsdf_glossy.c shader/nodes/node_shader_bsdf_glass.c + shader/nodes/node_shader_bsdf_glossy.c + shader/nodes/node_shader_bsdf_refraction.c shader/nodes/node_shader_bsdf_translucent.c shader/nodes/node_shader_bsdf_transparent.c shader/nodes/node_shader_bsdf_velvet.c shader/nodes/node_shader_bump.c shader/nodes/node_shader_emission.c shader/nodes/node_shader_fresnel.c - shader/nodes/node_shader_layer_weight.c shader/nodes/node_shader_geometry.c shader/nodes/node_shader_holdout.c - shader/nodes/node_shader_volume_transparent.c - shader/nodes/node_shader_volume_isotropic.c - shader/nodes/node_shader_light_path.c + shader/nodes/node_shader_layer_weight.c shader/nodes/node_shader_light_falloff.c - shader/nodes/node_shader_object_info.c - shader/nodes/node_shader_script.c - shader/nodes/node_shader_particle_info.c + shader/nodes/node_shader_light_path.c shader/nodes/node_shader_mix_shader.c - shader/nodes/node_shader_add_shader.c + shader/nodes/node_shader_normal_map.c + shader/nodes/node_shader_object_info.c shader/nodes/node_shader_output_lamp.c shader/nodes/node_shader_output_material.c shader/nodes/node_shader_output_world.c - shader/nodes/node_shader_tex_gradient.c + shader/nodes/node_shader_particle_info.c + shader/nodes/node_shader_script.c + shader/nodes/node_shader_tangent.c + shader/nodes/node_shader_tex_brick.c + shader/nodes/node_shader_tex_checker.c shader/nodes/node_shader_tex_coord.c shader/nodes/node_shader_tex_environment.c + shader/nodes/node_shader_tex_gradient.c shader/nodes/node_shader_tex_image.c shader/nodes/node_shader_tex_magic.c shader/nodes/node_shader_tex_musgrave.c @@ -182,8 +186,8 @@ set(SRC shader/nodes/node_shader_tex_sky.c shader/nodes/node_shader_tex_voronoi.c shader/nodes/node_shader_tex_wave.c - shader/nodes/node_shader_tex_checker.c - shader/nodes/node_shader_tex_brick.c + shader/nodes/node_shader_volume_isotropic.c + shader/nodes/node_shader_volume_transparent.c shader/node_shader_tree.c shader/node_shader_util.c @@ -218,7 +222,6 @@ set(SRC intern/node_common.c intern/node_socket.c - composite/node_composite_util.h shader/node_shader_util.h texture/node_texture_util.h @@ -231,6 +234,13 @@ set(SRC intern/node_common.h ) +if(WITH_COMPOSITOR_LEGACY) + list(APPEND SRC + composite/node_composite_util.h + composite/node_composite_util.c + ) +endif() + if(WITH_PYTHON) list(APPEND INC ../python diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index ee67ac88085..6d60ac0bb58 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -40,8 +40,6 @@ extern bNodeTreeType ntreeType_Composite; /* ****************** types array for all composite nodes ****************** */ void register_node_type_cmp_group(struct bNodeTreeType *ttype); -void register_node_type_cmp_forloop(struct bNodeTreeType *ttype); -void register_node_type_cmp_whileloop(struct bNodeTreeType *ttype); void register_node_type_cmp_rlayers(struct bNodeTreeType *ttype); void register_node_type_cmp_image(struct bNodeTreeType *ttype); @@ -72,6 +70,7 @@ void register_node_type_cmp_huecorrect(struct bNodeTreeType *ttype); void register_node_type_cmp_normal(struct bNodeTreeType *ttype); void register_node_type_cmp_curve_vec(struct bNodeTreeType *ttype); void register_node_type_cmp_map_value(struct bNodeTreeType *ttype); +void register_node_type_cmp_map_range(struct bNodeTreeType *ttype); void register_node_type_cmp_normalize(struct bNodeTreeType *ttype); void register_node_type_cmp_filter(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 66ab15ce29f..74135776c9c 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -41,8 +41,6 @@ extern struct bNodeTreeType ntreeType_Shader; /* ****************** types array for all shaders ****************** */ void register_node_type_sh_group(struct bNodeTreeType *ttype); -void register_node_type_sh_forloop(struct bNodeTreeType *ttype); -void register_node_type_sh_whileloop(struct bNodeTreeType *ttype); void register_node_type_sh_output(struct bNodeTreeType *ttype); void register_node_type_sh_material(struct bNodeTreeType *ttype); @@ -81,11 +79,15 @@ void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype); void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype); void register_node_type_sh_particle_info(struct bNodeTreeType *ttype); void register_node_type_sh_script(struct bNodeTreeType *ttype); +void register_node_type_sh_normal_map(struct bNodeTreeType *ttype); +void register_node_type_sh_tangent(struct bNodeTreeType *ttype); +void register_node_type_sh_ambient_occlusion(struct bNodeTreeType *ttype); void register_node_type_sh_background(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_glossy(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_glass(struct bNodeTreeType *ttype); +void register_node_type_sh_bsdf_refraction(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_translucent(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_transparent(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_velvet(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h index f41be2bb7d9..b14f7c4e884 100644 --- a/source/blender/nodes/NOD_socket.h +++ b/source/blender/nodes/NOD_socket.h @@ -60,6 +60,7 @@ void node_socket_set_default_value_vector(void *default_value, PropertySubType s void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a); void node_socket_set_default_value_shader(void *default_value); void node_socket_set_default_value_mesh(void *default_value); +void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value); struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp); struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp); diff --git a/source/blender/nodes/NOD_texture.h b/source/blender/nodes/NOD_texture.h index 7722580d136..a1be9963b8a 100644 --- a/source/blender/nodes/NOD_texture.h +++ b/source/blender/nodes/NOD_texture.h @@ -40,8 +40,6 @@ extern bNodeTreeType ntreeType_Texture; /* ****************** types array for all texture nodes ****************** */ void register_node_type_tex_group(struct bNodeTreeType *ttype); -void register_node_type_tex_forloop(struct bNodeTreeType *ttype); -void register_node_type_tex_whileloop(struct bNodeTreeType *ttype); void register_node_type_tex_math(struct bNodeTreeType *ttype); void register_node_type_tex_mix_rgb(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 9a7e587ff56..03462738d58 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -719,6 +719,16 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int /* *********************************************** */ +static void set_output_visible(bNode *node, int passflag, int index, int pass) +{ + bNodeSocket *sock = BLI_findlink(&node->outputs, index); + /* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */ + if (passflag & pass) + sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL); + else + sock->flag |= SOCK_UNAVAIL; +} + /* clumsy checking... should do dynamic outputs once */ static void force_hidden_passes(bNode *node, int passflag) { @@ -727,68 +737,35 @@ static void force_hidden_passes(bNode *node, int passflag) for (sock= node->outputs.first; sock; sock= sock->next) sock->flag &= ~SOCK_UNAVAIL; - if (!(passflag & SCE_PASS_COMBINED)) { - sock= BLI_findlink(&node->outputs, RRES_OUT_IMAGE); - sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_ALPHA); - sock->flag |= SOCK_UNAVAIL; - } + set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED); + set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED); - sock= BLI_findlink(&node->outputs, RRES_OUT_Z); - if (!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL); - if (!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_VEC); - if (!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_UV); - if (!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA); - if (!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF); - if (!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC); - if (!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW); - if (!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_AO); - if (!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT); - if (!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT); - if (!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_INDIRECT); - if (!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); - if (!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA); - if (!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_MIST); - if (!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT); - if (!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_ENV); - if (!(passflag & SCE_PASS_ENVIRONMENT)) sock->flag |= SOCK_UNAVAIL; - - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF_DIRECT); - if (!(passflag & SCE_PASS_DIFFUSE_DIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF_INDIRECT); - if (!(passflag & SCE_PASS_DIFFUSE_INDIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF_COLOR); - if (!(passflag & SCE_PASS_DIFFUSE_COLOR)) sock->flag |= SOCK_UNAVAIL; - - sock= BLI_findlink(&node->outputs, RRES_OUT_GLOSSY_DIRECT); - if (!(passflag & SCE_PASS_GLOSSY_DIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_GLOSSY_INDIRECT); - if (!(passflag & SCE_PASS_GLOSSY_INDIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_GLOSSY_COLOR); - if (!(passflag & SCE_PASS_GLOSSY_COLOR)) sock->flag |= SOCK_UNAVAIL; - - sock= BLI_findlink(&node->outputs, RRES_OUT_TRANSM_DIRECT); - if (!(passflag & SCE_PASS_TRANSM_DIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_TRANSM_INDIRECT); - if (!(passflag & SCE_PASS_TRANSM_INDIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_TRANSM_COLOR); - if (!(passflag & SCE_PASS_TRANSM_COLOR)) sock->flag |= SOCK_UNAVAIL; + set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z); + set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL); + set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR); + set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV); + set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA); + set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE); + set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC); + set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW); + set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO); + set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT); + set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT); + set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB); + set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA); + set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST); + set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT); + set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT); + set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT); + set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR); + set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT, SCE_PASS_TRANSM_DIRECT); + set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT, SCE_PASS_TRANSM_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR, SCE_PASS_TRANSM_COLOR); } /* based on rules, force sockets hidden always */ diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.c b/source/blender/nodes/composite/nodes/node_composite_blur.c index b9b2406631b..eb7f7763afb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_blur.c +++ b/source/blender/nodes/composite/nodes/node_composite_blur.c @@ -726,7 +726,9 @@ static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bN static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { - node->storage = MEM_callocN(sizeof(NodeBlurData), "node blur data"); + NodeBlurData *data = MEM_callocN(sizeof(NodeBlurData), "node blur data"); + data->filtertype = R_FILTER_GAUSS; + node->storage = data; } void register_node_type_cmp_blur(bNodeTreeType *ttype) diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c index e8965d50b47..44a5ac9e968 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c @@ -29,12 +29,8 @@ * \ingroup cmpnodes */ - - #include "node_composite_util.h" -#define AVG(a, b) ((a + b) / 2) - /* ******************* Color Spill Supression ********************************* */ static bNodeSocketTemplate cmp_node_color_spill_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, @@ -49,6 +45,9 @@ static bNodeSocketTemplate cmp_node_color_spill_out[] = { #ifdef WITH_COMPOSITOR_LEGACY +#define AVG(a, b) ((a + b) / 2) + + static void do_simple_spillmap_red(bNode *node, float* out, float *in) { NodeColorspill *ncs; diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c index e9d26ebebbc..df49e537788 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c @@ -49,14 +49,14 @@ static bNodeSocketTemplate cmp_node_colorbalance_out[] = { #ifdef WITH_COMPOSITOR_LEGACY /* this function implements ASC-CDL according to the spec at http://www.asctech.org/ - Slope - S = in * slope - Offset - O = S + offset - = (in * slope) + offset - Power - out = Clamp(O) ^ power - = Clamp((in * slope) + offset) ^ power + * Slope + * S = in * slope + * Offset + * O = S + offset + * = (in * slope) + offset + * Power + * out = Clamp(O) ^ power + * = Clamp((in * slope) + offset) ^ power */ DO_INLINE float colorbalance_cdl(float in, float offset, float power, float slope) { diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 150382c1f8f..88d78df190f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -173,9 +173,10 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) Image *ima= (Image *)node->id; if (ima) { ImageUser *iuser= node->storage; + ImBuf *ibuf; /* make sure ima->type is correct */ - BKE_image_get_ibuf(ima, iuser); + ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ima->rr) { RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); @@ -191,6 +192,8 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) } else cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z); + + BKE_image_release_ibuf(ima, ibuf, NULL); } else cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA); @@ -312,7 +315,7 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) } /* note: this function is used for multilayer too, to ensure uniform - * handling with BKE_image_get_ibuf() */ + * handling with BKE_image_acquire_ibuf() */ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) { ImBuf *ibuf; @@ -322,7 +325,7 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i float *rect; int alloc= FALSE; - ibuf= BKE_image_get_ibuf(ima, iuser); + ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { return NULL; } @@ -374,12 +377,15 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i } } #endif + + BKE_image_release_ibuf(ima, ibuf, NULL); + return stackbuf; } static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) { - ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage); + ImBuf *ibuf= BKE_image_acquire_ibuf((Image *)node->id, node->storage, NULL); CompBuf *zbuf= NULL; if (ibuf && ibuf->zbuf_float) { @@ -391,6 +397,9 @@ static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) zbuf->rect= ibuf->zbuf_float; } } + + BKE_image_release_ibuf((Image *)node->id, ibuf, NULL); + return zbuf; } @@ -418,13 +427,14 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE RenderData *rd= data; Image *ima= (Image *)node->id; ImageUser *iuser= (ImageUser *)node->storage; + ImBuf *ibuf = NULL; /* first set the right frame number in iuser */ BKE_image_user_frame_calc(iuser, rd->cfra, 0); /* force a load, we assume iuser index will be set OK anyway */ if (ima->type==IMA_TYPE_MULTILAYER) - BKE_image_get_ibuf(ima, iuser); + ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ima->type==IMA_TYPE_MULTILAYER && ima->rr) { RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); @@ -505,6 +515,8 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE generate_preview(data, node, stackbuf); } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c index e16b7e5d885..96e905827cb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c +++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c @@ -96,22 +96,25 @@ static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keying int j; zero_v3(site->color); - for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { - if (pattern_ibuf->rect_float) { - add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); - } - else { - unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; - site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); - site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); - site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + if (pattern_ibuf) { + for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { + if (pattern_ibuf->rect_float) { + add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); + } + else { + unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; + + site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); + site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); + site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + } } + + mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); + IMB_freeImBuf(pattern_ibuf); } - mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); - IMB_freeImBuf(pattern_ibuf); - site->co[0] = marker->pos[0] * screenbuf->x; site->co[1] = marker->pos[1] * screenbuf->y; diff --git a/source/blender/nodes/composite/nodes/node_composite_mapRange.c b/source/blender/nodes/composite/nodes/node_composite_mapRange.c new file mode 100644 index 00000000000..f96e133b19f --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_mapRange.c @@ -0,0 +1,58 @@ +/* + * ***** 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) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_mapRange.c + * \ingroup cmpnodes + */ + + +#include "node_composite_util.h" + +/* **************** MAP VALUE ******************** */ +static bNodeSocketTemplate cmp_node_map_range_in[] = { + { SOCK_FLOAT, 1, N_("Value"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("From Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("From Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("To Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("To Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { -1, 0, "" } +}; +static bNodeSocketTemplate cmp_node_map_range_out[] = { + { SOCK_FLOAT, 0, N_("Value")}, + { -1, 0, "" } +}; + +void register_node_type_cmp_map_range(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_map_range_in, cmp_node_map_range_out); + node_type_size(&ntype, 120, 60, 150); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c index bbd44c58314..5bc67adf5fb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_math.c +++ b/source/blender/nodes/composite/nodes/node_composite_math.c @@ -103,7 +103,7 @@ static void do_math(bNode *node, float *out, float *in, float *in2) out[0] = pow(in[0], in2[0]); } else { - float y_mod_1 = ABS(fmod(in2[0], 1)); + float y_mod_1 = fabsf(fmodf(in2[0], 1.0f)); /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.c b/source/blender/nodes/composite/nodes/node_composite_normal.c index 93fd7ca1c1b..d104e8f03e6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normal.c +++ b/source/blender/nodes/composite/nodes/node_composite_normal.c @@ -40,7 +40,7 @@ static bNodeSocketTemplate cmp_node_normal_in[] = { }; static bNodeSocketTemplate cmp_node_normal_out[] = { - { SOCK_VECTOR, 0, N_("Normal")}, + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index 656e2a72c03..214617c91e5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -242,7 +242,7 @@ static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack ImageFormatData *format = (sockdata->use_node_format ? &nimf->format : &sockdata->format); char path[FILE_MAX]; char filename[FILE_MAX]; - CompBuf *cbuf; + CompBuf *cbuf = NULL; ImBuf *ibuf; switch (format->planes) { diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c index 73cf039c6df..41fb0e822ed 100644 --- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c @@ -77,7 +77,7 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack * ibuf= BKE_image_acquire_ibuf(ima, node->storage, &lock); if (ibuf==NULL) { printf("node_composit_exec_viewer error\n"); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return; } @@ -128,7 +128,7 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack * composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); generate_preview(data, node, cbuf); free_compbuf(cbuf); diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c index 938f75cf3f5..1c27cc21b06 100644 --- a/source/blender/nodes/composite/nodes/node_composite_viewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c @@ -62,7 +62,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, ibuf = BKE_image_acquire_ibuf(ima, node->storage, &lock); if (ibuf == NULL) { printf("node_composit_exec_viewer error\n"); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return; } @@ -112,7 +112,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, free_compbuf(zbuf); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); generate_preview(data, node, cbuf); free_compbuf(cbuf); diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 8e49484d1eb..69256fafc3d 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -41,6 +41,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_string.h" #include "BKE_DerivedMesh.h" #include "BKE_node.h" @@ -157,6 +158,20 @@ static bNodeSocketType node_socket_type_mesh = { /* buttonfunc */ NULL, }; +/****************** STRING ******************/ + +static bNodeSocketType node_socket_type_string = { + /* type */ SOCK_STRING, + /* ui_name */ "String", + /* ui_description */ "String", + /* ui_icon */ 0, + /* ui_color */ {255, 255, 255, 255}, + + /* value_structname */ "bNodeSocketValueString", + /* value_structsize */ sizeof(bNodeSocketValueString), + + /* buttonfunc */ NULL, +}; void node_socket_type_init(bNodeSocketType *types[]) { @@ -169,6 +184,7 @@ void node_socket_type_init(bNodeSocketType *types[]) INIT_TYPE(boolean); INIT_TYPE(shader); INIT_TYPE(mesh); + INIT_TYPE(string); #undef INIT_TYPE } @@ -218,6 +234,9 @@ void node_socket_init_default_value(int type, void *default_value) case SOCK_MESH: node_socket_set_default_value_mesh(default_value); break; + case SOCK_STRING: + node_socket_set_default_value_string(default_value, PROP_NONE, (char *)""); + break; } } @@ -265,6 +284,13 @@ void node_socket_set_default_value_rgba(void *default_value, float r, float g, f val->value[3] = a; } +void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value) +{ + bNodeSocketValueString *val = default_value; + val->subtype = subtype; + BLI_strncpy(val->value, value, 1024);//FILE_MAX +} + void node_socket_set_default_value_shader(void *UNUSED(default_value)) { } @@ -282,12 +308,14 @@ void node_socket_copy_default_value(int type, void *to_default_value, void *from bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value; bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value; bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value; + bNodeSocketValueString *fromstring= (bNodeSocketValueString*)from_default_value; bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value; bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value; bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value; bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value; bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value; + bNodeSocketValueString *tostring= (bNodeSocketValueString*)to_default_value; switch (type) { case SOCK_FLOAT: @@ -305,6 +333,9 @@ void node_socket_copy_default_value(int type, void *to_default_value, void *from case SOCK_RGBA: *torgba = *fromrgba; break; + case SOCK_STRING: + *tostring = *fromstring; + break; } } @@ -442,6 +473,35 @@ void node_socket_convert_default_value(int to_type, void *to_default_value, int } } +static void node_socket_set_minmax_subtype(bNodeSocket *sock, struct bNodeSocketTemplate *stemp) +{ + switch (sock->type) { + case SOCK_FLOAT: + { + bNodeSocketValueFloat *dval= sock->default_value; + dval->min = stemp->min; + dval->max = stemp->max; + dval->subtype = stemp->subtype; + break; + } + case SOCK_INT: + { + bNodeSocketValueInt *dval= sock->default_value; + dval->min = stemp->min; + dval->max = stemp->max; + dval->subtype = stemp->subtype; + break; + } + case SOCK_VECTOR: + { + bNodeSocketValueVector *dval= sock->default_value; + dval->min = stemp->min; + dval->max = stemp->max; + dval->subtype = stemp->subtype; + break; + } + } +} struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp) { @@ -470,6 +530,9 @@ struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct case SOCK_MESH: node_socket_set_default_value_mesh(sock->default_value); break; + case SOCK_STRING: + node_socket_set_default_value_string(sock->default_value, stemp->subtype, (char *)""); + break; } return sock; @@ -478,6 +541,7 @@ struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp) { bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type); + node_socket_set_minmax_subtype(sock, stemp); return sock; } @@ -498,32 +562,7 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in /* Copy the property range and subtype parameters in case the template changed. * NOT copying the actual value here, only button behavior changes! */ - switch (sock->type) { - case SOCK_FLOAT: - { - bNodeSocketValueFloat *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; - break; - } - case SOCK_INT: - { - bNodeSocketValueInt *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; - break; - } - case SOCK_VECTOR: - { - bNodeSocketValueVector *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; - break; - } - } + node_socket_set_minmax_subtype(sock, stemp); BLI_remlink(socklist, sock); diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c new file mode 100644 index 00000000000..7dfefc9ece0 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c @@ -0,0 +1,63 @@ +/* + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_ambient_occlusion_in[] = { + { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = { + { SOCK_SHADER, 0, N_("AO")}, + { -1, 0, "" } +}; + +static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL)); +} + +/* node type definition */ +void register_node_type_sh_ambient_occlusion(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, NULL); + node_type_storage(&ntype, "", NULL, NULL); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, node_shader_gpu_ambient_occlusion); + + nodeRegisterType(ttype, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c new file mode 100644 index 00000000000..99e66e39002 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c @@ -0,0 +1,68 @@ +/* + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_bsdf_refraction_in[] = { + { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = { + { SOCK_SHADER, 0, N_("BSDF")}, + { -1, 0, "" } +}; + +static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[3].link) + in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bsdf_refraction", in, out); +} + +/* node type definition */ +void register_node_type_sh_bsdf_refraction(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, NULL); + node_type_storage(&ntype, "", NULL, NULL); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, node_shader_gpu_bsdf_refraction); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c index 24ed825c36e..b0605f9b248 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.c +++ b/source/blender/nodes/shader/nodes/node_shader_bump.c @@ -36,7 +36,7 @@ /* **************** BUMP ******************** */ static bNodeSocketTemplate sh_node_bump_in[] = { - { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, + { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, { SOCK_FLOAT, 1, "Height", 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c index bccf6d349cf..2902bf143c8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_material.c +++ b/source/blender/nodes/shader/nodes/node_shader_material.c @@ -85,7 +85,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, float col[4]; bNodeSocket *sock; char hasinput[NUM_MAT_IN] = {'\0'}; - int i; + int i, mode; /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily * the constant input stack values (e.g. in case material node is inside a group). @@ -142,10 +142,18 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, nodestack_get_vec(&shi->translucency, SOCK_FLOAT, in[MAT_IN_TRANSLUCENCY]); } + /* make alpha output give results even if transparency is only enabled on + * the material linked in this not and not on the parent material */ + mode = shi->mode; + if(shi->mat->mode & MA_TRANSP) + shi->mode |= MA_TRANSP; + shi->nodes= 1; /* temp hack to prevent trashadow recursion */ node_shader_lamp_loop(shi, &shrnode); /* clears shrnode */ shi->nodes= 0; + shi->mode = mode; + /* write to outputs */ if (node->custom1 & SH_NODE_MAT_DIFF) { copy_v3_v3(col, shrnode.combined); diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index 9dc900e6bd4..0b71a3f13b4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -142,7 +142,7 @@ bNodeStack **out) out[0]->vec[0] = pow(in[0]->vec[0], in[1]->vec[0]); } else { - float y_mod_1 = ABS(fmod(in[1]->vec[0], 1)); + float y_mod_1 = fabsf(fmodf(in[1]->vec[0], 1.0f)); /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { @@ -225,8 +225,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN case 13: case 15: case 16: - GPU_stack_link(mat, names[node->custom1], NULL, out, - GPU_socket(&in[0]), GPU_socket(&in[1])); + GPU_stack_link(mat, names[node->custom1], in, out); break; case 4: case 5: @@ -235,10 +234,20 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN case 8: case 9: case 14: - if (in[0].hasinput || !in[1].hasinput) - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); - else - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + if (in[0].hasinput || !in[1].hasinput) { + /* use only first item and terminator */ + GPUNodeStack tmp_in[2]; + memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack)); + memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); + GPU_stack_link(mat, names[node->custom1], tmp_in, out); + } + else { + /* use only second item and terminator */ + GPUNodeStack tmp_in[2]; + memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack)); + memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); + GPU_stack_link(mat, names[node->custom1], tmp_in, out); + } break; default: return 0; diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c index 98a56c85279..0ad58d6af76 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal.c @@ -34,12 +34,12 @@ /* **************** NORMAL ******************** */ static bNodeSocketTemplate sh_node_normal_in[] = { - { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, { -1, 0, "" } }; static bNodeSocketTemplate sh_node_normal_out[] = { - { SOCK_VECTOR, 0, N_("Normal")}, + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c new file mode 100644 index 00000000000..6a4eb9d81df --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.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. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_normal_map_in[] = { + { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, + { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_normal_map_out[] = { + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeShaderNormalMap *attr = MEM_callocN(sizeof(NodeShaderNormalMap), "NodeShaderNormalMap"); + node->storage = attr; +} + +static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_normal_map", in, out, GPU_builtin(GPU_VIEW_NORMAL)); +} + +/* node type definition */ +void register_node_type_sh_normal_map(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_normal_map_in, sh_node_normal_map_out); + node_type_size(&ntype, 250, 60, 250); + node_type_init(&ntype, node_shader_init_normal_map); + node_type_storage(&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, gpu_shader_normal_map); + + nodeRegisterType(ttype, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c index d4c2d188ffa..b5563658a64 100644 --- a/source/blender/nodes/shader/nodes/node_shader_script.c +++ b/source/blender/nodes/shader/nodes/node_shader_script.c @@ -64,7 +64,7 @@ static void node_copy_script(bNode *orig_node, bNode *new_node) NodeShaderScript *orig_nss = orig_node->storage; NodeShaderScript *new_nss = MEM_dupallocN(orig_nss); - if(orig_nss->bytecode) + if (orig_nss->bytecode) new_nss->bytecode = MEM_dupallocN(orig_nss->bytecode); if (orig_nss->prop) diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c new file mode 100644 index 00000000000..6c0d6d7cd9f --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c @@ -0,0 +1,60 @@ +/* + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_tangent_out[] = { + { SOCK_VECTOR, 0, N_("Tangent"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeShaderTangent *attr = MEM_callocN(sizeof(NodeShaderTangent), "NodeShaderTangent"); + attr->axis = SHD_TANGENT_AXIS_Z; + node->storage = attr; +} + +/* node type definition */ +void register_node_type_sh_tangent(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, NULL, sh_node_tangent_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, node_shader_init_tangent); + node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, NULL); + + nodeRegisterType(ttype, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index abe8e0190c8..d2d0870e2ed 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -75,12 +75,13 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod ret = GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, isdata)); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } + BKE_image_release_ibuf(ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 9b17f76bd47..49b38434246 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -75,12 +75,13 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack ret = GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } + BKE_image_release_ibuf(ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c index 6d1b3ff6dba..b77c7d07407 100644 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -128,12 +128,13 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G int ret = GPU_stack_link(mat, "texture_image", in, out, texlink); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) ==0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[1].link, &out[1].link); } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c index 2d9f1903c5b..3e00421ddf0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c +++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c @@ -114,14 +114,23 @@ static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, case 2: case 3: case 4: - GPU_stack_link(mat, names[node->custom1], NULL, out, - GPU_socket(&in[0]), GPU_socket(&in[1])); + GPU_stack_link(mat, names[node->custom1], in, out); break; case 5: - if (in[0].hasinput || !in[1].hasinput) - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); - else - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + if (in[0].hasinput || !in[1].hasinput) { + /* use only first item and terminator */ + GPUNodeStack tmp_in[2]; + memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack)); + memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); + GPU_stack_link(mat, names[node->custom1], tmp_in, out); + } + else { + /* use only second item and terminator */ + GPUNodeStack tmp_in[2]; + memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack)); + memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); + GPU_stack_link(mat, names[node->custom1], tmp_in, out); + } break; default: return 0; diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c index f3fdaf0bb64..2ef1669a266 100644 --- a/source/blender/nodes/texture/nodes/node_texture_image.c +++ b/source/blender/nodes/texture/nodes/node_texture_image.c @@ -46,7 +46,7 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i ImageUser *iuser= (ImageUser *)node->storage; if ( ima ) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if ( ibuf ) { float xsize, ysize; float xoff, yoff; @@ -77,6 +77,8 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i result = ibuf->rect_float + py*ibuf->x*4 + px*4; copy_v4_v4(out, result); + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } diff --git a/source/blender/python/bmesh/CMakeLists.txt b/source/blender/python/bmesh/CMakeLists.txt index 032a914fb70..ccabe572ce5 100644 --- a/source/blender/python/bmesh/CMakeLists.txt +++ b/source/blender/python/bmesh/CMakeLists.txt @@ -34,6 +34,7 @@ set(INC_SYS set(SRC bmesh_py_api.c bmesh_py_ops.c + bmesh_py_ops_call.c bmesh_py_types.c bmesh_py_types_customdata.c bmesh_py_types_meshdata.c @@ -42,6 +43,7 @@ set(SRC bmesh_py_api.h bmesh_py_ops.h + bmesh_py_ops_call.h bmesh_py_types.h bmesh_py_types_customdata.h bmesh_py_types_meshdata.h diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index e02efc79da0..18f5d895132 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -51,7 +51,6 @@ #include "bmesh_py_api.h" /* own include */ - PyDoc_STRVAR(bpy_bm_new_doc, ".. method:: new()\n" "\n" @@ -73,6 +72,8 @@ PyDoc_STRVAR(bpy_bm_from_edit_mesh_doc, "\n" " Return a BMesh from this mesh, currently the mesh must already be in editmode.\n" "\n" +" :arg mesh: The editmode mesh.\n" +" :type mesh: :class:`bpy.types.Mesh`\n" " :return: the BMesh associated with this mesh.\n" " :rtype: :class:`bmesh.types.BMesh`\n" ); @@ -96,22 +97,62 @@ static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value) return BPy_BMesh_CreatePyObject(bm, BPY_BMFLAG_IS_WRAPPED); } +PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc, +".. method:: update_edit_mesh(mesh, tessface=True)\n" +"\n" +" Update the mesh after changes to the BMesh in editmode, \n" +" optionally recalculating n-gon tessellation.\n" +"\n" +" :arg mesh: The editmode mesh.\n" +" :type mesh: :class:`bpy.types.Mesh`\n" +" :arg tessface: Option to recalculate n-gon tessellation.\n" +" :type tessface: boolean\n" +); +static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *py_me; + Mesh *me; + int do_tessface = TRUE; + + if (!PyArg_ParseTuple(args, "O|i:update_edit_mesh", &py_me, &do_tessface)) { + return NULL; + } + + me = PyC_RNA_AsPointer(py_me, "Mesh"); + + if (me == NULL) { + return NULL; + } + + if (me->edit_btmesh == NULL) { + PyErr_SetString(PyExc_ValueError, + "The mesh must be in editmode"); + return NULL; + } + + { + /* XXX, not great - infact this function could just not use the context at all + * postpone that change until after release: BMESH_TODO - campbell */ + extern struct bContext *BPy_GetContext(void); + extern void EDBM_update_generic(struct bContext *C, BMEditMesh *em, const short do_tessface); + + struct bContext *C = BPy_GetContext(); + EDBM_update_generic(C, me->edit_btmesh, do_tessface); + } + + Py_RETURN_NONE; +} + static struct PyMethodDef BPy_BM_methods[] = { {"new", (PyCFunction)bpy_bm_new, METH_NOARGS, bpy_bm_new_doc}, {"from_edit_mesh", (PyCFunction)bpy_bm_from_edit_mesh, METH_O, bpy_bm_from_edit_mesh_doc}, + {"update_edit_mesh", (PyCFunction)bpy_bm_update_edit_mesh, METH_VARARGS, bpy_bm_update_edit_mesh_doc}, {NULL, NULL, 0, NULL} }; PyDoc_STRVAR(BPy_BM_doc, "This module provides access to blenders bmesh data structures.\n" "\n" -"\n" -"Submodules:\n" -"\n" -"* :mod:`bmesh.utils`\n" -"* :mod:`bmesh.types`\n" -"\n" -"\n" ".. include:: include__bmesh.rst\n" ); static struct PyModuleDef BPy_BM_module_def = { diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c index fb5b94249e6..0a2091af5df 100644 --- a/source/blender/python/bmesh/bmesh_py_ops.c +++ b/source/blender/python/bmesh/bmesh_py_ops.c @@ -38,39 +38,19 @@ #include "../generic/py_capi_utils.h" -#include "../mathutils/mathutils.h" - #include "bmesh.h" +#include "bmesh_py_ops_call.h" #include "bmesh_py_ops.h" /* own include */ #include "bmesh_py_types.h" -#include "bmesh_py_utils.h" /* own include */ - -static int bpy_bm_op_as_py_error(BMesh *bm) -{ - if (BMO_error_occurred(bm)) { - const char *errmsg; - if (BMO_error_get(bm, &errmsg, NULL)) { - PyErr_Format(PyExc_RuntimeError, - "bmesh operator: %.200s", - errmsg); - return -1; - } - } - return 0; -} +#include "bmesh_py_utils.h" /* bmesh operator 'bmesh.ops.*' callable types * ******************************************* */ PyTypeObject bmesh_op_Type; -typedef struct { - PyObject_HEAD /* required python macro */ - const char *opname; -} BPy_BMeshOpFunc; - static PyObject *bpy_bmesh_op_CreatePyObject(const char *opname) { BPy_BMeshOpFunc *self = PyObject_New(BPy_BMeshOpFunc, &bmesh_op_Type); @@ -88,243 +68,6 @@ static PyObject *bpy_bmesh_op_repr(BPy_BMeshOpFunc *self) } -static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) -{ - BPy_BMesh *py_bm; - BMesh *bm; - - BMOperator bmop; - - if ((PyTuple_GET_SIZE(args) == 1) && - (py_bm = (BPy_BMesh *)PyTuple_GET_ITEM(args, 0)) && - (BPy_BMesh_Check(py_bm)) - ) - { - BPY_BM_CHECK_OBJ(py_bm); - bm = py_bm->bm; - } - else { - PyErr_SetString(PyExc_TypeError, - "calling a bmesh operator expects a single BMesh (non keyword) " - "as the first argument"); - return NULL; - } - - /* TODO - error check this!, though we do the error check on attribute access */ - /* TODO - make flags optional */ - BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, self->opname); - - if (kw && PyDict_Size(kw) > 0) { - /* setup properties, see bpy_rna.c: pyrna_py_to_prop() - * which shares this logic for parsing properties */ - - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next(kw, &pos, &key, &value)) { - const char *slot_name = _PyUnicode_AsString(key); - BMOpSlot *slot = BMO_slot_get(&bmop, slot_name); - - if (slot == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" is invalid for this operator", - self->opname, slot_name); - return NULL; - } - - /* now assign the value */ - switch (slot->slot_type) { - case BMO_OP_SLOT_BOOL: - { - int param; - - param = PyLong_AsLong(value); - - if (param < 0) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected True/False or 0/1, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else { - slot->data.i = param; - } - - break; - } - case BMO_OP_SLOT_INT: - { - int overflow; - long param = PyLong_AsLongAndOverflow(value, &overflow); - if (overflow || (param > INT_MAX) || (param < INT_MIN)) { - PyErr_Format(PyExc_ValueError, - "%.200s: keyword \"%.200s\" value not in 'int' range " - "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else if (param == -1 && PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected an int, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else { - slot->data.i = (int)param; - } - break; - } - case BMO_OP_SLOT_FLT: - { - float param = PyFloat_AsDouble(value); - if (param == -1 && PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected a float, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else { - slot->data.f = param; - } - break; - } - case BMO_OP_SLOT_MAT: - { - /* XXX - BMesh operator design is crappy here, operator slot should define matrix size, - * not the caller! */ - unsigned short size; - if (!MatrixObject_Check(value)) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected a Matrix, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else if (BaseMath_ReadCallback((MatrixObject *)value) == -1) { - return NULL; - } - else if (((size = ((MatrixObject *)value)->num_col) != ((MatrixObject *)value)->num_row) || - (ELEM(size, 3, 4) == FALSE)) - { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix Matrix", - self->opname, slot_name); - return NULL; - } - - BMO_slot_mat_set(&bmop, slot_name, ((MatrixObject *)value)->matrix, size); - break; - } - case BMO_OP_SLOT_VEC: - { - /* passing slot name here is a bit non-descriptive */ - if (mathutils_array_parse(slot->data.vec, 3, 3, value, slot_name) == -1) { - return NULL; - } - break; - } - case BMO_OP_SLOT_ELEMENT_BUF: - { - /* there are many ways we could interpret arguments, for now... - * - verts/edges/faces from the mesh direct, - * this way the operator takes every item. - * - `TODO` a plain python sequence (list) of elements. - * - `TODO` an iterator. eg. - * face.verts - * - `TODO` (type, flag) pair, eg. - * ('VERT', {'TAG'}) - */ - -#define BPY_BM_GENERIC_MESH_TEST(type_string) \ - if (((BPy_BMGeneric *)value)->bm != bm) { \ - PyErr_Format(PyExc_NotImplementedError, \ - "%.200s: keyword \"%.200s\" " type_string " are from another bmesh", \ - self->opname, slot_name, slot->slot_type); \ - return NULL; \ - } (void)0 - - if (BPy_BMVertSeq_Check(value)) { - BPY_BM_GENERIC_MESH_TEST("verts"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_VERT); - } - else if (BPy_BMEdgeSeq_Check(value)) { - BPY_BM_GENERIC_MESH_TEST("edges"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_EDGE); - } - else if (BPy_BMFaceSeq_Check(value)) { - BPY_BM_GENERIC_MESH_TEST("faces"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_FACE); - } - else if (BPy_BMElemSeq_Check(value)) { - BMIter iter; - BMHeader *ele; - int tot; - unsigned int i; - - BPY_BM_GENERIC_MESH_TEST("elements"); - - /* this will loop over all elements which is a shame but - * we need to know this before alloc */ - /* calls bpy_bmelemseq_length() */ - tot = Py_TYPE(value)->tp_as_sequence->sq_length((PyObject *)self); - - BMO_slot_buffer_alloc(&bmop, slot_name, tot); - - i = 0; - BM_ITER_BPY_BM_SEQ (ele, &iter, ((BPy_BMElemSeq *)value)) { - ((void **)slot->data.buf)[i] = (void *)ele; - i++; - } - } - /* keep this last */ - else if (PySequence_Check(value)) { - BMElem **elem_array = NULL; - Py_ssize_t elem_array_len; - - elem_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX, - &elem_array_len, BM_VERT | BM_EDGE | BM_FACE, - TRUE, TRUE, slot_name); - - /* error is set above */ - if (elem_array == NULL) { - return NULL; - } - - BMO_slot_buffer_alloc(&bmop, slot_name, elem_array_len); - memcpy(slot->data.buf, elem_array, sizeof(void *) * elem_array_len); - PyMem_FREE(elem_array); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected " - "a bmesh sequence, list, (htype, flag) pair, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - -#undef BPY_BM_GENERIC_MESH_TEST - - break; - } - default: - /* TODO --- many others */ - PyErr_Format(PyExc_NotImplementedError, - "%.200s: keyword \"%.200s\" type %d not working yet!", - self->opname, slot_name, slot->slot_type); - return NULL; - break; - } - } - } - - BMO_op_exec(bm, &bmop); - BMO_op_finish(bm, &bmop); - - if (bpy_bm_op_as_py_error(bm) == -1) { - return NULL; - } - - Py_RETURN_NONE; -} - PyTypeObject bmesh_op_Type = { PyVarObject_HEAD_INIT(NULL, 0) @@ -348,7 +91,7 @@ PyTypeObject bmesh_op_Type = { /* More standard operations (here for binary compatibility) */ NULL, /* hashfunc tp_hash; */ - (ternaryfunc)pyrna_op_call, /* ternaryfunc tp_call; */ + (ternaryfunc)BPy_BMO_call, /* ternaryfunc tp_call; */ NULL, /* reprfunc tp_str; */ /* will only use these if this is a subtype of a py class */ @@ -409,41 +152,41 @@ PyTypeObject bmesh_op_Type = { /* bmesh fake module 'bmesh.ops' * ***************************** */ -static PyObject *bpy_bmesh_fmod_getattro(PyObject *UNUSED(self), PyObject *pyname) +static PyObject *bpy_bmesh_ops_fakemod_getattro(PyObject *UNUSED(self), PyObject *pyname) { - const unsigned int tot = bmesh_total_ops; + const unsigned int tot = bmo_opdefines_total; unsigned int i; - const char *name = _PyUnicode_AsString(pyname); + const char *opname = _PyUnicode_AsString(pyname); for (i = 0; i < tot; i++) { - if (strcmp(opdefines[i]->name, name) == 0) { - return bpy_bmesh_op_CreatePyObject(opdefines[i]->name); + if (strcmp(bmo_opdefines[i]->opname, opname) == 0) { + return bpy_bmesh_op_CreatePyObject(opname); } } PyErr_Format(PyExc_AttributeError, "BMeshOpsModule: operator \"%.200s\" doesn't exist", - name); + opname); return NULL; } -static PyObject *bpy_bmesh_fmod_dir(PyObject *UNUSED(self)) +static PyObject *bpy_bmesh_ops_fakemod_dir(PyObject *UNUSED(self)) { - const unsigned int tot = bmesh_total_ops; + const unsigned int tot = bmo_opdefines_total; unsigned int i; PyObject *ret; - ret = PyList_New(bmesh_total_ops); + ret = PyList_New(bmo_opdefines_total); for (i = 0; i < tot; i++) { - PyList_SET_ITEM(ret, i, PyUnicode_FromString(opdefines[i]->name)); + PyList_SET_ITEM(ret, i, PyUnicode_FromString(bmo_opdefines[i]->opname)); } return ret; } -static struct PyMethodDef bpy_bmesh_fmod_methods[] = { - {"__dir__", (PyCFunction)bpy_bmesh_fmod_dir, METH_NOARGS, NULL}, +static struct PyMethodDef bpy_bmesh_ops_fakemod_methods[] = { + {"__dir__", (PyCFunction)bpy_bmesh_ops_fakemod_dir, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -473,7 +216,7 @@ static PyTypeObject bmesh_ops_fakemod_Type = { NULL, /* reprfunc tp_str; */ /* will only use these if this is a subtype of a py class */ - bpy_bmesh_fmod_getattro, /* getattrofunc tp_getattro; */ + bpy_bmesh_ops_fakemod_getattro, /* getattrofunc tp_getattro; */ NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ @@ -502,7 +245,7 @@ static PyTypeObject bmesh_ops_fakemod_Type = { NULL, /* iternextfunc tp_iternext; */ /*** Attribute descriptor and subclassing stuff ***/ - bpy_bmesh_fmod_methods, /* struct PyMethodDef *tp_methods; */ + bpy_bmesh_ops_fakemod_methods, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ NULL, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c new file mode 100644 index 00000000000..ded35363287 --- /dev/null +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -0,0 +1,783 @@ +/* + * ***** 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) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/bmesh/bmesh_py_ops_call.c + * \ingroup pybmesh + * + * This file provides __call__ aka BPy_BMO_call for + * the bmesh operatorand has been given its own file + * because argument conversion is involved. + */ + +#include + +#include "BLI_utildefines.h" + +#include "../mathutils/mathutils.h" + +#include "bmesh.h" + +#include "bmesh_py_ops.h" +#include "bmesh_py_ops_call.h" /* own include */ + +#include "bmesh_py_types.h" +#include "bmesh_py_utils.h" + +static int bpy_bm_op_as_py_error(BMesh *bm) +{ + if (BMO_error_occurred(bm)) { + const char *errmsg; + if (BMO_error_get(bm, &errmsg, NULL)) { + PyErr_Format(PyExc_RuntimeError, + "bmesh operator: %.200s", + errmsg); + return -1; + } + } + return 0; +} + +/** + * \brief Utility function to check BMVert/BMEdge/BMFace's + * + * \param value + * \param bm Check the \a value against this. + * \param htype Test \a value matches this type. + * \param descr Description text. + */ +static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char htype, + /* for error messages */ + const char *opname, const char *slot_name, const char *descr) +{ + if (!BPy_BMElem_Check(value) || + !(value->ele->head.htype & htype)) + { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s, expected a %.200s not *.200s", + opname, slot_name, descr, + BPy_BMElem_StringFromHType(htype), + Py_TYPE(value)->tp_name); + return -1; + } + else if (value->bm == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s invalidated element", + opname, slot_name, descr); + return -1; + } + else if (value->bm != bm) { /* we may want to make this check optional by setting 'bm' to NULL */ + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s invalidated element", + opname, slot_name, descr); + return -1; + } + return 0; +} + +/** + * \brief Utility function to check BMVertSeq/BMEdgeSeq/BMFaceSeq's + * + * \param value Caller must check its a BMeshSeq + * \param bm Check the \a value against this. + * \param htype_py The type(s) of \a value. + * \param htype_bmo The type(s) supported by the target slot. + * \param descr Description text. + */ +static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm, + const char htype_py, const char htype_bmo, + /* for error messages */ + const char *opname, const char *slot_name, const char *descr) +{ + if (value->bm == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s, invalidated sequence", + opname, slot_name, descr); + return -1; + } + else if (value->bm != bm) { /* we may want to make this check optional by setting 'bm' to NULL */ + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s, invalidated sequence", + opname, slot_name, descr); + return -1; + } + else if ((htype_py & htype_bmo) == 0) { + char str_bmo[32]; + char str_py[32]; + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s, expected " + "a sequence of %.200s not %.200s", + opname, slot_name, descr, + BPy_BMElem_StringFromHType_ex(htype_bmo, str_bmo), + BPy_BMElem_StringFromHType_ex(htype_py, str_py)); + return -1; + } + + return 0; +} + +/** + * Use for giving py args to an operator. + */ +static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value, + /* the are just for exception messages */ + const char *opname, const char *slot_name) +{ + switch (slot->slot_type) { + case BMO_OP_SLOT_BOOL: + { + int param; + + param = PyLong_AsLong(value); + + if (param < 0) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected True/False or 0/1, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else { + BMO_SLOT_AS_BOOL(slot) = param; + } + + break; + } + case BMO_OP_SLOT_INT: + { + int overflow; + long param = PyLong_AsLongAndOverflow(value, &overflow); + if (overflow || (param > INT_MAX) || (param < INT_MIN)) { + PyErr_Format(PyExc_ValueError, + "%.200s: keyword \"%.200s\" value not in 'int' range " + "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else if (param == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected an int, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else { + BMO_SLOT_AS_INT(slot) = (int)param; + } + break; + } + case BMO_OP_SLOT_FLT: + { + float param = PyFloat_AsDouble(value); + if (param == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected a float, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else { + BMO_SLOT_AS_FLOAT(slot) = param; + } + break; + } + case BMO_OP_SLOT_MAT: + { + /* XXX - BMesh operator design is crappy here, operator slot should define matrix size, + * not the caller! */ + unsigned short size; + if (!MatrixObject_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected a Matrix, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else if (BaseMath_ReadCallback((MatrixObject *)value) == -1) { + return -1; + } + else if (((size = ((MatrixObject *)value)->num_col) != ((MatrixObject *)value)->num_row) || + (ELEM(size, 3, 4) == FALSE)) + { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix Matrix", + opname, slot_name); + return -1; + } + + BMO_slot_mat_set(bmop, bmop->slots_in, slot_name, ((MatrixObject *)value)->matrix, size); + break; + } + case BMO_OP_SLOT_VEC: + { + /* passing slot name here is a bit non-descriptive */ + if (mathutils_array_parse(BMO_SLOT_AS_VECTOR(slot), 3, 3, value, slot_name) == -1) { + return -1; + } + break; + } + case BMO_OP_SLOT_ELEMENT_BUF: + { + if (slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) { + if (bpy_slot_from_py_elem_check((BPy_BMElem *)value, bm, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "single element") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_buffer_from_single(bmop, slot, &((BPy_BMElem *)value)->ele->head); + } + else { + /* there are many ways we could interpret arguments, for now... + * - verts/edges/faces from the mesh direct, + * this way the operator takes every item. + * - `TODO` a plain python sequence (list) of elements. + * - `TODO` an iterator. eg. + * face.verts + * - `TODO` (type, flag) pair, eg. + * ('VERT', {'TAG'}) + */ + + if (BPy_BMVertSeq_Check(value)) { + if (bpy_slot_from_py_elemseq_check((BPy_BMGeneric *)value, bm, + BM_VERT, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "element buffer") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_buffer_from_all(bm, bmop, bmop->slots_in, slot_name, BM_VERT); + } + else if (BPy_BMEdgeSeq_Check(value)) { + if (bpy_slot_from_py_elemseq_check((BPy_BMGeneric *)value, bm, + BM_EDGE, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "element buffer") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_buffer_from_all(bm, bmop, bmop->slots_in, slot_name, BM_EDGE); + } + else if (BPy_BMFaceSeq_Check(value)) { + if (bpy_slot_from_py_elemseq_check((BPy_BMGeneric *)value, bm, + BM_FACE, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "element buffer") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + BMO_slot_buffer_from_all(bm, bmop, bmop->slots_in, slot_name, BM_FACE); + } + + else if (BPy_BMElemSeq_Check(value)) { + BMIter iter; + BMHeader *ele; + int tot; + unsigned int i; + + if (bpy_slot_from_py_elemseq_check((BPy_BMGeneric *)value, bm, + bm_iter_itype_htype_map[((BPy_BMElemSeq *)value)->itype], + (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "element buffer") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + /* this will loop over all elements which is a shame but + * we need to know this before alloc */ + /* calls bpy_bmelemseq_length() */ + tot = Py_TYPE(value)->tp_as_sequence->sq_length(value); + + BMO_slot_buffer_alloc(bmop, bmop->slots_in, slot_name, tot); + + i = 0; + BM_ITER_BPY_BM_SEQ (ele, &iter, ((BPy_BMElemSeq *)value)) { + slot->data.buf[i] = ele; + i++; + } + } + /* keep this last */ + else if (PySequence_Check(value)) { + BMElem **elem_array = NULL; + Py_ssize_t elem_array_len; + + elem_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX, + &elem_array_len, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + TRUE, TRUE, slot_name); + + /* error is set above */ + if (elem_array == NULL) { + return -1; + } + + BMO_slot_buffer_alloc(bmop, bmop->slots_in, slot_name, elem_array_len); + memcpy(slot->data.buf, elem_array, sizeof(void *) * elem_array_len); + PyMem_FREE(elem_array); + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a bmesh sequence, list, (htype, flag) pair, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + } + break; + } + case BMO_OP_SLOT_MAPPING: + { + /* first check types */ + if (slot->slot_subtype.map != BMO_OP_SLOT_SUBTYPE_MAP_EMPTY) { + if (!PyDict_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + } + else { + if (!PySet_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a set, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + } + + switch (slot->slot_subtype.map) { + case BMO_OP_SLOT_SUBTYPE_MAP_ELEM: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_value, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid value in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_map_elem_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele, ((BPy_BMElem *)arg_value)->ele); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_FLT: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + float value_f; + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + value_f = PyFloat_AsDouble(arg_value); + + if (value_f == -1.0f && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with float values, not %.200s", + opname, slot_name, Py_TYPE(arg_value)->tp_name); + return -1; + } + + BMO_slot_map_float_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_f); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INT: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + int value_i; + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + value_i = PyLong_AsLong(arg_value); + + if (value_i == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with int values, not %.200s", + opname, slot_name, Py_TYPE(arg_value)->tp_name); + return -1; + } + + BMO_slot_map_int_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_i); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_BOOL: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + int value_i; + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + value_i = PyLong_AsLong(arg_value); + + if (value_i == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with bool values, not %.200s", + opname, slot_name, Py_TYPE(arg_value)->tp_name); + return -1; + } + + BMO_slot_map_bool_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_i != 0); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: + { + if (PySet_Size(value) > 0) { + PyObject *arg_key; + Py_ssize_t arg_pos = 0; + Py_ssize_t arg_hash = 0; + while (_PySet_NextEntry(value, &arg_pos, &arg_key, &arg_hash)) { + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in set") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_map_empty_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL: + { + /* can't convert from these */ + PyErr_Format(PyExc_NotImplementedError, + "This arguments mapping subtype %d is not supported", slot->slot_subtype); + return -1; + } + } + } + default: + /* TODO --- many others */ + PyErr_Format(PyExc_NotImplementedError, + "%.200s: keyword \"%.200s\" type %d not working yet!", + opname, slot_name, slot->slot_type); + return -1; + } + + /* all is well */ + return 0; +} + +/** + * Use for getting return values from an operator thats already executed. + * + * \note Don't throw any exceptions and should always return a valid (PyObject *). + */ +static PyObject* bpy_slot_to_py(BMesh *bm, BMOpSlot *slot) +{ + PyObject *item = NULL; + + /* keep switch in same order as above */ + switch (slot->slot_type) { + case BMO_OP_SLOT_BOOL: + item = PyBool_FromLong((BMO_SLOT_AS_BOOL(slot))); + break; + case BMO_OP_SLOT_INT: + item = PyLong_FromLong(BMO_SLOT_AS_INT(slot)); + break; + case BMO_OP_SLOT_FLT: + item = PyFloat_FromDouble((double)BMO_SLOT_AS_FLOAT(slot)); + break; + case BMO_OP_SLOT_MAT: + item = Matrix_CreatePyObject((float *)BMO_SLOT_AS_MATRIX(slot), 4, 4, Py_NEW, NULL); + break; + case BMO_OP_SLOT_VEC: + item = Vector_CreatePyObject(BMO_SLOT_AS_VECTOR(slot), slot->len, Py_NEW, NULL); + break; + case BMO_OP_SLOT_PTR: + BLI_assert(0); /* currently we don't have any pointer return values in use */ + item = (Py_INCREF(Py_None), Py_None); + break; + case BMO_OP_SLOT_ELEMENT_BUF: + { + if (slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) { + BMHeader *ele = BMO_slot_buffer_get_single(slot); + item = ele ? BPy_BMElem_CreatePyObject(bm, ele) : (Py_INCREF(Py_None), Py_None); + } + else { + const int size = slot->len; + void **buffer = BMO_SLOT_AS_BUFFER(slot); + int j; + + item = PyList_New(size); + for (j = 0; j < size; j++) { + BMHeader *ele = buffer[j]; + PyList_SET_ITEM(item, j, BPy_BMElem_CreatePyObject(bm, ele)); + } + } + break; + } + case BMO_OP_SLOT_MAPPING: + { + GHash *slot_hash = BMO_SLOT_AS_GHASH(slot); + GHashIterator hash_iter; + + switch (slot->slot_subtype.map) { + case BMO_OP_SLOT_SUBTYPE_MAP_ELEM: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = BPy_BMElem_CreatePyObject(bm, *(void **)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(item, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_FLT: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyFloat_FromDouble(*(float *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(item, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INT: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyLong_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(item, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_BOOL: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyBool_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(item, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: + { + item = PySet_New(NULL); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + + PySet_Add(item, py_key); + + Py_DECREF(py_key); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL: + /* can't convert from these */ + item = (Py_INCREF(Py_None), Py_None); + break; + } + break; + } + } + BLI_assert(item != NULL); + + return item; +} + +/** + * This is the __call__ for bmesh.ops.xxx() + */ +PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) +{ + PyObject *ret; + BPy_BMesh *py_bm; + BMesh *bm; + + BMOperator bmop; + + if ((PyTuple_GET_SIZE(args) == 1) && + (py_bm = (BPy_BMesh *)PyTuple_GET_ITEM(args, 0)) && + (BPy_BMesh_Check(py_bm)) + ) + { + BPY_BM_CHECK_OBJ(py_bm); + bm = py_bm->bm; + } + else { + PyErr_SetString(PyExc_TypeError, + "calling a bmesh operator expects a single BMesh (non keyword) " + "as the first argument"); + return NULL; + } + + /* TODO - error check this!, though we do the error check on attribute access */ + /* TODO - make flags optional */ + BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, self->opname); + + if (kw && PyDict_Size(kw) > 0) { + /* setup properties, see bpy_rna.c: pyrna_py_to_prop() + * which shares this logic for parsing properties */ + + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(kw, &pos, &key, &value)) { + const char *slot_name = _PyUnicode_AsString(key); + BMOpSlot *slot; + + if (!BMO_slot_exists(bmop.slots_in, slot_name)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" is invalid for this operator", + self->opname, slot_name); + BMO_op_finish(bm, &bmop); + return NULL; + } + + slot = BMO_slot_get(bmop.slots_in, slot_name); + + /* now assign the value */ + if (bpy_slot_from_py(bm, &bmop, slot, value, + self->opname, slot_name) == -1) + { + BMO_op_finish(bm, &bmop); + return NULL; + } + } + } + + BMO_op_exec(bm, &bmop); + + /* from here until the end of the function, no returns, just set 'ret' */ + if (UNLIKELY(bpy_bm_op_as_py_error(bm) == -1)) { + ret = NULL; /* exception raised above */ + } + else if (bmop.slots_out[0].slot_name == NULL) { + ret = (Py_INCREF(Py_None), Py_None); + } + else { + /* build return value */ + int i; + ret = PyDict_New(); + + for (i = 0; bmop.slots_out[i].slot_name; i++) { + // BMOpDefine *op_def = opdefines[bmop.type]; + // BMOSlotType *slot_type = op_def->slot_types_out[i]; + BMOpSlot *slot = &bmop.slots_out[i]; + PyObject *item; + + /* this function doesn't throw exceptions */ + item = bpy_slot_to_py(bm, slot); + if (item == NULL) { + item = (Py_INCREF(Py_None), Py_None); + } + +#if 1 + /* temp code, strip off '.out' while we keep this convention */ + { + char slot_name_strip[MAX_SLOTNAME]; + char *ch = strchr(slot->slot_name, '.'); /* can't fail! */ + int tot = ch - slot->slot_name; + BLI_assert(ch != NULL); + memcpy(slot_name_strip, slot->slot_name, tot); + slot_name_strip[tot] = '\0'; + PyDict_SetItemString(ret, slot_name_strip, item); + } +#else + PyDict_SetItemString(ret, slot->slot_name, item); +#endif + Py_DECREF(item); + } + } + + BMO_op_finish(bm, &bmop); + return ret; +} diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.h b/source/blender/python/bmesh/bmesh_py_ops_call.h new file mode 100644 index 00000000000..d350aec8f7f --- /dev/null +++ b/source/blender/python/bmesh/bmesh_py_ops_call.h @@ -0,0 +1,41 @@ +/* + * ***** 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) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/bmesh/bmesh_py_ops_call.h + * \ingroup pybmesh + */ + +#ifndef __BMESH_PY_OPS_CALL_H__ +#define __BMESH_PY_OPS_CALL_H__ + +typedef struct { + PyObject_HEAD /* required python macro */ + const char *opname; +} BPy_BMeshOpFunc; + + +PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw); + +#endif /* __BMESH_PY_OPS_CALL_H__ */ diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 2cae10101d1..5db9962e690 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -541,12 +541,30 @@ static PyObject *bpy_bmloop_link_loop_prev_get(BPy_BMLoop *self) return BPy_BMLoop_CreatePyObject(self->bm, self->l->prev); } +PyDoc_STRVAR(bpy_bmloop_link_loop_radial_next_doc, +"The next loop around the edge (read-only).\n\n:type: :class:`BMLoop`" +); +static PyObject *bpy_bmloop_link_loop_radial_next_get(BPy_BMLoop *self) +{ + BPY_BM_CHECK_OBJ(self); + return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_next); +} + +PyDoc_STRVAR(bpy_bmloop_link_loop_radial_prev_doc, +"The previous loop around the edge (read-only).\n\n:type: :class:`BMLoop`" +); +static PyObject *bpy_bmloop_link_loop_radial_prev_get(BPy_BMLoop *self) +{ + BPY_BM_CHECK_OBJ(self); + return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_prev); +} + /* ElemSeq * ^^^^^^^ */ /* note: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly */ PyDoc_STRVAR(bpy_bmelemseq_layers_doc, -"blah blah (read-only).\n\n:type: :class:`BMLayerAccess`" +"custom-data layers (read-only).\n\n:type: :class:`BMLayerAccess`" ); static PyObject *bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype) { @@ -555,6 +573,46 @@ static PyObject *bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype) return BPy_BMLayerAccess_CreatePyObject(self->bm, GET_INT_FROM_POINTER(htype)); } +/* FaceSeq + * ^^^^^^^ */ + +PyDoc_STRVAR(bpy_bmfaceseq_active_doc, +"active face.\n\n:type: :class:`BMFace` or None" +); +static PyObject *bpy_bmfaceseq_active_get(BPy_BMElemSeq *self, void *UNUSED(closure)) +{ + BMesh *bm = self->bm; + BPY_BM_CHECK_OBJ(self); + + if (bm->act_face) { + return BPy_BMElem_CreatePyObject(bm, (BMHeader *)bm->act_face); + } + else { + Py_RETURN_NONE; + } +} + +static int bpy_bmfaceseq_active_set(BPy_BMElem *self, PyObject *value, void *UNUSED(closure)) +{ + BMesh *bm = self->bm; + if (value == Py_None) { + bm->act_face = NULL; + return 0; + } + else if (BPy_BMFace_Check(value)) { + BPY_BM_CHECK_SOURCE_INT(value, bm, "faces.active = f"); + + bm->act_face = ((BPy_BMFace *)value)->f; + return 0; + } + else { + PyErr_Format(PyExc_TypeError, + "faces.active = f: expected BMFace or None, not %.200s", + Py_TYPE(value)->tp_name); + return -1; + } +} + static PyGetSetDef bpy_bmesh_getseters[] = { {(char *)"verts", (getter)bpy_bmvertseq_get, (setter)NULL, (char *)bpy_bmvertseq_doc, NULL}, {(char *)"edges", (getter)bpy_bmedgeseq_get, (setter)NULL, (char *)bpy_bmedgeseq_doc, NULL}, @@ -659,6 +717,8 @@ static PyGetSetDef bpy_bmloop_getseters[] = { {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmloops_link_loops_doc, (void *)BM_LOOPS_OF_LOOP}, {(char *)"link_loop_next", (getter)bpy_bmloop_link_loop_next_get, (setter)NULL, (char *)bpy_bmloop_link_loop_next_doc, NULL}, {(char *)"link_loop_prev", (getter)bpy_bmloop_link_loop_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_prev_doc, NULL}, + {(char *)"link_loop_radial_next", (getter)bpy_bmloop_link_loop_radial_next_get, (setter)NULL, (char *)bpy_bmloop_link_loop_radial_next_doc, NULL}, + {(char *)"link_loop_radial_prev", (getter)bpy_bmloop_link_loop_radial_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_radial_prev_doc, NULL}, /* readonly checks */ {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL}, @@ -668,7 +728,7 @@ static PyGetSetDef bpy_bmloop_getseters[] = { static PyGetSetDef bpy_bmvertseq_getseters[] = { {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_VERT}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyGetSetDef bpy_bmedgeseq_getseters[] = { {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_EDGE}, @@ -676,6 +736,8 @@ static PyGetSetDef bpy_bmedgeseq_getseters[] = { }; static PyGetSetDef bpy_bmfaceseq_getseters[] = { {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_FACE}, + /* face only */ + {(char *)"active", (getter)bpy_bmfaceseq_active_get, (setter)bpy_bmfaceseq_active_set, (char *)bpy_bmfaceseq_active_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyGetSetDef bpy_bmloopseq_getseters[] = { @@ -801,34 +863,92 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args) Py_RETURN_NONE; } -/* note: rna_Object_to_mesh() also has apply_modifiers arg that works the same way */ PyDoc_STRVAR(bpy_bmesh_from_object_doc, -".. method:: from_object(mesh, apply_modifiers=True)\n" +".. method:: from_object(object, scene, deform=True, render=False, cage=False)\n" "\n" -" Initialize this bmesh from existing object datablock.\n" +" Initialize this bmesh from existing object datablock (currently only meshes are supported).\n" "\n" " :arg object: The object data to load.\n" " :type object: :class:`Object`\n" -" :arg apply_modifiers: Use the final display mesh rather then the deformed cage.\n" -" :type apply_modifiers: boolean\n" +" :arg deform: Apply deformation modifiers.\n" +" :type deform: boolean\n" +" :arg render: Use render settings.\n" +" :type render: boolean\n" +" :arg cage: Get the mesh as a deformed cage.\n" +" :type cage: boolean\n" ); static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args) { PyObject *py_object; + PyObject *py_scene; Object *ob; + struct Scene *scene; BMesh *bm; - int apply_modifiers = TRUE; + int use_deform = TRUE; + int use_render = FALSE; + int use_cage = FALSE; DerivedMesh *dm; + const int mask = CD_MASK_BMESH; BPY_BM_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "O|i:from_object", &py_object, &apply_modifiers) || - !(ob = PyC_RNA_AsPointer(py_object, "Object"))) + if (!PyArg_ParseTuple(args, "OO|iii:from_object", &py_object, &py_scene, &use_render, &use_cage) || + !(ob = PyC_RNA_AsPointer(py_object, "Object")) || + !(scene = PyC_RNA_AsPointer(py_scene, "Scene"))) { return NULL; } - dm = apply_modifiers ? ob->derivedFinal : ob->derivedDeform; + if (ob->type != OB_MESH) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): currently only mesh objects are supported"); + return NULL; + } + + /* Write the display mesh into the dummy mesh */ + if (use_deform) { + if (use_render) { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (render=True)"); + return NULL; + } + else { + dm = mesh_create_derived_render(scene, ob, mask); + } + } + else { + if (use_cage) { + dm = mesh_get_derived_deform(scene, ob, mask); /* ob->derivedDeform */ + } + else { + dm = mesh_get_derived_final(scene, ob, mask); /* ob->derivedFinal */ + } + } + } + else { + /* !use_deform */ + if (use_render) { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (render=True)"); + return NULL; + } + else { + dm = mesh_create_derived_no_deform_render(scene, ob, NULL, mask); + } + } + else { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (deform=False, render=False)"); + return NULL; + } + else { + dm = mesh_create_derived_no_deform(scene, ob, NULL, mask); + } + } + } if (dm == NULL) { PyErr_Format(PyExc_ValueError, @@ -840,6 +960,8 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args) DM_to_bmesh_ex(dm, bm); + dm->release(dm); + Py_RETURN_NONE; } @@ -1172,13 +1294,7 @@ static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *ar else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(py_face); - - if (py_face->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "BMVert.copy_from_face_interp(face): face is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "copy_from_face_interp()"); BM_vert_interp_from_face(bm, self->v, py_face->f); @@ -1312,13 +1428,7 @@ static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value) return NULL; } - BPY_BM_CHECK_OBJ(value); - - if (self->bm != value->bm) { - PyErr_SetString(PyExc_ValueError, - "BMEdge.other_vert(vert): vert is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "BMEdge.other_vert(vert)"); other = BM_edge_other_vert(self->e, value->v); @@ -1372,13 +1482,7 @@ static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *ar else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(py_face); - - if (py_face->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "BMFace.copy_from_face_interp(face): face is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMFace.copy_from_face_interp(face)"); BM_face_interp_from_face(bm, self->f, py_face->f); @@ -1544,13 +1648,7 @@ static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *ar else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(py_face); - - if (py_face->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "BMLoop.copy_from_face_interp(face): face is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMLoop.copy_from_face_interp(face)"); BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires); @@ -1648,7 +1746,7 @@ static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args) return NULL; } - v = BM_vert_create(bm, co, NULL); + v = BM_vert_create(bm, co, NULL, 0); if (v == NULL) { PyErr_SetString(PyExc_ValueError, @@ -1717,7 +1815,7 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args) goto cleanup; } - e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, FALSE); + e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, 0); if (e == NULL) { PyErr_SetString(PyExc_ValueError, @@ -1790,7 +1888,7 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) } /* check if the face exists */ - if (BM_face_exists(bm, vert_array, vert_seq_len, NULL)) { + if (BM_face_exists(vert_array, vert_seq_len, NULL)) { PyErr_SetString(PyExc_ValueError, "faces.new(verts): face already exists"); goto cleanup; @@ -1803,10 +1901,10 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) /* ensure edges */ for (i = vert_seq_len - 1, i_next = 0; i_next < vert_seq_len; (i = i_next++)) { - edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_next], NULL, TRUE); + edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_next], NULL, BM_CREATE_NO_DOUBLE); } - f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE); + f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, 0); if (UNLIKELY(f_new == NULL)) { PyErr_SetString(PyExc_ValueError, @@ -1846,13 +1944,7 @@ static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value) else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(value); - - if (value->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "verts.remove(vert): vert is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, bm, "verts.remove(vert)"); BM_vert_kill(bm, value->v); bpy_bm_generic_invalidate((BPy_BMGeneric *)value); @@ -1876,13 +1968,7 @@ static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value) else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(value); - - if (value->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "edges.remove(edge): edge is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, bm, "edges.remove(edges)"); BM_edge_kill(bm, value->e); bpy_bm_generic_invalidate((BPy_BMGeneric *)value); @@ -1906,13 +1992,7 @@ static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value) else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(value); - - if (value->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "faces.remove(face): face is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, bm, "faces.remove(face)"); BM_face_kill(bm, value->f); bpy_bm_generic_invalidate((BPy_BMGeneric *)value); @@ -2012,7 +2092,7 @@ static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args) return NULL; } - if (BM_face_exists(bm, vert_array, vert_seq_len, &f)) { + if (BM_face_exists(vert_array, vert_seq_len, &f)) { ret = BPy_BMFace_CreatePyObject(bm, f); } else { @@ -2972,7 +3052,8 @@ void BPy_BM_init_types(void) BPy_BMLoopSeq_Type.tp_methods = bpy_bmloopseq_methods; BPy_BMIter_Type.tp_methods = NULL; - + /*BPy_BMElem_Check() uses bpy_bm_elem_hash() to check types. + * if this changes update the macro */ BPy_BMesh_Type.tp_hash = bpy_bm_hash; BPy_BMVert_Type.tp_hash = bpy_bm_elem_hash; BPy_BMEdge_Type.tp_hash = bpy_bm_elem_hash; @@ -3306,6 +3387,7 @@ PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele) case BM_LOOP: return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele); default: + BLI_assert(0); PyErr_SetString(PyExc_SystemError, "internal error"); return NULL; } @@ -3339,6 +3421,21 @@ int bpy_bm_generic_valid_check(BPy_BMGeneric *self) } } +int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix) +{ + int ret = bpy_bm_generic_valid_check(self); + if (LIKELY(ret == 0)) { + if (UNLIKELY(self->bm != bm_source)) { + /* could give more info here */ + PyErr_Format(PyExc_ValueError, + "%.200s: BMesh data of type %.200s is from another mesh", + error_prefix, Py_TYPE(self)->tp_name); + ret = -1; + } + } + return ret; +} + void bpy_bm_generic_invalidate(BPy_BMGeneric *self) { self->bm = NULL; diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index df5231a4b1b..d15918a3c11 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -55,6 +55,8 @@ extern PyTypeObject BPy_BMIter_Type; #define BPy_BMFaceSeq_Check(v) (Py_TYPE(v) == &BPy_BMFaceSeq_Type) #define BPy_BMLoopSeq_Check(v) (Py_TYPE(v) == &BPy_BMLoopSeq_Type) #define BPy_BMIter_Check(v) (Py_TYPE(v) == &BPy_BMIter_Type) +/* trick since we know they share a hash function */ +#define BPy_BMElem_Check(v) (Py_TYPE(v)->tp_hash == BPy_BMVert_Type.tp_hash) /* cast from _any_ bmesh type - they all have BMesh first */ typedef struct BPy_BMGeneric { @@ -156,9 +158,6 @@ PyObject *BPy_BMIter_CreatePyObject(BMesh *bm); PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */ -int bpy_bm_generic_valid_check(BPy_BMGeneric *self); -void bpy_bm_generic_invalidate(BPy_BMGeneric *self); - void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, const char htype, const char do_unique_check, const char do_bm_check, @@ -169,9 +168,20 @@ int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype); char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32]); char *BPy_BMElem_StringFromHType(const char htype); +void bpy_bm_generic_invalidate(BPy_BMGeneric *self); +int bpy_bm_generic_valid_check(BPy_BMGeneric *self); +int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix); -#define BPY_BM_CHECK_OBJ(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0 -#define BPY_BM_CHECK_INT(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return -1; } (void)0 +#define BPY_BM_CHECK_OBJ(obj) \ + if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0 +#define BPY_BM_CHECK_INT(obj) \ + if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return -1; } (void)0 + +/* macros like BPY_BM_CHECK_OBJ/BPY_BM_CHECK_INT that ensure we're from the right BMesh */ +#define BPY_BM_CHECK_SOURCE_OBJ(obj, bm, errmsg) \ + if (UNLIKELY(bpy_bm_generic_valid_check_source((BPy_BMGeneric *)obj, bm, errmsg) == -1)) { return NULL; } (void)0 +#define BPY_BM_CHECK_SOURCE_INT(obj, bm, errmsg) \ + if (UNLIKELY(bpy_bm_generic_valid_check_source((BPy_BMGeneric *)obj, bm, errmsg) == -1)) { return -1; } (void)0 #define BPY_BM_IS_VALID(obj) (LIKELY((obj)->bm != NULL)) diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index 1fea12d105c..fd31f3c40cc 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -262,16 +262,10 @@ static PyObject *bpy_bmlayeritem_copy_from(BPy_BMLayerItem *self, BPy_BMLayerIte } BPY_BM_CHECK_OBJ(self); - BPY_BM_CHECK_OBJ(value); + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "layer.copy_from()"); - if (self->bm != value->bm) { - PyErr_SetString(PyExc_ValueError, - "layer.copy_from(): layer is from another mesh"); - return NULL; - } - - else if ((self->htype != value->htype) || - (self->type != value->type)) + if ((self->htype != value->htype) || + (self->type != value->type)) { PyErr_SetString(PyExc_ValueError, "layer.copy_from(other): layer type mismatch"); @@ -981,7 +975,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer) } case CD_PROP_INT: { - ret = PyLong_FromSsize_t((Py_ssize_t)(*(int *)value)); + ret = PyLong_FromLong(*(int *)value); break; } case CD_PROP_STR: @@ -1060,7 +1054,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj } case CD_PROP_INT: { - int tmp_val = PyLong_AsSsize_t(py_value); + int tmp_val = PyLong_AsLong(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format(PyExc_TypeError, "expected an int, not a %.200s", Py_TYPE(py_value)->tp_name); ret = -1; diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index 8316d33ea38..b0870578f5a 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -527,7 +527,7 @@ static PyObject *bpy_bmdeformvert_keys(BPy_BMDeformVert *self) ret = PyList_New(self->data->totweight); for (i = 0; i < self->data->totweight; i++, dw++) { - PyList_SET_ITEM(ret, i, PyLong_FromSsize_t(dw->def_nr)); + PyList_SET_ITEM(ret, i, PyLong_FromLong(dw->def_nr)); } return ret; @@ -576,7 +576,7 @@ static PyObject *bpy_bmdeformvert_items(BPy_BMDeformVert *self) for (i = 0; i < self->data->totweight; i++, dw++) { item = PyTuple_New(2); - PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(dw->def_nr)); + PyTuple_SET_ITEM(item, 0, PyLong_FromLong(dw->def_nr)); PyTuple_SET_ITEM(item, 1, PyFloat_FromDouble(dw->weight)); PyList_SET_ITEM(ret, i, item); diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index 2ff731559d1..dfcfbeb0ab5 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -114,13 +114,7 @@ static PyObject *bpy_bmeditselseq_add(BPy_BMEditSelSeq *self, BPy_BMElem *value) return NULL; } - BPY_BM_CHECK_OBJ(value); - - if (self->bm != value->bm) { - PyErr_SetString(PyExc_ValueError, - "Element is not from this mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "select_history.add()"); BM_select_history_store(self->bm, value->ele); @@ -145,11 +139,9 @@ static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *val return NULL; } - BPY_BM_CHECK_OBJ(value); + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "select_history.remove()"); - if ((self->bm != value->bm) || - (BM_select_history_remove(self->bm, value->ele) == FALSE)) - { + if (BM_select_history_remove(self->bm, value->ele) == FALSE) { PyErr_SetString(PyExc_ValueError, "Element not found in selection history"); return NULL; diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index b70df53aff0..f85c3347104 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -557,16 +557,10 @@ static PyObject *bpy_bm_utils_face_vert_separate(PyObject *UNUSED(self), PyObjec return NULL; } - BPY_BM_CHECK_OBJ(py_face); - BPY_BM_CHECK_OBJ(py_vert); - bm = py_face->bm; - if (bm != py_vert->bm) { - PyErr_SetString(PyExc_ValueError, - "mesh elements are from different meshes"); - return NULL; - } + BPY_BM_CHECK_OBJ(py_face); + BPY_BM_CHECK_SOURCE_OBJ(py_vert, bm, "face_vert_separate()"); l = BM_face_vert_share_loop(py_face->f, py_vert->v); diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index a10bfef2a8d..22b9c1a2208 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -613,15 +613,15 @@ static PyObject *Buffer_repr(Buffer *self) } -BGL_Wrap(2, Accum, void, (GLenum, GLfloat)) -BGL_Wrap(1, ActiveTexture, void, (GLenum)) -BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf)) +BGL_Wrap(2, Accum, void, (GLenum, GLfloat)) +BGL_Wrap(1, ActiveTexture, void, (GLenum)) +BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf)) BGL_Wrap(3, AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP)) BGL_Wrap(2, AttachShader, void, (GLuint, GLuint)) -BGL_Wrap(1, Begin, void, (GLenum)) -BGL_Wrap(2, BindTexture, void, (GLenum, GLuint)) -BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat, - GLfloat, GLfloat, GLfloat, GLubyteP)) +BGL_Wrap(1, Begin, void, (GLenum)) +BGL_Wrap(2, BindTexture, void, (GLenum, GLuint)) +BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat, + GLfloat, GLfloat, GLfloat, GLubyteP)) BGL_Wrap(2, BlendFunc, void, (GLenum, GLenum)) BGL_Wrap(1, CallList, void, (GLuint)) BGL_Wrap(3, CallLists, void, (GLsizei, GLenum, GLvoidP)) @@ -675,7 +675,7 @@ BGL_Wrap(1, CullFace, void, (GLenum)) BGL_Wrap(2, DeleteLists, void, (GLuint, GLsizei)) BGL_Wrap(1, DeleteProgram, void, (GLuint)) BGL_Wrap(1, DeleteShader, void, (GLuint)) -BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP)) +BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP)) BGL_Wrap(1, DepthFunc, void, (GLenum)) BGL_Wrap(1, DepthMask, void, (GLboolean)) BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd)) @@ -773,7 +773,7 @@ BGL_Wrap(3, Lighti, void, (GLenum, GLenum, GLint)) BGL_Wrap(3, Lightiv, void, (GLenum, GLenum, GLintP)) BGL_Wrap(2, LineStipple, void, (GLint, GLushort)) BGL_Wrap(1, LineWidth, void, (GLfloat)) -BGL_Wrap(1, LinkProgram, void, (GLuint)) +BGL_Wrap(1, LinkProgram, void, (GLuint)) BGL_Wrap(1, ListBase, void, (GLuint)) BGL_Wrap(1, LoadIdentity, void, (void)) BGL_Wrap(1, LoadMatrixd, void, (GLdoubleP)) @@ -1907,9 +1907,9 @@ PyObject *BPyInit_bgl(void) return submodule; } -static PyObject *Method_ShaderSource (PyObject *UNUSED(self), PyObject *args) +static PyObject *Method_ShaderSource(PyObject *UNUSED(self), PyObject *args) { - int shader; + unsigned int shader; char *source; if (!PyArg_ParseTuple(args, "Is", &shader, &source)) diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index b9ef4b056ad..8d146bedb48 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -1,4 +1,4 @@ -/* +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -56,8 +56,22 @@ static ListBase bpy_import_main_list; static PyMethodDef bpy_import_meth; static PyMethodDef bpy_reload_meth; +static PyObject *imp_reload_orig = NULL; /* 'builtins' is most likely PyEval_GetBuiltins() */ + +/** + * \note to the discerning developer, yes - this is nasty + * monkey-patching our own import into Python's builtin 'imp' module. + * + * However Python's alternative is to use import hooks, + * which are implemented in a way that we can't use our own importer as a + * fall-back (instead we must try and fail - raise an exception evert time). + * Since importing from blenders text-blocks is not the common case + * I prefer to use Pythons import by default and fall-back to + * Blenders - which we can only do by intercepting import calls I'm afraid. + * - Campbell + */ void bpy_import_init(PyObject *builtins) { PyObject *item; @@ -69,7 +83,13 @@ void bpy_import_init(PyObject *builtins) * XXX, use import hooks */ mod = PyImport_ImportModuleLevel((char *)"imp", NULL, NULL, NULL, 0); if (mod) { - PyDict_SetItemString(PyModule_GetDict(mod), "reload", item = PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item); + PyObject *mod_dict = PyModule_GetDict(mod); + + /* blender owns the function */ + imp_reload_orig = PyDict_GetItemString(mod_dict, "reload"); + Py_INCREF(imp_reload_orig); + + PyDict_SetItemString(mod_dict, "reload", item = PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item); Py_DECREF(mod); } else { @@ -309,7 +329,12 @@ static PyObject *blender_reload(PyObject *UNUSED(self), PyObject *module) int found = 0; /* try reimporting from file */ - newmodule = PyImport_ReloadModule(module); + + /* in Py3.3 this just calls imp.reload() which we overwrite, causing recursive calls */ + //newmodule = PyImport_ReloadModule(module); + + newmodule = PyObject_CallFunctionObjArgs(imp_reload_orig, module, NULL); + if (newmodule) return newmodule; diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 529b2e708ad..53112d46098 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -249,7 +249,7 @@ static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUS #if 0 static PyObject *BPy_IDGroup_GetType(BPy_IDProperty *self) { - return PyLong_FromSsize_t(self->prop->type); + return PyLong_FromLong(self->prop->type); } #endif @@ -351,7 +351,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty prop = IDP_New(IDP_DOUBLE, &val, name); } else if (PyLong_Check(ob)) { - val.i = (int) PyLong_AsSsize_t(ob); + val.i = (int)PyLong_AsLong(ob); prop = IDP_New(IDP_INT, &val, name); } else if (PyUnicode_Check(ob)) { @@ -409,7 +409,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty prop = IDP_New(IDP_ARRAY, &val, name); for (i = 0; i < val.array.len; i++) { item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); - ((int *)IDP_Array(prop))[i] = (int)PyLong_AsSsize_t(item); + ((int *)IDP_Array(prop))[i] = (int)PyLong_AsLong(item); } break; case IDP_IDPARRAY: @@ -1072,7 +1072,7 @@ static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value) ((double *)IDP_Array(self->prop))[index] = d; break; case IDP_INT: - i = PyLong_AsSsize_t(value); + i = PyLong_AsLong(value); if (i == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected an int type"); return -1; diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 3b8193c422d..f62fdaf09db 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -83,13 +83,13 @@ int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length, /* could use is_double for 'long int' but no use now */ int *array_int = array; for (i = 0; i < length; i++) { - array_int[i] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)); + array_int[i] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)); } } else if (type == &PyBool_Type) { int *array_bool = array; for (i = 0; i < length; i++) { - array_bool[i] = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0); + array_bool[i] = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)) != 0); } } else { @@ -504,7 +504,7 @@ void PyC_SetHomePath(const char *py_path_bundle) * but current Python lib (release 3.1.1) doesn't handle these correctly */ if (strchr(py_path_bundle, ':')) printf("Warning : Blender application is located in a path containing : or / chars\ - \nThis may make python import function fail\n"); + \nThis may make python import function fail\n"); #endif @@ -567,7 +567,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...) ret = PyObject_CallFunction(calcsize, (char *)"s", format); if (ret) { - sizes[i] = PyLong_AsSsize_t(ret); + sizes[i] = PyLong_AsLong(ret); Py_DECREF(ret); ret = PyObject_CallFunction(unpack, (char *)"sy#", format, (char *)ptr, sizes[i]); } diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index a8aa7269b72..b1eeff8b3ae 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -195,12 +195,12 @@ PyDoc_STRVAR(bpy_app_debug_value_doc, ); static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyLong_FromSsize_t(G.debug_value); + return PyLong_FromLong(G.debug_value); } static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure)) { - int param = PyLong_AsSsize_t(value); + int param = PyLong_AsLong(value); if (param == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "bpy.app.debug_value can only be set to a whole number"); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 94cbee383ea..cdecf64c93c 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -268,6 +268,23 @@ void BPY_python_start(int argc, const char **argv) Py_Initialize(); + /* THIS IS BAD: see http://bugs.python.org/issue16129 */ +#if 1 + /* until python provides a reliable way to set the env var */ + PyRun_SimpleString("import sys, io\n" + "sys.__backup_stdio__ = sys.__stdout__, sys.__stderr__\n" /* else we loose the FD's [#32720] */ + "sys.__stdout__ = sys.stdout = io.TextIOWrapper(io.open(sys.stdout.fileno(), 'wb', -1), " + "encoding='utf-8', errors='surrogateescape', newline='\\n', line_buffering=True)\n" + "sys.__stderr__ = sys.stderr = io.TextIOWrapper(io.open(sys.stderr.fileno(), 'wb', -1), " + "encoding='utf-8', errors='surrogateescape', newline='\\n', line_buffering=True)\n"); + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } +#endif + /* end the baddness */ + + // PySys_SetArgv(argc, argv); /* broken in py3, not a huge deal */ /* sigh, why do python guys not have a (char **) version anymore? */ { @@ -601,7 +618,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value, const short ve } } - PyC_MainModule_Backup(&main_mod); + PyC_MainModule_Restore(main_mod); bpy_context_clear(C, &gilstate); diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c index 7c8291d62d3..70ea57bb33f 100644 --- a/source/blender/python/intern/bpy_intern_string.c +++ b/source/blender/python/intern/bpy_intern_string.c @@ -38,6 +38,8 @@ PyObject *bpy_intern_str_bl_rna; PyObject *bpy_intern_str_order; PyObject *bpy_intern_str_attr; PyObject *bpy_intern_str___slots__; +PyObject *bpy_intern_str___name__; +PyObject *bpy_intern_str___doc__; void bpy_intern_string_init(void) { @@ -47,6 +49,8 @@ void bpy_intern_string_init(void) bpy_intern_str_order = PyUnicode_FromString("order"); bpy_intern_str_attr = PyUnicode_FromString("attr"); bpy_intern_str___slots__ = PyUnicode_FromString("__slots__"); + bpy_intern_str___name__ = PyUnicode_FromString("__name__"); + bpy_intern_str___doc__ = PyUnicode_FromString("__doc__"); } void bpy_intern_string_exit(void) @@ -57,4 +61,6 @@ void bpy_intern_string_exit(void) Py_DECREF(bpy_intern_str_order); Py_DECREF(bpy_intern_str_attr); Py_DECREF(bpy_intern_str___slots__); + Py_DECREF(bpy_intern_str___name__); + Py_DECREF(bpy_intern_str___doc__); } diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h index dc7af735743..0b7ca2cd47b 100644 --- a/source/blender/python/intern/bpy_intern_string.h +++ b/source/blender/python/intern/bpy_intern_string.h @@ -33,3 +33,5 @@ extern PyObject *bpy_intern_str_bl_rna; extern PyObject *bpy_intern_str_order; extern PyObject *bpy_intern_str_attr; extern PyObject *bpy_intern_str___slots__; +extern PyObject *bpy_intern_str___name__; +extern PyObject *bpy_intern_str___doc__; diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index eaaced416fe..a0df8988068 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1344,7 +1344,7 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop)); break; case PROP_INT: - ret = PyLong_FromSsize_t((Py_ssize_t)RNA_property_int_get(ptr, prop)); + ret = PyLong_FromLong(RNA_property_int_get(ptr, prop)); break; case PROP_FLOAT: ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop)); @@ -2371,7 +2371,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po RNA_property_int_get_array(ptr, prop, values); for (count = start; count < stop; count++) - PyTuple_SET_ITEM(tuple, count - start, PyLong_FromSsize_t(values[count])); + PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count])); if (values != values_stack) { PyMem_FREE(values); @@ -4077,7 +4077,7 @@ static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self) } else { /* a bit strange but better then returning an empty list */ - PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); + PyTuple_SET_ITEM(item, 0, PyLong_FromLong(i)); } PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); @@ -4256,7 +4256,7 @@ static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key } RNA_PROP_END; - return PyLong_FromSsize_t(index); + return PyLong_FromLong(index); } static void foreach_attr_type(BPy_PropertyRNA *self, const char *attr, @@ -4463,13 +4463,13 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) switch (raw_type) { case PROP_RAW_CHAR: - item = PyLong_FromSsize_t((Py_ssize_t) ((char *)array)[i]); + item = PyLong_FromLong((long) ((char *)array)[i]); break; case PROP_RAW_SHORT: - item = PyLong_FromSsize_t((Py_ssize_t) ((short *)array)[i]); + item = PyLong_FromLong((long) ((short *)array)[i]); break; case PROP_RAW_INT: - item = PyLong_FromSsize_t((Py_ssize_t) ((int *)array)[i]); + item = PyLong_FromLong((long) ((int *)array)[i]); break; case PROP_RAW_FLOAT: item = PyFloat_FromDouble((double) ((float *)array)[i]); @@ -4756,7 +4756,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat case PROP_INT: ret = PyTuple_New(len); for (a = 0; a < len; a++) - PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t((Py_ssize_t)((int *)data)[a])); + PyTuple_SET_ITEM(ret, a, PyLong_FromLong(((int *)data)[a])); break; case PROP_FLOAT: switch (RNA_property_subtype(prop)) { @@ -4797,7 +4797,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat ret = PyBool_FromLong(*(int *)data); break; case PROP_INT: - ret = PyLong_FromSsize_t((Py_ssize_t)*(int *)data); + ret = PyLong_FromLong(*(int *)data); break; case PROP_FLOAT: ret = PyFloat_FromDouble(*(float *)data); @@ -6883,8 +6883,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v /* Sneaky workaround to use the class name as the bl_idname */ #define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ - if (strcmp(identifier, rna_attr) == 0) { \ - item = PyObject_GetAttrString(py_class, py_attr); \ + (strcmp(identifier, rna_attr) == 0) { \ + item = PyObject_GetAttr(py_class, py_attr); \ if (item && item != Py_None) { \ if (pyrna_py_to_prop(dummyptr, prop, NULL, \ item, "validating class:") != 0) \ @@ -6894,11 +6894,10 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v } \ } \ Py_XDECREF(item); \ - } (void)0 + } /* intendionally allow else here */ - - BPY_REPLACEMENT_STRING("bl_idname", "__name__"); - BPY_REPLACEMENT_STRING("bl_description", "__doc__"); + if BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__) + else if BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__) #undef BPY_REPLACEMENT_STRING @@ -6912,10 +6911,11 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v PyErr_Clear(); } else { - Py_DECREF(item); /* no need to keep a ref, the class owns it */ - - if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) + if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { + Py_DECREF(item); return -1; + } + Py_DECREF(item); } } diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index e66d8f05309..62c0ced9eab 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -507,7 +507,7 @@ static void py_to_float(PyObject *py, char *data) static void py_to_int(PyObject *py, char *data) { - *(int *)data = (int)PyLong_AsSsize_t(py); + *(int *)data = (int)PyLong_AsLong(py); } static void py_to_bool(PyObject *py, char *data) @@ -609,7 +609,7 @@ PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index) item = PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index)); break; case PROP_INT: - item = PyLong_FromSsize_t(RNA_property_int_get_index(ptr, prop, index)); + item = PyLong_FromLong(RNA_property_int_get_index(ptr, prop, index)); break; default: PyErr_SetString(PyExc_TypeError, "not an array type"); @@ -766,7 +766,7 @@ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) case PROP_BOOLEAN: case PROP_INT: { - int value_i = PyLong_AsSsize_t(value); + int value_i = PyLong_AsLong(value); if (value_i == -1 && PyErr_Occurred()) { PyErr_Clear(); return 0; diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index f7aa6e0880b..48bf65a841b 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -39,70 +39,80 @@ static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) return PyBytes_AS_STRING((*coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename))); } -/* copied from pythonrun.c, 3.2.0 */ +/* copied from pythonrun.c, 3.3.0 */ static int parse_syntax_error(PyObject *err, PyObject **message, const char **filename, int *lineno, int *offset, const char **text) { long hold; PyObject *v; + _Py_IDENTIFIER(msg); + _Py_IDENTIFIER(filename); + _Py_IDENTIFIER(lineno); + _Py_IDENTIFIER(offset); + _Py_IDENTIFIER(text); - /* old style errors */ - if (PyTuple_Check(err)) - return PyArg_ParseTuple(err, "O(ziiz)", message, filename, - lineno, offset, text); + *message = NULL; /* new style errors. `err' is an instance */ - - if (!(v = PyObject_GetAttrString(err, "msg"))) + *message = _PyObject_GetAttrId(err, &PyId_msg); + if (!*message) goto finally; - *message = v; - if (!(v = PyObject_GetAttrString(err, "filename"))) + v = _PyObject_GetAttrId(err, &PyId_filename); + if (!v) goto finally; - if (v == Py_None) + if (v == Py_None) { + Py_DECREF(v); *filename = NULL; - else if (!(*filename = _PyUnicode_AsString(v))) - goto finally; + } + else { + *filename = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*filename) + goto finally; + } - Py_DECREF(v); - if (!(v = PyObject_GetAttrString(err, "lineno"))) + v = _PyObject_GetAttrId(err, &PyId_lineno); + if (!v) goto finally; hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *lineno = (int)hold; - if (!(v = PyObject_GetAttrString(err, "offset"))) + v = _PyObject_GetAttrId(err, &PyId_offset); + if (!v) goto finally; if (v == Py_None) { *offset = -1; Py_DECREF(v); - v = NULL; - } - else { + } else { hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *offset = (int)hold; } - if (!(v = PyObject_GetAttrString(err, "text"))) + v = _PyObject_GetAttrId(err, &PyId_text); + if (!v) goto finally; - if (v == Py_None) + if (v == Py_None) { + Py_DECREF(v); *text = NULL; - else if (!PyUnicode_Check(v) || - !(*text = _PyUnicode_AsString(v))) - goto finally; - Py_DECREF(v); + } + else { + *text = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*text) + goto finally; + } return 1; finally: - Py_XDECREF(v); + Py_XDECREF(*message); return 0; } /* end copied function! */ diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index 6aa50cf88de..b5f679b741f 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -27,16 +27,8 @@ #ifndef __BPY_UTIL_H__ #define __BPY_UTIL_H__ -#if PY_VERSION_HEX < 0x03020000 -# error "Python 3.2 or greater is required, you'll need to update your python." -#endif - #if PY_VERSION_HEX < 0x03030000 -# ifdef _MSC_VER -# pragma message("Python 3.2 will be deprecated soon, upgrade to Python 3.3.") -# else -# warning "Python 3.2 will be deprecated soon, upgrade to Python 3.3." -# endif +# error "Python 3.3 or greater is required, you'll need to update your python." #endif struct EnumPropertyItem; diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index a4a4010005a..202598233b6 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif PyDoc_STRVAR(M_Mathutils_doc, "This module provides access to matrices, eulers, quaternions and vectors." @@ -302,7 +305,7 @@ int EXPP_FloatsAreEqual(float af, float bf, int maxDiff) /*---------------------- EXPP_VectorsAreEqual ------------------------- * Builds on EXPP_FloatsAreEqual to test vectors */ -int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps) +int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps) { int x; for (x = 0; x < size; x++) { @@ -312,6 +315,7 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps) return 1; } +#ifndef MATH_STANDALONE /* dynstr as python string utility funcions, frees 'ds'! */ PyObject *mathutils_dynstr_to_py(struct DynStr *ds) { @@ -324,6 +328,7 @@ PyObject *mathutils_dynstr_to_py(struct DynStr *ds) PyMem_Free(ds_buf); return ret; } +#endif /* silly function, we dont use arg. just check its compatible with __deepcopy__ */ int mathutils_deepcopy_args_check(PyObject *args) diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index d4673d14823..7b03b149459 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -74,7 +74,7 @@ void BaseMathObject_dealloc(BaseMathObject * self); PyMODINIT_FUNC PyInit_mathutils(void); int EXPP_FloatsAreEqual(float A, float B, int floatSteps); -int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps); +int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps); #define Py_NEW 1 #define Py_WRAP 2 @@ -120,8 +120,11 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat); +#ifndef MATH_STANDALONE /* dynstr as python string utility funcions */ PyObject *mathutils_dynstr_to_py(struct DynStr *ds); +#endif + int mathutils_deepcopy_args_check(PyObject *args); #endif /* __MATHUTILS_H__ */ diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index f16b488f9d0..4a29e72418b 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -31,7 +31,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif #define COLOR_SIZE 3 @@ -131,6 +134,7 @@ static PyObject *Color_repr(ColorObject *self) return ret; } +#ifndef MATH_STANDALONE static PyObject *Color_str(ColorObject *self) { DynStr *ds; @@ -145,6 +149,7 @@ static PyObject *Color_str(ColorObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } +#endif /* ------------------------tp_richcmpr */ /* returns -1 exception, 0 false, 1 true */ @@ -820,7 +825,11 @@ PyTypeObject color_Type = { &Color_AsMapping, /* tp_as_mapping */ NULL, /* tp_hash */ NULL, /* tp_call */ +#ifndef MATH_STANDALONE (reprfunc) Color_str, /* tp_str */ +#else + NULL, /* tp_str */ +#endif NULL, /* tp_getattro */ NULL, /* tp_setattro */ NULL, /* tp_as_buffer */ diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 829d3ee27e1..1be8a5efe28 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif #define EULER_SIZE 3 @@ -323,6 +326,7 @@ static PyObject *Euler_repr(EulerObject *self) return ret; } +#ifndef MATH_STANDALONE static PyObject *Euler_str(EulerObject *self) { DynStr *ds; @@ -337,6 +341,7 @@ static PyObject *Euler_str(EulerObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } +#endif static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op) { @@ -663,7 +668,11 @@ PyTypeObject euler_Type = { &Euler_AsMapping, /* tp_as_mapping */ NULL, /* tp_hash */ NULL, /* tp_call */ +#ifndef MATH_STANDALONE (reprfunc) Euler_str, /* tp_str */ +#else + NULL, /* tp_str */ +#endif NULL, /* tp_getattro */ NULL, /* tp_setattro */ NULL, /* tp_as_buffer */ diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 64112024dd1..05306f230d1 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif typedef enum eMatrixAccess_t { MAT_ACCESS_ROW, @@ -1647,6 +1650,7 @@ static PyObject *Matrix_repr(MatrixObject *self) return NULL; } +#ifndef MATH_STANDALONE static PyObject *Matrix_str(MatrixObject *self) { DynStr *ds; @@ -1682,6 +1686,7 @@ static PyObject *Matrix_str(MatrixObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } +#endif static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op) { @@ -2418,7 +2423,11 @@ PyTypeObject matrix_Type = { &Matrix_AsMapping, /*tp_as_mapping*/ NULL, /*tp_hash*/ NULL, /*tp_call*/ +#ifndef MATH_STANDALONE (reprfunc) Matrix_str, /*tp_str*/ +#else + NULL, /*tp_str*/ +#endif NULL, /*tp_getattro*/ NULL, /*tp_setattro*/ NULL, /*tp_as_buffer*/ diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index cda39932610..c28631e5045 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif #define QUAT_SIZE 4 @@ -496,6 +499,7 @@ static PyObject *Quaternion_repr(QuaternionObject *self) return ret; } +#ifndef MATH_STANDALONE static PyObject *Quaternion_str(QuaternionObject *self) { DynStr *ds; @@ -510,6 +514,7 @@ static PyObject *Quaternion_str(QuaternionObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } +#endif static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op) { @@ -1202,7 +1207,11 @@ PyTypeObject quaternion_Type = { &Quaternion_AsMapping, /* tp_as_mapping */ NULL, /* tp_hash */ NULL, /* tp_call */ +#ifndef MATH_STANDALONE (reprfunc) Quaternion_str, /* tp_str */ +#else + NULL, /* tp_str */ +#endif NULL, /* tp_getattro */ NULL, /* tp_setattro */ NULL, /* tp_as_buffer */ diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 19be2b6a62e..f8159f6f187 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif #define MAX_DIMENSIONS 4 @@ -1231,6 +1234,7 @@ static PyObject *Vector_repr(VectorObject *self) return ret; } +#ifndef MATH_STANDALONE static PyObject *Vector_str(VectorObject *self) { int i; @@ -1252,7 +1256,7 @@ static PyObject *Vector_str(VectorObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } - +#endif /* Sequence Protocol */ /* sequence length len(vector) */ @@ -2784,7 +2788,7 @@ static struct PyMethodDef Vector_methods[] = { /* Note * Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing * but this means for eg that - * (vec * mat) and (mat * vec) both get sent to Vector_mul and it neesd to sort out the order + * (vec * mat) and (mat * vec) both get sent to Vector_mul and it needs to sort out the order */ PyDoc_STRVAR(vector_doc, @@ -2816,7 +2820,11 @@ PyTypeObject vector_Type = { NULL, /* hashfunc tp_hash; */ NULL, /* ternaryfunc tp_call; */ +#ifndef MATH_STANDALONE (reprfunc)Vector_str, /* reprfunc tp_str; */ +#else + NULL, /* reprfunc tp_str; */ +#endif NULL, /* getattrofunc tp_getattro; */ NULL, /* setattrofunc tp_setattro; */ diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 22317636faa..1db0538eb07 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -973,12 +973,14 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a float n1n2[3], n2n3[3], n3n1[3]; float potentialVertex[3]; - char *planes_used = MEM_callocN(sizeof(char) * len, __func__); + char *planes_used = PyMem_Malloc(sizeof(char) * len); /* python */ PyObject *py_verts = PyList_New(0); PyObject *py_plene_index = PyList_New(0); + memset(planes_used, 0, sizeof(char) * len); + for (i = 0; i < len; i++) { const float *N1 = planes[i]; for (j = i + 1; j < len; j++) { @@ -1031,7 +1033,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a Py_DECREF(item); } } - MEM_freeN(planes_used); + PyMem_Free(planes_used); { PyObject *ret = PyTuple_New(2); diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index cef4cb8c2a6..a3469ddafde 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -87,8 +87,8 @@ void makeqtstring(struct RenderData *rd, char *string); //for playanim.c -#if (defined(USE_QTKIT) && defined(MAC_OS_X_VERSION_10_6) && __LP64__) -//Include the quicktime codec types constants that are missing in QTKitDefines.h in 10.6 / 64bit +#if (defined(USE_QTKIT) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 && __LP64__) +//Include the quicktime codec types constants that are missing in QTKitDefines.h enum { kRawCodecType = 'raw ', kCinepakCodecType = 'cvid', diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 1331c287d7c..d2ffc3a0e26 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -60,6 +60,7 @@ struct Scene; #define RE_ENGINE_PREVIEW 2 #define RE_ENGINE_DO_DRAW 4 #define RE_ENGINE_DO_UPDATE 8 +#define RE_ENGINE_RENDERING 16 extern ListBase R_engines; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 984b1a8e651..ecdd1774221 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -170,6 +170,8 @@ void RE_FreeRender (struct Render *re); void RE_FreeAllRender (void); /* only call on file load */ void RE_FreeAllRenderResults(void); +/* for external render engines that can keep persistent data */ +void RE_FreePersistentData(void); /* get results and statistics */ void RE_FreeRenderResult(struct RenderResult *rr); diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h index 43ab9552194..73dc29c8feb 100644 --- a/source/blender/render/intern/include/initrender.h +++ b/source/blender/render/intern/include/initrender.h @@ -40,8 +40,9 @@ struct Object; void free_sample_tables(Render *re); void make_sample_tables(Render *re); -void initparts(Render *re, int do_crop); -void freeparts(Render *re); +void RE_parts_clamp(Render *re); +void RE_parts_init(Render *re, int do_crop); +void RE_parts_free(Render *re); #endif /* __INITRENDER_H__ */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 825fe2ff4d0..6ed8d6a7b6c 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -59,6 +59,7 @@ struct RenderBuckets; struct ObjectInstanceRen; struct RayObject; struct RayFace; +struct RenderEngine; struct ReportList; struct Main; @@ -183,6 +184,9 @@ struct Render ListBase parts; + /* render engine */ + struct RenderEngine *engine; + /* octree tables and variables for raytrace */ struct RayObject *raytree; struct RayFace *rayfaces; diff --git a/source/blender/render/intern/raytrace/rayobject_internal.h b/source/blender/render/intern/raytrace/rayobject_internal.h index 92ac39909a8..aa8ab8c3da4 100644 --- a/source/blender/render/intern/raytrace/rayobject_internal.h +++ b/source/blender/render/intern/raytrace/rayobject_internal.h @@ -92,7 +92,7 @@ int RE_rayobjectcontrol_test_break(RayObjectControl *c); * eg.: on render code) * * 0 means it's reserved and has it own meaning inside each ray acceleration structure - * (this way each structure can use the allign offset to determine if a node represents a + * (this way each structure can use the align offset to determine if a node represents a * RayObject primitive, which can be used to save memory) */ diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp index 77e9dc9d8fd..afb8fe6c3b5 100644 --- a/source/blender/render/intern/raytrace/rayobject_octree.cpp +++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp @@ -1026,7 +1026,7 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) labdao = ddalabda; - /* traversing ocree nodes need careful detection of smallest values, with proper + /* traversing octree nodes need careful detection of smallest values, with proper * exceptions for equal labdas */ eqval = (labdax == labday); if (labday == labdaz) eqval += 2; diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index bae65c492f4..4195b103811 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -435,7 +435,7 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) /* * Helper code * PARTITION code / used on mean-split - * basicly this a std::nth_element (like on C++ STL algorithm) + * basically this a std::nth_element (like on C++ STL algorithm) */ #if 0 static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index e305f434ebb..386086333e0 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -125,7 +125,9 @@ #define FLT_EPSILON10 1.19209290e-06F /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ------------------------------------------------------------------------- */ @@ -1705,8 +1707,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem totface= psmd->dm->getNumTessFaces(psmd->dm); index_mf_to_mpoly = psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX); index_mp_to_orig = psmd->dm->getPolyDataArray(psmd->dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } for (a=0; atotbound = max_ii(strandbuf->totbound, (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a): a); @@ -4296,7 +4298,7 @@ static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset) /* compute average bounding box of strandpoint itself (width) */ if (obr->strandbuf->flag & R_STRAND_B_UNITS) - obr->strandbuf->maxwidth= MAX2(obr->strandbuf->ma->strand_sta, obr->strandbuf->ma->strand_end); + obr->strandbuf->maxwidth = max_ff(obr->strandbuf->ma->strand_sta, obr->strandbuf->ma->strand_end); else obr->strandbuf->maxwidth= 0.0f; @@ -4501,7 +4503,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject * ParticleSystem *psys; int show_emitter, allow_render= 1, index, psysindex, i; - index= (dob)? dob->index: 0; + index= (dob)? dob->persistent_id[0]: 0; /* the emitter has to be processed first (render levels of modifiers) */ /* so here we only check if the emitter should be rendered */ @@ -4900,7 +4902,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) { mult_m4_m4m4(mat, re->viewmat, dob->mat); /* ob = particle system, use that layer */ - obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat, ob->lay); + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay); /* fill in instance variables for texturing */ set_dupli_tex_mat(re, obi, dob); @@ -4927,7 +4929,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) { if (obi == NULL) mult_m4_m4m4(mat, re->viewmat, dob->mat); - obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat, obd->lay); + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay); set_dupli_tex_mat(re, obi, dob); if (dob->type != OB_DUPLIGROUP) { diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 28f70211a9c..c3126e57b53 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -687,11 +687,12 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o env->ima = tex->ima; if (env->ima && env->ima->ok) { if (env->cube[1] == NULL) { - ImBuf *ibuf_ima = BKE_image_get_ibuf(env->ima, NULL); + ImBuf *ibuf_ima = BKE_image_acquire_ibuf(env->ima, NULL, NULL); if (ibuf_ima) envmap_split_ima(env, ibuf_ima); else env->ok = 0; + BKE_image_release_ibuf(env->ima, ibuf_ima, NULL); } } } diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 4ec19fa729f..6fdf11ba48c 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -306,7 +306,7 @@ void RE_engine_report(RenderEngine *engine, int type, const char *msg) if (re) BKE_report(engine->re->reports, type, msg); - else if(engine->reports) + else if (engine->reports) BKE_report(engine->reports, type, msg); } @@ -316,6 +316,7 @@ int RE_engine_render(Render *re, int do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; + int persistent_data = re->r.mode & R_PERSISTENT_DATA; /* verify if we can render */ if (!type->render) @@ -349,7 +350,18 @@ int RE_engine_render(Render *re, int do_all) re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ - engine = RE_engine_create(type); + engine = re->engine; + + if (!engine) { + engine = RE_engine_create(type); + + if (persistent_data) + re->engine = engine; + } + + engine->flag |= RE_ENGINE_RENDERING; + + /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; if (re->flag & R_ANIMATION) @@ -364,7 +376,7 @@ int RE_engine_render(Render *re, int do_all) if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_PREVIEWBUTS)) == 0) BKE_scene_update_for_newframe(re->main, re->scene, re->lay); - initparts(re, FALSE); + RE_parts_init(re, FALSE); engine->tile_x = re->partx; engine->tile_y = re->party; @@ -377,19 +389,25 @@ int RE_engine_render(Render *re, int do_all) if (type->render) type->render(engine, re->scene); + engine->tile_x = 0; + engine->tile_y = 0; + engine->flag &= ~RE_ENGINE_RENDERING; + + render_result_free_list(&engine->fullresult, engine->fullresult.first); + + /* re->engine becomes zero if user changed active render engine during render */ + if (!persistent_data || !re->engine) { + RE_engine_free(engine); + re->engine = NULL; + } + if (re->result->do_exr_tile) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_end(re); BLI_rw_mutex_unlock(&re->resultmutex); } - engine->tile_x = 0; - engine->tile_y = 0; - freeparts(re); - - render_result_free_list(&engine->fullresult, engine->fullresult.first); - - RE_engine_free(engine); + RE_parts_free(re); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = TRUE; diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index db1454fd82f..cd06839b004 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -124,13 +124,16 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul /* hack for icon render */ if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - - ibuf= BKE_image_get_ibuf(ima, &tex->iuser); + + ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); ima->flag|= IMA_USED_FOR_RENDER; } - if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; + } /* setup mapping */ if (tex->imaflag & TEX_IMAROT) { @@ -155,11 +158,17 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul /* pass */ } else { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { - if ((xs+ys) & 1) return retval; + if ((xs+ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } } /* scale around center, (0.5, 0.5) */ if (tex->checkerdist<1.0f) { @@ -173,11 +182,15 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul if (tex->extend == TEX_CLIPCUBE) { if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } @@ -287,6 +300,9 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul texres->tb*= fx; } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1056,10 +1072,14 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex if (ima) { /* hack for icon render */ if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); } - if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval; + if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } if (ima) { ima->flag |= IMA_USED_FOR_RENDER; @@ -1172,8 +1192,16 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex } } else { - if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) return retval; - if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) return retval; + if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } + if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } fx -= xs; fy -= ys; } @@ -1189,10 +1217,18 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex } if (tex->extend == TEX_CLIPCUBE) { - if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) return retval; + if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } } else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) { - if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) return retval; + if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } } else { if (tex->extend == TEX_EXTEND) { @@ -1413,6 +1449,9 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex texres->tb *= fx; } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1449,12 +1488,15 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - ibuf= BKE_image_get_ibuf(ima, &tex->iuser); + ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); ima->flag|= IMA_USED_FOR_RENDER; } - if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; + } /* mipmap test */ image_mipmap_test(tex, ibuf); @@ -1565,11 +1607,15 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const /* pass */ } else { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { if ((xs + ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } @@ -1605,11 +1651,15 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (tex->extend == TEX_CLIPCUBE) { if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } @@ -1804,6 +1854,9 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const mul_v3_fl(&texres->tr, 1.0f / texres->ta); } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1812,7 +1865,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4]) { TexResult texres; - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); if (UNLIKELY(ibuf == NULL)) { zero_v4(result); @@ -1830,6 +1883,8 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu ibuf->rect-= (ibuf->x*ibuf->y); ima->flag|= IMA_USED_FOR_RENDER; + + BKE_image_release_ibuf(ima, ibuf, NULL); } void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4]) diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index b2cf8db7995..3ea74abbcc2 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -525,7 +525,7 @@ void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, flo /* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */ -void freeparts(Render *re) +void RE_parts_free(Render *re) { RenderPart *part = re->parts.first; @@ -537,12 +537,19 @@ void freeparts(Render *re) BLI_freelistN(&re->parts); } -void initparts(Render *re, int do_crop) +void RE_parts_clamp(Render *re) +{ + /* part size */ + re->partx = min_ii(re->r.tilex, re->rectx); + re->party = min_ii(re->r.tiley, re->recty); +} + +void RE_parts_init(Render *re, int do_crop) { int nr, xd, yd, partx, party, xparts, yparts; int xminb, xmaxb, yminb, ymaxb; - freeparts(re); + RE_parts_free(re); /* this is render info for caller, is not reset when parts are freed! */ re->i.totpart = 0; @@ -555,13 +562,10 @@ void initparts(Render *re, int do_crop) xmaxb = re->disprect.xmax; ymaxb = re->disprect.ymax; - /* part size */ - partx = min_ii(re->r.tilex, re->rectx); - party = min_ii(re->r.tiley, re->recty); - - re->partx = partx; - re->party = party; - + RE_parts_clamp(re); + + partx = re->partx; + party = re->party; /* part count */ xparts = (re->rectx + partx - 1) / partx; yparts = (re->recty + party - 1) / party; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7ef3aecad08..6b5b9716f3b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -63,6 +63,7 @@ #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" +#include "BLI_threads.h" #include "BLI_rand.h" #include "BLI_callbacks.h" @@ -244,6 +245,7 @@ Render *RE_GetRender(const char *name) return re; } + /* if you want to know exactly what has been done */ RenderResult *RE_AcquireResultRead(Render *re) { @@ -387,6 +389,9 @@ void RE_InitRenderCB(Render *re) /* only call this while you know it will remove the link too */ void RE_FreeRender(Render *re) { + if (re->engine) + RE_engine_free(re->engine); + BLI_rw_mutex_end(&re->resultmutex); free_renderdata_tables(re); @@ -421,6 +426,22 @@ void RE_FreeAllRenderResults(void) } } +void RE_FreePersistentData(void) +{ + Render *re; + + /* render engines can be kept around for quick re-render, this clears all */ + for (re = RenderGlobal.renderlist.first; re; re = re->next) { + if (re->engine) { + /* if engine is currently rendering, just tag it to be freed when render is finished */ + if (!(re->engine->flag & RE_ENGINE_RENDERING)) + RE_engine_free(re->engine); + + re->engine = NULL; + } + } +} + /* ********* initialize state ******** */ @@ -672,7 +693,7 @@ static void *do_part_thread(void *pa_v) /* calculus for how much 1 pixel rendered should rotate the 3d geometry */ /* is not that simple, needs to be corrected for errors of larger viewplane sizes */ -/* called in initrender.c, initparts() and convertblender.c, for speedvectors */ +/* called in initrender.c, RE_parts_init() and convertblender.c, for speedvectors */ float panorama_pixel_rot(Render *re) { float psize, phi, xfac; @@ -815,7 +836,7 @@ static void threaded_tile_processor(Render *re) /* warning; no return here without closing exr file */ - initparts(re, TRUE); + RE_parts_init(re, TRUE); if (re->result->do_exr_tile) render_result_exr_file_begin(re); @@ -907,7 +928,7 @@ static void threaded_tile_processor(Render *re) g_break = 0; BLI_end_threads(&threads); - freeparts(re); + RE_parts_free(re); re->viewplane = viewplane; /* restore viewplane, modified by pano render */ } @@ -926,6 +947,7 @@ static void do_render_3d(Render *re) return; /* internal */ + RE_parts_clamp(re); // re->cfra= cfra; /* <- unused! */ re->scene->r.subframe = re->mblur_offs + re->field_offs; @@ -2507,8 +2529,8 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, if (env->type == ENV_CUBE) { for (i = 0; i < 12; i += 2) { - maxX = MAX2(maxX, layout[i] + 1); - maxY = MAX2(maxY, layout[i + 1] + 1); + maxX = max_ii(maxX, (int)layout[i] + 1); + maxY = max_ii(maxY, (int)layout[i + 1] + 1); } ibuf = IMB_allocImBuf(maxX * dx, maxY * dx, 24, IB_rectfloat); diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index c507d6595e0..e6daa5f9094 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1233,11 +1233,13 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output); if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); + + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } } else { @@ -1264,11 +1266,13 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os rgbnor= multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output); { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); + + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } } @@ -1723,11 +1727,12 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) { /* in case we have no proper derivatives, fall back to * computing du/dv it based on image size */ - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf) { du = 1.f/(float)ibuf->x; dv = 1.f/(float)ibuf->y; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } else if (shi->osatex) { /* we have derivatives, can compute proper du/dv */ @@ -1900,12 +1905,13 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T /* resolve image dimensions */ if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf) { dimx = ibuf->x; dimy = ibuf->y; aspect = ((float) dimy) / dimx; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } if (found_deriv_map) { @@ -2396,11 +2402,13 @@ void do_material_tex(ShadeInput *shi, Render *re) /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); + + BKE_image_release_ibuf(ima, ibuf, NULL); } if (mtex->mapto & MAP_COL) { @@ -2928,11 +2936,13 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) /* inverse gamma correction */ if (mtex->tex->type==TEX_IMAGE) { Image *ima = mtex->tex->ima; - ImBuf *ibuf = BKE_image_get_ibuf(ima, &mtex->tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &mtex->tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); + + BKE_image_release_ibuf(ima, ibuf, NULL); } fact= texres.tin*mtex->colfac; @@ -3147,11 +3157,13 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); + + BKE_image_release_ibuf(ima, ibuf, NULL); } if (mtex->mapto & WOMAP_HORIZ) { @@ -3361,11 +3373,13 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); + + BKE_image_release_ibuf(ima, ibuf, NULL); } /* lamp colors were premultiplied with this */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 9fe2620747c..3431c3ff5de 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2506,21 +2506,26 @@ static int get_next_bake_face(BakeShade *bs) if (tface && tface->tpage) { Image *ima= tface->tpage; - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f}; const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f}; if (ibuf==NULL) continue; - if (ibuf->rect==NULL && ibuf->rect_float==NULL) + if (ibuf->rect==NULL && ibuf->rect_float==NULL) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } - if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) + if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } if (ima->flag & IMA_USED_FOR_RENDER) { ima->id.flag &= ~LIB_DOIT; + BKE_image_release_ibuf(ima, ibuf, NULL); continue; } @@ -2548,6 +2553,9 @@ static int get_next_bake_face(BakeShade *bs) v++; BLI_unlock_thread(LOCK_CUSTOM1); + + BKE_image_release_ibuf(ima, ibuf, NULL); + return 1; } } @@ -2571,8 +2579,10 @@ static void shade_tface(BakeShade *bs) /* check valid zspan */ if (ima!=bs->ima) { + BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); + bs->ima= ima; - bs->ibuf= BKE_image_get_ibuf(ima, NULL); + bs->ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); /* note, these calls only free/fill contents of zspan struct, not zspan itself */ zbuf_free_span(bs->zspan); zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); @@ -2638,7 +2648,9 @@ static void *do_bake_thread(void *bs_v) *bs->do_update= TRUE; } bs->ready= 1; - + + BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); + return NULL; } @@ -2689,12 +2701,13 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up /* baker uses this flag to detect if image was initialized */ for (ima= G.main->image.first; ima; ima= ima->id.next) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); ima->id.flag |= LIB_DOIT; ima->flag&= ~IMA_USED_FOR_RENDER; if (ibuf) { ibuf->userdata = NULL; /* use for masking if needed */ } + BKE_image_release_ibuf(ima, ibuf, NULL); } BLI_init_threads(&threads, do_bake_thread, re->r.threads); @@ -2747,7 +2760,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up /* filter and refresh images */ for (ima= G.main->image.first; ima; ima= ima->id.next) { if ((ima->id.flag & LIB_DOIT)==0) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima->flag & IMA_USED_FOR_RENDER) result= BAKE_RESULT_FEEDBACK_LOOP; @@ -2758,6 +2771,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter); ibuf->userflags |= IB_BITMAPDIRTY; + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 7a7602dcce2..44daaf516e1 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -1179,30 +1179,36 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater /* -------------------------- operations on entire database ----------------------- */ /* ugly function for halos in panorama */ -static int panotestclip(Render *re, int do_pano, float *v) +static int panotestclip(Render *re, int do_pano, float v[4]) { - /* to be used for halos en infos */ - float abs4; - short c=0; - int xparts = (re->rectx + re->partx - 1) / re->partx; + /* part size (ensure we run RE_parts_clamp first) */ + BLI_assert(re->partx == min_ii(re->r.tilex, re->rectx)); + BLI_assert(re->party == min_ii(re->r.tiley, re->recty)); if (do_pano == FALSE) { return testclip(v); } + else { + /* to be used for halos en infos */ + float abs4; + short c = 0; - abs4= fabs(v[3]); + int xparts = (re->rectx + re->partx - 1) / re->partx; - if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ - else if (v[2]> abs4) c+= 32; + abs4= fabsf(v[3]); - if ( v[1]>abs4) c+=4; - else if ( v[1]< -abs4) c+=8; + if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ + else if (v[2]> abs4) c+= 32; - abs4*= xparts; - if ( v[0]>abs4) c+=2; - else if ( v[0]< -abs4) c+=1; + if ( v[1]>abs4) c+=4; + else if ( v[1]< -abs4) c+=8; - return c; + abs4*= xparts; + if ( v[0]>abs4) c+=2; + else if ( v[0]< -abs4) c+=1; + + return c; + } } /** diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index c37f48bc329..a7f6b40981d 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -637,7 +637,7 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar) maxtotvert= 0; for (obr=re->objecttable.first; obr; obr=obr->next) - maxtotvert= MAX2(obr->totvert, maxtotvert); + maxtotvert = max_ii(obr->totvert, maxtotvert); clipflag= MEM_callocN(sizeof(char)*maxtotvert, "autoclipflag"); diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 77602edf955..597196f464b 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -58,7 +58,9 @@ #include "shading.h" /* own include */ /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c index e4a42fcd675..e812b99287c 100644 --- a/source/blender/render/intern/source/sunsky.c +++ b/source/blender/render/intern/source/sunsky.c @@ -118,8 +118,8 @@ static void DirectionToThetaPhi(float *toSun, float *theta, float *phi) /** * PerezFunction: - * compute perez function value based on input paramters - * */ + * compute perez function value based on input parameters + */ static float PerezFunction(struct SunSky *sunsky, const float *lam, float theta, float gamma, float lvz) { float den, num; diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index b486407c61c..77d6644479a 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -157,10 +157,10 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) /* find the first valid ibuf and use it to initialize the resolution of the data set */ /* need to do this in advance so we know how much memory to allocate */ - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); while (!ibuf && (iuser.framenr < iuser.frames)) { iuser.framenr++; - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); } if (!ibuf) return; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); @@ -175,7 +175,8 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) /* get a new ibuf for each frame */ if (z > 0) { iuser.framenr++; - ibuf = BKE_image_get_ibuf(ima, &iuser); + BKE_image_release_ibuf(ima, ibuf, NULL); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (!ibuf) break; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); } @@ -191,7 +192,9 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) BKE_image_free_anim_ibufs(ima, iuser.framenr); } - + + BKE_image_release_ibuf(ima, ibuf, NULL); + vd->ok = 1; return; } @@ -265,7 +268,7 @@ static void init_frame_smoke(VoxelData *vd, float cfra) /* map velocities between 0 and 0.3f */ for (i = 0; i < totRes; i++) { - vd->dataset[i] = sqrt(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; + vd->dataset[i] = sqrtf(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; } } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 62bf9ac2005..c52fb84a7f8 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -77,7 +77,9 @@ #include "zbuf.h" /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index b9a4e720230..8d885bf6d6f 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -106,7 +106,7 @@ int WM_homefile_read_exec(struct bContext *C, struct wmOperator *op); int WM_homefile_read(struct bContext *C, struct ReportList *reports, short from_memory); int WM_homefile_write_exec(struct bContext *C, struct wmOperator *op); void WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports); -int WM_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports, int copy); +int WM_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports); void WM_autosave_init(struct wmWindowManager *wm); /* mouse cursors */ @@ -171,6 +171,7 @@ void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, str /* operator api, default callbacks */ /* invoke callback, uses enum property named "type" */ +int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_menu_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); /* invoke callback, confirm menu + exec */ @@ -181,6 +182,7 @@ int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const char imt /* poll callback, context checks */ int WM_operator_winactive (struct bContext *C); /* invoke callback, exec + redo popup */ +int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_operator_props_dialog_popup (struct bContext *C, struct wmOperator *op, int width, int height); int WM_operator_redo_popup (struct bContext *C, struct wmOperator *op); @@ -320,9 +322,9 @@ enum { WM_JOB_SUSPEND = (1 << 3) }; -/* identifying jobs by owner alone is unreliable, this isnt saved, order can change */ +/* identifying jobs by owner alone is unreliable, this isnt saved, order can change (keep 0 for 'any') */ enum { - WM_JOB_TYPE_ANY = -1, + WM_JOB_TYPE_ANY = 0, WM_JOB_TYPE_COMPOSITE, WM_JOB_TYPE_RENDER, WM_JOB_TYPE_RENDER_PREVIEW, /* UI preview */ @@ -359,8 +361,9 @@ void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *); void WM_jobs_stop(struct wmWindowManager *wm, void *owner, void *startjob); void WM_jobs_kill(struct wmWindowManager *wm, void *owner, void (*)(void *, short int *, short int *, float *)); void WM_jobs_kill_all(struct wmWindowManager *wm); - void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner); - +void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner); +void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type); + int WM_jobs_has_running(struct wmWindowManager *wm); /* clipboard */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 094df73bbd9..347f46c8166 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -300,6 +300,7 @@ typedef struct wmNotifier { /* NC_MATERIAL Material */ #define ND_SHADING (30<<16) #define ND_SHADING_DRAW (31<<16) +#define ND_SHADING_LINKS (32<<16) /* NC_LAMP Lamp */ #define ND_LIGHTING (40<<16) @@ -326,6 +327,7 @@ typedef struct wmNotifier { /* Mesh, Curve, MetaBall, Armature, .. */ #define ND_SELECT (90<<16) #define ND_DATA (91<<16) +#define ND_VERTEX_GROUP (92<<16) /* NC_NODE Nodes */ diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 66bb321e832..a92ed65392c 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -84,7 +84,7 @@ static void wm_paintcursor_draw(bContext *C, ARegion *ar) bScreen *screen = win->screen; wmPaintCursor *pc; - if (screen->subwinactive == ar->swinid) { + if (ar->swinid && screen->subwinactive == ar->swinid) { for (pc = wm->paintcursors.first; pc; pc = pc->next) { if (pc->poll == NULL || pc->poll(C)) { ARegion *ar_other = CTX_wm_region(C); @@ -631,7 +631,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) if (paintcursor && wm->paintcursors.first) { for (sa = screen->areabase.first; sa; sa = sa->next) { for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->swinid == screen->subwinactive) { + if (ar->swinid && ar->swinid == screen->subwinactive) { CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); @@ -711,12 +711,14 @@ static int wm_automatic_draw_method(wmWindow *win) if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) return USER_DRAW_OVERLAP; /* also Intel drivers are slow */ +#if 0 /* 2.64 BCon3 period, let's try if intel now works... */ else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_UNIX, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP; else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP_FLIP; else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP_FLIP; +#endif /* Windows software driver darkens color on each redraw */ else if (GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_WIN, GPU_DRIVER_SOFTWARE)) return USER_DRAW_OVERLAP_FLIP; @@ -751,6 +753,15 @@ void wm_draw_update(bContext *C) GPU_free_unused_buffers(); for (win = wm->windows.first; win; win = win->next) { + int state = GHOST_GetWindowState(win->ghostwin);; + + if (state == GHOST_kWindowStateMinimized) { + /* do not update minimized windows, it gives issues on intel drivers (see [#33223]) + * anyway, it seems logical to skip update for invisile windows + */ + continue; + } + if (win->drawmethod != U.wmdrawmethod) { wm_draw_window_clear(win); win->drawmethod = U.wmdrawmethod; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index fee94b95a6a..c0e3b19c716 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -135,6 +135,7 @@ static int wm_test_duplicate_notifier(wmWindowManager *wm, unsigned int type, vo /* XXX: in future, which notifiers to send to other windows? */ void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference) { + ARegion *ar; wmNotifier *note = MEM_callocN(sizeof(wmNotifier), "notifier"); note->wm = CTX_wm_manager(C); @@ -142,8 +143,9 @@ void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference note->window = CTX_wm_window(C); - if (CTX_wm_region(C)) - note->swinid = CTX_wm_region(C)->swinid; + ar = CTX_wm_region(C); + if (ar) + note->swinid = ar->swinid; note->category = type & NOTE_CATEGORY; note->data = type & NOTE_DATA; @@ -340,7 +342,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve int retval; /* UI code doesn't handle return values - it just always returns break. - to make the DBL_CLICK conversion work, we just don't send this to UI */ + * to make the DBL_CLICK conversion work, we just don't send this to UI */ if (event->val == KM_DBL_CLICK) return WM_HANDLER_CONTINUE; @@ -1279,74 +1281,6 @@ int WM_userdef_event_map(int kmitype) return kmitype; } -static void wm_eventemulation(wmEvent *event) -{ - /* Store last mmb event value to make emulation work when modifier keys are released first. */ - static int mmb_emulated = 0; /* this should be in a data structure somwhere */ - - /* middlemouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->alt) { - event->type = MIDDLEMOUSE; - event->alt = 0; - mmb_emulated = 1; - } - else if (event->val == KM_RELEASE) { - /* only send middle-mouse release if emulated */ - if (mmb_emulated) { - event->type = MIDDLEMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } - -#ifdef __APPLE__ - - /* rightmouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->oskey) { - event->type = RIGHTMOUSE; - event->oskey = 0; - mmb_emulated = 1; - } - else if (event->val == KM_RELEASE) { - if (mmb_emulated) { - event->oskey = RIGHTMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } -#endif - - /* numpad emulation */ - if (U.flag & USER_NONUMPAD) { - switch (event->type) { - case ZEROKEY: event->type = PAD0; break; - case ONEKEY: event->type = PAD1; break; - case TWOKEY: event->type = PAD2; break; - case THREEKEY: event->type = PAD3; break; - case FOURKEY: event->type = PAD4; break; - case FIVEKEY: event->type = PAD5; break; - case SIXKEY: event->type = PAD6; break; - case SEVENKEY: event->type = PAD7; break; - case EIGHTKEY: event->type = PAD8; break; - case NINEKEY: event->type = PAD9; break; - case MINUSKEY: event->type = PADMINUS; break; - case EQUALKEY: event->type = PADPLUSKEY; break; - case BACKSLASHKEY: event->type = PADSLASHKEY; break; - } - } -} static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) { @@ -1356,9 +1290,9 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) /* the matching rules */ if (kmitype == KM_TEXTINPUT) - if (winevent->val == KM_PRESS) { // prevent double clicks + if (winevent->val == KM_PRESS) { /* prevent double clicks */ /* NOT using ISTEXTINPUT anymore because (at least on Windows) some key codes above 255 - could have printable ascii keys - BUG [#30479] */ + * could have printable ascii keys - BUG [#30479] */ if (ISKEYBOARD(winevent->type) && (winevent->ascii || winevent->utf8_buf[0])) return 1; } @@ -1378,7 +1312,8 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if (kmi->oskey != KM_ANY) if (winevent->oskey != kmi->oskey && !(winevent->oskey & kmi->oskey)) return 0; - if (winevent->keymodifier != kmi->keymodifier) return 0; + if (kmi->keymodifier) + if (winevent->keymodifier != kmi->keymodifier) return 0; return 1; @@ -1618,8 +1553,8 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa if (handler->op->reports->list.first) { /* FIXME, temp setting window, this is really bad! - * only have because lib linking errors need to be seen by users :( - * it can be removed without breaking anything but then no linking errors - campbell */ + * only have because lib linking errors need to be seen by users :( + * it can be removed without breaking anything but then no linking errors - campbell */ wmWindow *win_prev = CTX_wm_window(C); ScrArea *area_prev = CTX_wm_area(C); ARegion *ar_prev = CTX_wm_region(C); @@ -2113,8 +2048,6 @@ void wm_event_do_handlers(bContext *C) } #endif - wm_eventemulation(event); - CTX_wm_window_set(C, win); /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ @@ -2616,6 +2549,75 @@ static int convert_key(GHOST_TKey key) } } +static void wm_eventemulation(wmEvent *event) +{ + /* Store last mmb event value to make emulation work when modifier keys are released first. */ + static int mmb_emulated = 0; /* this should be in a data structure somwhere */ + + /* middlemouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->alt) { + event->type = MIDDLEMOUSE; + event->alt = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + /* only send middle-mouse release if emulated */ + if (mmb_emulated) { + event->type = MIDDLEMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } + } + + } + +#ifdef __APPLE__ + + /* rightmouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->oskey) { + event->type = RIGHTMOUSE; + event->oskey = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + if (mmb_emulated) { + event->oskey = RIGHTMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } + } + + } +#endif + + /* numpad emulation */ + if (U.flag & USER_NONUMPAD) { + switch (event->type) { + case ZEROKEY: event->type = PAD0; break; + case ONEKEY: event->type = PAD1; break; + case TWOKEY: event->type = PAD2; break; + case THREEKEY: event->type = PAD3; break; + case FOURKEY: event->type = PAD4; break; + case FIVEKEY: event->type = PAD5; break; + case SIXKEY: event->type = PAD6; break; + case SEVENKEY: event->type = PAD7; break; + case EIGHTKEY: event->type = PAD8; break; + case NINEKEY: event->type = PAD9; break; + case MINUSKEY: event->type = PADMINUS; break; + case EQUALKEY: event->type = PADPLUSKEY; break; + case BACKSLASHKEY: event->type = PADSLASHKEY; break; + } + } +} + /* adds customdata to event */ static void update_tablet_data(wmWindow *win, wmEvent *event) { @@ -2731,47 +2733,45 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event = *evt; switch (type) { - /* mouse move */ + /* mouse move, also to inactive window (X11 does this) */ case GHOST_kEventCursorMove: { - if (win->active) { - GHOST_TEventCursorData *cd = customdata; - wmEvent *lastevent = win->queue.last; - int cx, cy; - - GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); - evt->x = cx; - evt->y = (win->sizey - 1) - cy; - - event.x = evt->x; - event.y = evt->y; + GHOST_TEventCursorData *cd = customdata; + wmEvent *lastevent = win->queue.last; + int cx, cy; + + GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); + evt->x = cx; + evt->y = (win->sizey - 1) - cy; + + event.x = evt->x; + event.y = evt->y; - event.type = MOUSEMOVE; + event.type = MOUSEMOVE; - /* some painting operators want accurate mouse events, they can - * handle in between mouse move moves, others can happily ignore - * them for better performance */ - if (lastevent && lastevent->type == MOUSEMOVE) - lastevent->type = INBETWEEN_MOUSEMOVE; + /* some painting operators want accurate mouse events, they can + * handle in between mouse move moves, others can happily ignore + * them for better performance */ + if (lastevent && lastevent->type == MOUSEMOVE) + lastevent->type = INBETWEEN_MOUSEMOVE; - update_tablet_data(win, &event); - wm_event_add(win, &event); + update_tablet_data(win, &event); + wm_event_add(win, &event); + + /* also add to other window if event is there, this makes overdraws disappear nicely */ + /* it remaps mousecoord to other window in event */ + owin = wm_event_cursor_other_windows(wm, win, &event); + if (owin) { + wmEvent oevent = *(owin->eventstate); - /* also add to other window if event is there, this makes overdraws disappear nicely */ - /* it remaps mousecoord to other window in event */ - owin = wm_event_cursor_other_windows(wm, win, &event); - if (owin) { - wmEvent oevent = *(owin->eventstate); - - oevent.x = owin->eventstate->x = event.x; - oevent.y = owin->eventstate->y = event.y; - oevent.type = MOUSEMOVE; - - update_tablet_data(owin, &oevent); - wm_event_add(owin, &oevent); - } + oevent.x = owin->eventstate->x = event.x; + oevent.y = owin->eventstate->y = event.y; + oevent.type = MOUSEMOVE; + update_tablet_data(owin, &oevent); + wm_event_add(owin, &oevent); } + break; } case GHOST_kEventTrackpad: @@ -2827,6 +2827,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U else event.type = MIDDLEMOUSE; + wm_eventemulation(&event); + /* copy previous state to prev event state (two old!) */ evt->prevval = evt->val; evt->prevtype = evt->type; @@ -2892,6 +2894,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/ event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; + wm_eventemulation(&event); + /* copy previous state to prev event state (two old!) */ evt->prevval = evt->val; evt->prevtype = evt->type; @@ -2980,9 +2984,13 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U if (event.keymodifier == UNKNOWNKEY) event.keymodifier = 0; - /* if test_break set, it catches this. XXX Keep global for now? */ - if (event.type == ESCKEY && event.val == KM_PRESS) + /* if test_break set, it catches this. Do not set with modifier presses. XXX Keep global for now? */ + if ((event.type == ESCKEY && event.val == KM_PRESS) && + /* check other modifiers because ms-windows uses these to bring up the task manager */ + (event.shift == 0 && event.ctrl == 0 && event.alt == 0)) + { G.is_break = TRUE; + } /* double click test - only for press */ if (event.val == KM_PRESS) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 6124b03778d..0e4af46d0fc 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -762,7 +762,7 @@ int write_crash_blend(void) } } -int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *reports, int copy) +int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *reports) { Library *li; int len; @@ -818,7 +818,7 @@ int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *re fileflags |= G_FILE_HISTORY; /* write file history */ if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) { - if (!copy) { + if (!(fileflags & G_FILE_SAVE_COPY)) { G.relbase_valid = 1; BLI_strncpy(G.main->name, filepath, sizeof(G.main->name)); /* is guaranteed current file */ diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index b3ffb80243a..a80386e9860 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -255,7 +255,7 @@ static void draw_filled_lasso(wmGesture *gt) if (sf_vert_first) { const float zvec[3] = {0.0f, 0.0f, 1.0f}; BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); - BLI_scanfill_calc_ex(&sf_ctx, FALSE, zvec); + BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES, zvec); glEnable(GL_BLEND); glColor4f(1.0, 1.0, 1.0, 0.05); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 42d721327b6..3c3e2c0feaa 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -131,31 +131,34 @@ struct wmJob { }; /* finds: - * 1st priority: job with same owner and name - * 2nd priority: job with same owner + * if type, compare for it, otherwise any matching job */ -static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const char *name) +static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const int job_type) { - wmJob *wm_job, *found = NULL; + wmJob *wm_job; for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) if (wm_job->owner == owner) { - found = wm_job; - if (name && strcmp(wm_job->name, name) == 0) + + if (job_type) { + if ( wm_job->job_type == job_type) + return wm_job; + } + else return wm_job; } - return found; + return NULL; } /* ******************* public API ***************** */ /* returns current or adds new job, but doesnt run it */ -/* every owner only gets a single job, adding a new one will stop running stop and +/* every owner only gets a single job, adding a new one will stop running job and * when stopped it starts the new one */ wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type) { - wmJob *wm_job = wm_job_find(wm, owner, name); + wmJob *wm_job = wm_job_find(wm, owner, job_type); if (wm_job == NULL) { wm_job = MEM_callocN(sizeof(wmJob), "new job"); @@ -167,7 +170,11 @@ wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char * wm_job->job_type = job_type; BLI_strncpy(wm_job->name, name, sizeof(wm_job->name)); } + /* else: a running job, be careful */ + /* prevent creating a job with an invalid type */ + BLI_assert(wm_job->job_type != WM_JOB_TYPE_ANY); + return wm_job; } @@ -192,7 +199,7 @@ int WM_jobs_test(wmWindowManager *wm, void *owner, int job_type) float WM_jobs_progress(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, NULL); + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); if (wm_job && wm_job->flag & WM_JOB_PROGRESS) return wm_job->progress; @@ -202,7 +209,7 @@ float WM_jobs_progress(wmWindowManager *wm, void *owner) char *WM_jobs_name(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, NULL); + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); if (wm_job) return wm_job->name; @@ -398,15 +405,29 @@ void WM_jobs_kill_all(wmWindowManager *wm) /* wait until every job ended, except for one owner (used in undo to keep screen job alive) */ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) { - wmJob *wm_job; + wmJob *wm_job, *next_job; - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { + next_job = wm_job->next; + if (wm_job->owner != owner) wm_jobs_kill_job(wm, wm_job); } } +void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type) +{ + wmJob *wm_job, *next_job; + + for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { + next_job = wm_job->next; + + if (wm_job->job_type == job_type) + wm_jobs_kill_job(wm, wm_job); + } +} + /* signal job(s) from this owner or callback to stop, timer is required to get handled */ void WM_jobs_stop(wmWindowManager *wm, void *owner, void *startjob) { diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 7aa2b403897..3739462ac2c 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -101,11 +101,8 @@ static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b) if (strcmp(a->idname, b->idname) != 0) return 0; - if (!((a->ptr == NULL && b->ptr == NULL) || - (a->ptr && b->ptr && IDP_EqualsProperties(a->ptr->data, b->ptr->data)))) - { + if (!RNA_struct_equals(a->ptr, b->ptr)) return 0; - } if ((a->flag & KMI_INACTIVE) != (b->flag & KMI_INACTIVE)) return 0; @@ -395,7 +392,7 @@ int WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) } BLI_freelinkN(&keymap->items, kmi); - WM_keyconfig_update_tag(keymap, kmi); + WM_keyconfig_update_tag(keymap, NULL); return TRUE; } else { @@ -545,7 +542,7 @@ static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKe /* copy new keymap from an existing one */ if (usermap && !(usermap->flag & KEYMAP_DIFF)) { - /* for compatibiltiy with old user preferences with non-diff + /* for compatibility with old user preferences with non-diff * keymaps we override the original entirely */ wmKeyMapItem *kmi, *orig_kmi; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 2ef33aa5964..8a0701b1063 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -72,6 +72,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" /* BKE_ST_MAXNAME */ +#include "BKE_utildefines.h" #include "BKE_idcode.h" @@ -86,6 +87,7 @@ #include "ED_screen.h" #include "ED_util.h" #include "ED_object.h" +#include "ED_view3d.h" #include "RNA_access.h" #include "RNA_define.h" @@ -623,7 +625,7 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context) /** set all props to their default, * \param do_update Only update un-initialized props. * - * \note, theres nothing spesific to operators here. + * \note, theres nothing specific to operators here. * this could be made a general function. */ int WM_operator_properties_default(PointerRNA *ptr, const int do_update) @@ -688,6 +690,35 @@ void WM_operator_properties_free(PointerRNA *ptr) /* ************ default op callbacks, exported *********** */ +int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *UNUSED(event)) +{ + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + + const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL); + + /* always run, so the values are initialized, + * otherwise we may get differ behavior when (dia != 1.0) */ + RNA_STRUCT_BEGIN(op->ptr, prop) + { + if (RNA_property_type(prop) == PROP_FLOAT) { + PropertySubType pstype = RNA_property_subtype(prop); + if (pstype == PROP_DISTANCE) { + /* we don't support arrays yet */ + BLI_assert(RNA_property_array_check(prop) == FALSE); + /* initialize */ + if (!RNA_property_is_set_ex(op->ptr, prop, FALSE)) { + const float value = RNA_property_float_get_default(op->ptr, prop) * dia; + RNA_property_float_set(op->ptr, prop, value); + } + } + } + } + RNA_STRUCT_END; + + return op->type->exec(C, op); +} + /* invoke callback, uses enum property named "type" */ int WM_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { @@ -792,7 +823,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op) uiButSetSearchFunc(but, operator_enum_search_cb, op->type, operator_enum_call_cb, NULL); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9 * UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL); uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ uiEndBlock(C, block); @@ -903,6 +934,8 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & BLENDERFILE), "Filter .blend files", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & BLENDERFILE_BACKUP), "Filter .blend files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "filter_image", (filter & IMAGEFILE), "Filter image files", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & MOVIEFILE), "Filter movie files", ""); @@ -1022,6 +1055,23 @@ wmOperator *WM_operator_last_redo(const bContext *C) return op; } +static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event)) +{ + wmOperator *op = arg_op; + + if (op == WM_operator_last_redo(C)) { + /* operator was already executed once? undo & repeat */ + ED_undo_operator_repeat(C, op); + } + else { + /* operator not executed yet, call it */ + ED_undo_push_op(C, op); + wm_operator_register(C, op); + + WM_operator_repeat(C, op); + } +} + static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) { wmOperator *op = arg_op; @@ -1029,7 +1079,6 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) uiLayout *layout; uiStyle *style = UI_GetStyle(); int width = 300; - block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockClearFlag(block, UI_BLOCK_LOOP); @@ -1039,11 +1088,12 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) * ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */ assert(op->type->flag & OPTYPE_REGISTER); - uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, arg_op); + uiBlockSetHandleFunc(block, wm_block_redo_cb, arg_op); layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, style); - if (!WM_operator_check_ui_enabled(C, op->type->name)) - uiLayoutSetEnabled(layout, FALSE); + if (op == WM_operator_last_redo(C)) + if (!WM_operator_check_ui_enabled(C, op->type->name)) + uiLayoutSetEnabled(layout, FALSE); if (op->type->flag & OPTYPE_MACRO) { for (op = op->macro.first; op; op = op->next) { @@ -1055,7 +1105,6 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); } - uiPopupBoundsBlock(block, 4, 0, 0); uiEndBlock(C, block); @@ -1183,6 +1232,8 @@ static void wm_operator_ui_popup_ok(struct bContext *C, void *arg, int retval) if (op && retval > 0) WM_operator_call(C, op); + + MEM_freeN(data); } int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) @@ -1196,24 +1247,45 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) return OPERATOR_RUNNING_MODAL; } -/* operator menu needs undo, for redo callback */ -int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +/** + * For use by #WM_operator_props_popup_call, #WM_operator_props_popup only. + * + * \note operator menu needs undo flag enabled , for redo callback */ +static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_call) { - if ((op->type->flag & OPTYPE_REGISTER) == 0) { BKE_reportf(op->reports, RPT_ERROR, "Operator '%s' does not have register enabled, incorrect invoke function", op->type->idname); return OPERATOR_CANCELLED; } - - ED_undo_push_op(C, op); - wm_operator_register(C, op); + + /* if we don't have global undo, we can't do undo push for automatic redo, + * so we require manual OK clicking in this popup */ + if (!(U.uiflag & USER_GLOBALUNDO)) + return WM_operator_props_dialog_popup(C, op, 300, UI_UNIT_Y); uiPupBlock(C, wm_block_create_redo, op); + if (do_call) + wm_block_redo_cb(C, op, 0); + return OPERATOR_RUNNING_MODAL; } +/* Same as WM_operator_props_popup but call the operator first, + * This way - the button values correspond to the result of the operator. + * Without this, first access to a button will make the result jump, + * see [#32452] */ +int WM_operator_props_popup_call(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + return wm_operator_props_popup_ex(C, op, TRUE); +} + +int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + return wm_operator_props_popup_ex(C, op, FALSE); +} + int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int height) { wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup"); @@ -1277,6 +1349,31 @@ static void WM_OT_debug_menu(wmOperatorType *ot) RNA_def_int(ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000); } +/* ***************** Operator defaults ************************* */ +static int wm_operator_defaults_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr = CTX_data_pointer_get_type(C, "active_operator", &RNA_Operator); + + if (!ptr.data) { + BKE_report(op->reports, RPT_ERROR, "No operator in context"); + return OPERATOR_CANCELLED; + } + + WM_operator_properties_reset((wmOperator *)ptr.data); + return OPERATOR_FINISHED; +} + +/* used by operator preset menu. pre-2.65 this was a 'Reset' button */ +static void WM_OT_operator_defaults(wmOperatorType *ot) +{ + ot->name = "Restore Defaults"; + ot->idname = "WM_OT_operator_defaults"; + ot->description = "Set the active operator to its default values"; + + ot->exec = wm_operator_defaults_exec; + + ot->flag = OPTYPE_INTERNAL; +} /* ***************** Splash Screen ************************* */ @@ -1332,6 +1429,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar int i; MenuType *mt = WM_menutype_find("USERPREF_MT_splash", TRUE); char url[96]; + char file [FILE_MAX]; #ifndef WITH_HEADLESS extern char datatoc_splash_png[]; @@ -1397,7 +1495,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar uiItemL(col, "Links", ICON_NONE); uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/blenderorg/blender-foundation/donation-payment"); uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/credits"); - uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-264"); + uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-265"); uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url", "http://wiki.blender.org/index.php/Doc:2.6/Manual"); uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org"); uiItemStringO(col, IFACE_("User Community"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/community/user-community"); @@ -1419,7 +1517,11 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar uiItemL(col, IFACE_("Recent"), ICON_NONE); for (recent = G.recent_files.first, i = 0; (i < 5) && (recent); recent = recent->next, i++) { - uiItemStringO(col, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath); + BLI_split_file_part(recent->filepath, file, sizeof(file)); + if (BLO_has_bfile_extension(file)) + uiItemStringO(col, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath); + else + uiItemStringO(col, BLI_path_basename(recent->filepath), ICON_FILE_BACKUP, "WM_OT_open_mainfile", "filepath", recent->filepath); } uiItemS(col); @@ -1451,49 +1553,6 @@ static void WM_OT_splash(wmOperatorType *ot) /* ***************** Search menu ************************* */ -static void operator_call_cb(struct bContext *C, void *UNUSED(arg1), void *arg2) -{ - wmOperatorType *ot = arg2; - - if (ot) - WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL); -} - -static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items) -{ - GHashIterator *iter = WM_operatortype_iter(); - - for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { - wmOperatorType *ot = BLI_ghashIterator_getValue(iter); - - if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) - continue; - - if (BLI_strcasestr(ot->name, str)) { - if (WM_operator_poll((bContext *)C, ot)) { - char name[256]; - int len = strlen(ot->name); - - /* display name for menu, can hold hotkey */ - BLI_strncpy(name, ot->name, sizeof(name)); - - /* check for hotkey */ - if (len < sizeof(name) - 6) { - if (WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, TRUE, - &name[len + 1], sizeof(name) - len - 1)) - { - name[len] = '|'; - } - } - - if (0 == uiSearchItemAdd(items, name, ot, 0)) - break; - } - } - } - BLI_ghashIterator_free(iter); -} - static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_op)) { static char search[256] = ""; @@ -1506,10 +1565,10 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_ uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, 9 * UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); - uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); + uiOperatorSearch_But(but); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9 * UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL); uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ uiEndBlock(C, block); @@ -2070,7 +2129,6 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) { char path[FILE_MAX]; int fileflags; - int copy = 0; save_set_compress(op); @@ -2080,29 +2138,27 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) BLI_strncpy(path, G.main->name, FILE_MAX); untitled(path); } - - if (RNA_struct_property_is_set(op->ptr, "copy")) - copy = RNA_boolean_get(op->ptr, "copy"); fileflags = G.fileflags; /* set compression flag */ - if (RNA_boolean_get(op->ptr, "compress")) fileflags |= G_FILE_COMPRESS; - else fileflags &= ~G_FILE_COMPRESS; - if (RNA_boolean_get(op->ptr, "relative_remap")) fileflags |= G_FILE_RELATIVE_REMAP; - else fileflags &= ~G_FILE_RELATIVE_REMAP; + BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "compress"), + G_FILE_COMPRESS); + BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "relative_remap"), + G_FILE_RELATIVE_REMAP); + BKE_BIT_TEST_SET(fileflags, + (RNA_struct_property_is_set(op->ptr, "copy") && + RNA_boolean_get(op->ptr, "copy")), + G_FILE_SAVE_COPY); + #ifdef USE_BMESH_SAVE_AS_COMPAT - /* property only exists for 'Save As' */ - if (RNA_struct_find_property(op->ptr, "use_mesh_compat")) { - if (RNA_boolean_get(op->ptr, "use_mesh_compat")) fileflags |= G_FILE_MESH_COMPAT; - else fileflags &= ~G_FILE_MESH_COMPAT; - } - else { - fileflags &= ~G_FILE_MESH_COMPAT; - } + BKE_BIT_TEST_SET(fileflags, + (RNA_struct_find_property(op->ptr, "use_mesh_compat") && + RNA_boolean_get(op->ptr, "use_mesh_compat")), + G_FILE_MESH_COMPAT); #endif - if (WM_file_write(C, path, fileflags, op->reports, copy) != 0) + if (WM_file_write(C, path, fileflags, op->reports) != 0) return OPERATOR_CANCELLED; WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL); @@ -3743,6 +3799,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_memory_statistics); WM_operatortype_append(WM_OT_dependency_relations); WM_operatortype_append(WM_OT_debug_menu); + WM_operatortype_append(WM_OT_operator_defaults); WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); WM_operatortype_append(WM_OT_call_menu); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 96bbedfee1b..8b387196da7 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -61,6 +61,7 @@ #include "BKE_blender.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -74,17 +75,19 @@ #include "WM_api.h" /* only for WM_main_playanim */ +struct PlayState; +static void playanim_window_zoom(const struct PlayState *ps, const float zoom_offset); + typedef struct PlayState { /* playback state */ short direction; - short next; + short next_frame; short once; short turbo; short pingpong; short noskip; short sstep; - short pause; short wait2; short stopped; short go; @@ -132,6 +135,7 @@ typedef enum eWS_Qual { WS_QUAL_ALT = (WS_QUAL_LALT | WS_QUAL_RALT), WS_QUAL_LCTRL = (1 << 4), WS_QUAL_RCTRL = (1 << 5), + WS_QUAL_CTRL = (WS_QUAL_LCTRL | WS_QUAL_RCTRL), WS_QUAL_LMOUSE = (1 << 16), WS_QUAL_MMOUSE = (1 << 17), WS_QUAL_RMOUSE = (1 << 18), @@ -179,27 +183,12 @@ static void playanim_event_qual_update(void) /* Alt */ GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftAlt, &val); - if (val) g_WS.qual |= WS_QUAL_LCTRL; - else g_WS.qual &= ~WS_QUAL_LCTRL; + if (val) g_WS.qual |= WS_QUAL_LALT; + else g_WS.qual &= ~WS_QUAL_LALT; GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightAlt, &val); - if (val) g_WS.qual |= WS_QUAL_RCTRL; - else g_WS.qual &= ~WS_QUAL_RCTRL; - - /* LMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskLeft, &val); - if (val) g_WS.qual |= WS_QUAL_LMOUSE; - else g_WS.qual &= ~WS_QUAL_LMOUSE; - - /* MMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskMiddle, &val); - if (val) g_WS.qual |= WS_QUAL_MMOUSE; - else g_WS.qual &= ~WS_QUAL_MMOUSE; - - /* RMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskRight, &val); - if (val) g_WS.qual |= WS_QUAL_RMOUSE; - else g_WS.qual &= ~WS_QUAL_RMOUSE; + if (val) g_WS.qual |= WS_QUAL_RALT; + else g_WS.qual &= ~WS_QUAL_RALT; } typedef struct PlayAnimPict { @@ -218,6 +207,21 @@ static int fromdisk = FALSE; static float zoomx = 1.0, zoomy = 1.0; static double ptottime = 0.0, swaptime = 0.04; +static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step) +{ + if (step > 0) { + while (step-- && playanim) { + playanim = playanim->next; + } + } + else if (step < 0) { + while (step++ && playanim) { + playanim = playanim->prev; + } + } + return playanim; +} + static int pupdate_time(void) { static double ltime; @@ -234,7 +238,7 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon { if (ibuf == NULL) { - printf("no ibuf !\n"); + printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : ""); return; } if (ibuf->rect == NULL && ibuf->rect_float) { @@ -432,6 +436,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->stopped = FALSE; } + if (ps->wait2) { + pupdate_time(); + ptottime = 0; + } + switch (type) { case GHOST_kEventKeyDown: case GHOST_kEventKeyUp: @@ -446,33 +455,42 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) case GHOST_kKeyP: if (val) ps->pingpong = !ps->pingpong; break; + case GHOST_kKey1: case GHOST_kKeyNumpad1: if (val) swaptime = ps->fstep / 60.0; break; + case GHOST_kKey2: case GHOST_kKeyNumpad2: if (val) swaptime = ps->fstep / 50.0; break; + case GHOST_kKey3: case GHOST_kKeyNumpad3: if (val) swaptime = ps->fstep / 30.0; break; + case GHOST_kKey4: case GHOST_kKeyNumpad4: if (g_WS.qual & WS_QUAL_SHIFT) swaptime = ps->fstep / 24.0; else swaptime = ps->fstep / 25.0; break; + case GHOST_kKey5: case GHOST_kKeyNumpad5: if (val) swaptime = ps->fstep / 20.0; break; + case GHOST_kKey6: case GHOST_kKeyNumpad6: if (val) swaptime = ps->fstep / 15.0; break; + case GHOST_kKey7: case GHOST_kKeyNumpad7: if (val) swaptime = ps->fstep / 12.0; break; + case GHOST_kKey8: case GHOST_kKeyNumpad8: if (val) swaptime = ps->fstep / 10.0; break; + case GHOST_kKey9: case GHOST_kKeyNumpad9: if (val) swaptime = ps->fstep / 6.0; break; @@ -482,10 +500,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { ps->picture = picsbase.first; - ps->next = 0; + ps->next_frame = 0; } else { - ps->next = -1; + ps->next_frame = -1; } } break; @@ -493,10 +511,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) if (val) { ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { - ps->next = ps->direction = -1; + ps->next_frame = ps->direction = -1; } else { - ps->next = -10; + ps->next_frame = -10; ps->sstep = TRUE; } } @@ -507,10 +525,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { ps->picture = picsbase.last; - ps->next = 0; + ps->next_frame = 0; } else { - ps->next = 1; + ps->next_frame = 1; } } break; @@ -518,10 +536,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) if (val) { ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { - ps->next = ps->direction = 1; + ps->next_frame = ps->direction = 1; } else { - ps->next = 10; + ps->next_frame = 10; ps->sstep = TRUE; } } @@ -532,35 +550,15 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) if (val) { if (g_WS.qual & WS_QUAL_SHIFT) { if (ps->curframe_ibuf) - printf(" Name: %s | Speed: %.2f frames/s\n", ps->curframe_ibuf->name, ps->fstep / swaptime); + printf(" Name: %s | Speed: %.2f frames/s\n", + ps->curframe_ibuf->name, ps->fstep / swaptime); } else { swaptime = ps->fstep / 5.0; } } break; - case GHOST_kKeyEqual: - if (val) { - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->pause++; - printf("pause:%d\n", ps->pause); - } - else { - swaptime /= 1.1; - } - } - break; - case GHOST_kKeyMinus: - if (val) { - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->pause--; - printf("pause:%d\n", ps->pause); - } - else { - swaptime *= 1.1; - } - } - break; + case GHOST_kKey0: case GHOST_kKeyNumpad0: if (val) { if (ps->once) { @@ -579,6 +577,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->wait2 = ps->sstep = FALSE; } break; + case GHOST_kKeyPeriod: case GHOST_kKeyNumpadPeriod: if (val) { if (ps->sstep) ps->wait2 = FALSE; @@ -588,29 +587,28 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } } break; + case GHOST_kKeyEqual: case GHOST_kKeyNumpadPlus: + { if (val == 0) break; - zoomx += 2.0f; - zoomy += 2.0f; - /* no break??? - is this intentional? - campbell XXX25 */ + if (g_WS.qual & WS_QUAL_CTRL) { + playanim_window_zoom(ps, 1.0f); + } + else { + swaptime /= 1.1; + } + break; + } + case GHOST_kKeyMinus: case GHOST_kKeyNumpadMinus: { - int sizex, sizey; - /* int ofsx, ofsy; */ /* UNUSED */ - if (val == 0) break; - if (zoomx > 1.0f) zoomx -= 1.0f; - if (zoomy > 1.0f) zoomy -= 1.0f; - // playanim_window_get_position(&ofsx, &ofsy); - playanim_window_get_size(&sizex, &sizey); - /* ofsx += sizex / 2; */ /* UNUSED */ - /* ofsy += sizey / 2; */ /* UNUSED */ - sizex = zoomx * ps->ibufx; - sizey = zoomy * ps->ibufy; - /* ofsx -= sizex / 2; */ /* UNUSED */ - /* ofsy -= sizey / 2; */ /* UNUSED */ - // window_set_position(g_WS.ghost_window,sizex,sizey); - GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); + if (g_WS.qual & WS_QUAL_CTRL) { + playanim_window_zoom(ps, -1.0f); + } + else { + swaptime *= 1.1; + } break; } case GHOST_kKeyEsc: @@ -621,6 +619,44 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } break; } + case GHOST_kEventButtonDown: + case GHOST_kEventButtonUp: + { + GHOST_TEventButtonData *bd = GHOST_GetEventData(evt); + int cx, cy, sizex, sizey, inside_window; + + GHOST_GetCursorPosition(g_WS.ghost_system, &cx, &cy); + GHOST_ScreenToClient(g_WS.ghost_window, cx, cy, &cx, &cy); + playanim_window_get_size(&sizex, &sizey); + + inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey); + + if (bd->button == GHOST_kButtonMaskLeft) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_LMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_LMOUSE; + } + else if (bd->button == GHOST_kButtonMaskMiddle) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_MMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_MMOUSE; + } + else if (bd->button == GHOST_kButtonMaskRight) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_RMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_RMOUSE; + } + break; + } case GHOST_kEventCursorMove: { if (g_WS.qual & WS_QUAL_LMOUSE) { @@ -648,10 +684,15 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } ps->sstep = TRUE; ps->wait2 = FALSE; - ps->next = 0; + ps->next_frame = 0; } break; } + case GHOST_kEventWindowActivate: + case GHOST_kEventWindowDeactivate: { + g_WS.qual &= ~WS_QUAL_MOUSE; + break; + } case GHOST_kEventWindowSize: case GHOST_kEventWindowMove: { @@ -716,6 +757,25 @@ static void playanim_window_open(const char *title, int posx, int posy, int size FALSE /* no stereo */, FALSE); } +static void playanim_window_zoom(const PlayState *ps, const float zoom_offset) +{ + int sizex, sizey; + /* int ofsx, ofsy; */ /* UNUSED */ + + if (zoomx + zoom_offset > 0.0f) zoomx += zoom_offset; + if (zoomy + zoom_offset > 0.0f) zoomy += zoom_offset; + + // playanim_window_get_position(&ofsx, &ofsy); + playanim_window_get_size(&sizex, &sizey); + /* ofsx += sizex / 2; */ /* UNUSED */ + /* ofsy += sizey / 2; */ /* UNUSED */ + sizex = zoomx * ps->ibufx; + sizey = zoomy * ps->ibufy; + /* ofsx -= sizex / 2; */ /* UNUSED */ + /* ofsy -= sizey / 2; */ /* UNUSED */ + // window_set_position(g_WS.ghost_window,sizex,sizey); + GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); +} void WM_main_playanim(int argc, const char **argv) { @@ -736,13 +796,12 @@ void WM_main_playanim(int argc, const char **argv) /* ps.doubleb = TRUE;*/ /* UNUSED */ ps.go = TRUE; ps.direction = TRUE; - ps.next = TRUE; + ps.next_frame = 1; ps.once = FALSE; ps.turbo = FALSE; ps.pingpong = FALSE; ps.noskip = FALSE; ps.sstep = FALSE; - ps.pause = FALSE; ps.wait2 = FALSE; ps.stopped = FALSE; ps.picture = NULL; @@ -939,6 +998,7 @@ void WM_main_playanim(int argc, const char **argv) if (ptottime > 0.0) ptottime = 0.0; while (ps.picture) { + int hasevent; #ifndef USE_IMB_CACHE if (ibuf != NULL && ibuf->ftype == 0) IMB_freeImBuf(ibuf); #endif @@ -989,22 +1049,25 @@ void WM_main_playanim(int argc, const char **argv) } } - ps.next = ps.direction; + ps.next_frame = ps.direction; - { - int hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0); + while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0) || ps.wait2 != 0)) { if (hasevent) { GHOST_DispatchEvents(g_WS.ghost_system); } - } - - /* XXX25 - we should not have to do this, but it makes scrubbing functional! */ - if (g_WS.qual & WS_QUAL_LMOUSE) { - ps.next = 0; - } - else { - ps.sstep = 0; + if (ps.wait2) { + if (hasevent) { + if (ibuf) { + while (pupdate_time()) PIL_sleep_ms(1); + ptottime -= swaptime; + playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep); + } + } + } + if (!ps.go) { + break; + } } ps.wait2 = ps.sstep; @@ -1015,15 +1078,10 @@ void WM_main_playanim(int argc, const char **argv) pupdate_time(); - if (ps.picture && ps.next) { + if (ps.picture && ps.next_frame) { /* always at least set one step */ while (ps.picture) { - if (ps.next < 0) { - ps.picture = ps.picture->prev; - } - else { - ps.picture = ps.picture->next; - } + ps.picture = playanim_step(ps.picture, ps.next_frame); if (ps.once && ps.picture != NULL) { if (ps.picture->next == NULL) { @@ -1038,12 +1096,7 @@ void WM_main_playanim(int argc, const char **argv) ptottime -= swaptime; } if (ps.picture == NULL && ps.sstep) { - if (ps.next < 0) { - ps.picture = picsbase.last; - } - else if (ps.next > 0) { - ps.picture = picsbase.first; - } + ps.picture = playanim_step(ps.picture, ps.next_frame); } } if (ps.go == FALSE) { @@ -1082,6 +1135,7 @@ void WM_main_playanim(int argc, const char **argv) /* we still miss freeing a lot!, * but many areas could skip initialization too for anim play */ IMB_exit(); + BKE_images_exit(); BLF_exit(); #endif GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 616567e8184..09f7e1692d9 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -333,8 +333,14 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) static void wm_window_add_ghostwindow(const char *title, wmWindow *win) { GHOST_WindowHandle ghostwin; + static int multisamples = -1; int scr_w, scr_h, posy; + /* force setting multisamples only once, it requires restart - and you cannot + * mix it, either all windows have it, or none (tested in OSX opengl) */ + if (multisamples == -1) + multisamples = U.ogl_multisamples; + wm_get_screensize(&scr_w, &scr_h); posy = (scr_h - win->posy - win->sizey); @@ -345,7 +351,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) (GHOST_TWindowState)win->windowstate, GHOST_kDrawingContextTypeOpenGL, 0 /* no stereo */, - 0 /* no AA */); + multisamples /* AA */); if (ghostwin) { /* needed so we can detect the graphics card below */ @@ -373,7 +379,6 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) /* standard state vars for window */ glEnable(GL_SCISSOR_TEST); - GPU_state_init(); } } @@ -749,6 +754,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr state = GHOST_GetWindowState(win->ghostwin); win->windowstate = state; + /* stop screencast if resize */ + if (type == GHOST_kEventWindowSize) { + WM_jobs_stop(CTX_wm_manager(C), win->screen, NULL); + } + /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index ca0e9659a22..4d3d6ef89d9 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -285,9 +285,9 @@ enum { /* for event checks */ /* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */ - /* UNUSED - see wm_eventmatch - BUG [#30479] -#define ISTEXTINPUT(event) (event >= ' ' && event <= 255) - */ + /* UNUSED - see wm_eventmatch - BUG [#30479] */ +// #define ISTEXTINPUT(event) (event >= ' ' && event <= 255) + /* test whether the event is a key on the keyboard */ #define ISKEYBOARD(event) (event >= ' ' && event <= 320) diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 828b7f5066c..85bb07d6e83 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -60,7 +60,7 @@ elseif(APPLE) add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c) # setup Info.plist execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) - set(PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) + set(PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blenderplayer.app) set(PLAYER_SOURCEINFO ${PLAYER_SOURCEDIR}/Contents/Info.plist) set_target_properties(blenderplayer PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PLAYER_SOURCEINFO} @@ -191,6 +191,10 @@ endif() list(APPEND BLENDER_SORTED_LIBS bf_intern_guardedalloc_cpp) endif() + if(WITH_INTERNATIONAL) + list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 5550cc69f89..5e38dad74ed 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -422,7 +422,7 @@ void uiTemplateEditModeSelection(struct uiLayout *layout, struct bContext *C) {} void uiTemplateTextureImage(struct uiLayout *layout, struct bContext *C, struct Tex *tex) {} void uiTemplateImage(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *userptr, int compact) {} void uiTemplateDopeSheetFilter(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr) {} -void uiTemplateColorWheel(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {} +void uiTemplateColorPicker(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {} void uiTemplateHistogram(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {} void uiTemplateReportsBanner(struct uiLayout *layout, struct bContext *C, struct wmOperator *op) {} void uiTemplateWaveform(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {} @@ -461,6 +461,8 @@ ListBase R_engines = {NULL, NULL}; void RE_engine_free(struct RenderEngine *engine) {} struct RenderEngineType *RE_engines_find(const char *idname) { return NULL; } void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used, float mem_peak) {}; +struct RenderEngine *RE_engine_create(struct RenderEngineType *type) { return NULL; }; +void RE_FreePersistentData(void) {} /* python */ struct wmOperatorType *WM_operatortype_find(const char *idname, int quiet) {return (struct wmOperatorType *) NULL;} diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index c06669c3ac2..b66c000ac89 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -469,30 +469,19 @@ elseif(WIN32) DESTINATION ${TARGETDIR} ) - if(WITH_INTERNATIONAL AND (NOT WITH_MINGW64)) - install( - FILES ${LIBDIR}/gettext/lib/gnu_gettext.dll - DESTINATION ${TARGETDIR} - ) - - if(NOT CMAKE_CL_64) - install( - FILES ${LIBDIR}/iconv/lib/iconv.dll - DESTINATION ${TARGETDIR} - ) - endif() - endif() - if(WITH_PYTHON) set_lib_path(PYLIB "python") + + STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) + install( - FILES ${PYLIB}/lib/python32.dll + FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}.dll DESTINATION ${TARGETDIR} CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel ) install( - FILES ${PYLIB}/lib/python32_d.dll + FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll DESTINATION ${TARGETDIR} CONFIGURATIONS Debug ) @@ -516,10 +505,10 @@ elseif(WIN32) " if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" STREQUAL \"Debug\") execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \"${TARGETDIR_VER}/python/lib\" - \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python32_d.tar.gz\") + \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_d.tar.gz\") else() execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \"${TARGETDIR_VER}/python/lib\" - \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python32.tar.gz\") + \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}.tar.gz\") endif() " ) @@ -527,10 +516,12 @@ elseif(WIN32) # doesnt work, todo # install(CODE "execute_process(COMMAND find ${TARGETDIR}/${BLENDER_VERSION}/python/lib/ -name '*.so' -exec strip -s {} '\;')") endif() + + unset(_PYTHON_VERSION_NO_DOTS) endif() if(CMAKE_CL_64) - # gettext and png are statically linked on win64 + # png is statically linked on win64 install( FILES ${LIBDIR}/zlib/lib/zlib.dll DESTINATION ${TARGETDIR} @@ -632,18 +623,7 @@ elseif(WIN32) install( # x86 builds can run on x64 Windows, so this is required at all times FILES ${LIBDIR}/thumbhandler/lib/BlendThumb64.dll DESTINATION ${TARGETDIR} - ) - - if(WITH_OPENIMAGEIO) - if(NOT MINGW) - set(OIIOBIN ${LIBDIR}/openimageio) - install( - FILES - ${OIIOBIN}/bin/OpenImageIO.dll - DESTINATION ${TARGETDIR} - ) - endif() - endif() + ) if(WITH_OPENCOLORIO) set(OCIOBIN ${LIBDIR}/opencolorio/bin) @@ -681,7 +661,7 @@ elseif(APPLE) ) endmacro() - set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blender.app) + set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blender.app) # setup Info.plist execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -740,7 +720,7 @@ elseif(APPLE) # install blenderplayer bundle - copy of blender.app above. re-using macros et al # note we are using OSX Bundle as base and copying Blender dummy bundle on top of it if(WITH_GAMEENGINE AND WITH_PLAYER) - set(OSX_APP_PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) + set(OSX_APP_PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blenderplayer.app) set(PLAYER_SOURCEINFO ${OSX_APP_PLAYER_SOURCEDIR}/Contents/Info.plist) set(PLAYER_TARGETDIR_VER ${TARGETDIR}/blenderplayer.app/Contents/MacOS/${BLENDER_VERSION}) @@ -987,6 +967,10 @@ endif() list_insert_after(BLENDER_SORTED_LIBS "cycles_kernel" "cycles_kernel_osl") endif() + if(WITH_INTERNATIONAL) + list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/creator/blender.map b/source/creator/blender.map new file mode 100644 index 00000000000..928d0c2d904 --- /dev/null +++ b/source/creator/blender.map @@ -0,0 +1,16 @@ + +/* on Linux we exclude LLVM symbols, they conflict with Mesa llvmpipe + * we also keep boost's symbols local, since some python modules could + * be using boost as well (mainly that's for lux render) + */ + +{ +global: + *; + *_boost*; +local: + *llvm*; + *LLVM*; + *boost*; +}; + diff --git a/source/creator/creator.c b/source/creator/creator.c index ca3deaf70a4..0f1207a9a88 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1077,7 +1077,9 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) "\n\t\t-p \tOpen with lower left corner at , " "\n\t\t-m\t\tRead from disk (Don't buffer)" "\n\t\t-f \t\tSpecify FPS to start with" - "\n\t\t-j \tSet frame step to "; + "\n\t\t-j \tSet frame step to " + "\n\t\t-s \tPlay from " + "\n\t\t-e \tPlay until "; static char game_doc[] = "Game Engine specific options" "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames" @@ -1270,6 +1272,7 @@ int main(int argc, const char **argv) initglobals(); /* blender.c */ IMB_init(); + BKE_images_init(); #ifdef WITH_FFMPEG IMB_ffmpeg_init(); diff --git a/source/creator/osx_locals.map b/source/creator/osx_locals.map new file mode 100644 index 00000000000..c3dd8b62792 --- /dev/null +++ b/source/creator/osx_locals.map @@ -0,0 +1,3 @@ +## The symbols will be treated as if they were marked as __private_extern__ +## (aka visibility=hidden) and will not be global in the output file +*boost* diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index 7c4c759e361..00836fa8ecb 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -95,35 +95,29 @@ static void DisableForText() { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts otherwise they render as wireframe */ - if (glIsEnabled(GL_BLEND)) glDisable(GL_BLEND); - if (glIsEnabled(GL_ALPHA_TEST)) glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); - if (glIsEnabled(GL_LIGHTING)) { - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - } + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); if (GLEW_ARB_multitexture) { for (int i=0; i KX_BEGINMOUSE && kxevent < KX_ENDMOUSEBUTTONS) { - if (val == KM_PRESS) + if (val == KM_PRESS || val == KM_DBL_CLICK) { m_eventStatusTables[m_currentTable][kxevent].m_eventval = val ; //??? diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp index 7cf895255ba..11e90e1797d 100644 --- a/source/gameengine/Converter/BL_ArmatureChannel.cpp +++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp @@ -95,7 +95,7 @@ BL_ArmatureChannel::~BL_ArmatureChannel() // PYTHON PyMethodDef BL_ArmatureChannel::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; // order of definition of attributes, must match Attributes[] array diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp index b8ad117a220..379be91b523 100644 --- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp +++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp @@ -246,7 +246,7 @@ void BL_ArmatureConstraint::SetSubtarget(KX_GameObject* subtarget) // PYTHON PyMethodDef BL_ArmatureConstraint::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; // order of definition of attributes, must match Attributes[] array diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index ed97b9ff73f..1f1c404efcb 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -639,7 +639,6 @@ PyTypeObject BL_ArmatureObject::Type = { }; PyMethodDef BL_ArmatureObject::Methods[] = { - KX_PYMETHODTABLE_NOARGS(BL_ArmatureObject, update), {NULL,NULL} //Sentinel }; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 58ae415e9d3..eb695e624e4 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -423,64 +423,55 @@ static void SetDefaultLightMode(Scene* scene) // -- -static void GetRGB(short type, - MFace* mface, - MCol* mmcol, - Material *mat, - unsigned int &c0, - unsigned int &c1, - unsigned int &c2, - unsigned int &c3) +static void GetRGB( + const bool use_mcol, + MFace *mface, + MCol *mmcol, + Material *mat, + unsigned int &c0, + unsigned int &c1, + unsigned int &c2, + unsigned int &c3) { unsigned int color = 0xFFFFFFFFL; - switch (type) { - case 0: // vertex colors - { - if (mmcol) { - c0 = KX_Mcol2uint_new(mmcol[0]); - c1 = KX_Mcol2uint_new(mmcol[1]); - c2 = KX_Mcol2uint_new(mmcol[2]); - if (mface->v4) - c3 = KX_Mcol2uint_new(mmcol[3]); - } - else { // backup white - c0 = KX_rgbaint2uint_new(color); - c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); - if (mface->v4) - c3 = KX_rgbaint2uint_new( color ); - } - } break; - - - case 1: // material rgba - { - if (mat) { - union { - unsigned char cp[4]; - unsigned int integer; - } col_converter; - col_converter.cp[3] = (unsigned char) (mat->r * 255.0f); - col_converter.cp[2] = (unsigned char) (mat->g * 255.0f); - col_converter.cp[1] = (unsigned char) (mat->b * 255.0f); - col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f); - color = col_converter.integer; - } + if (use_mcol) { + // vertex colors + + if (mmcol) { + c0 = KX_Mcol2uint_new(mmcol[0]); + c1 = KX_Mcol2uint_new(mmcol[1]); + c2 = KX_Mcol2uint_new(mmcol[2]); + if (mface->v4) + c3 = KX_Mcol2uint_new(mmcol[3]); + } + else { // backup white c0 = KX_rgbaint2uint_new(color); c1 = KX_rgbaint2uint_new(color); c2 = KX_rgbaint2uint_new(color); if (mface->v4) - c3 = KX_rgbaint2uint_new(color); - } break; - - default: // white - { - c0 = KX_rgbaint2uint_new(color); - c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); - if (mface->v4) - c3 = KX_rgbaint2uint_new(color); - } break; + c3 = KX_rgbaint2uint_new( color ); + } + } + else { + // material rgba + if (mat) { + union { + unsigned char cp[4]; + unsigned int integer; + } col_converter; + col_converter.cp[3] = (unsigned char) (mat->r * 255.0f); + col_converter.cp[2] = (unsigned char) (mat->g * 255.0f); + col_converter.cp[1] = (unsigned char) (mat->b * 255.0f); + col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f); + color = col_converter.integer; + } + // backup white is fallback + + c0 = KX_rgbaint2uint_new(color); + c1 = KX_rgbaint2uint_new(color); + c2 = KX_rgbaint2uint_new(color); + if (mface->v4) + c3 = KX_rgbaint2uint_new(color); } } @@ -489,6 +480,45 @@ typedef struct MTF_localLayer { const char *name; } MTF_localLayer; +static void tface_to_uv_bge(const MFace *mface, const MTFace *tface, MT_Point2 uv[4]) +{ + uv[0].setValue(tface->uv[0]); + uv[1].setValue(tface->uv[1]); + uv[2].setValue(tface->uv[2]); + if (mface->v4) { + uv[3].setValue(tface->uv[3]); + } +} + +static void GetUV( + MFace *mface, + MTFace *tface, + MTF_localLayer *layers, + const int layer_uv[2], + MT_Point2 uv[4], + MT_Point2 uv2[4]) +{ + bool validface = (tface != NULL); + + uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f); + + /* No material, what to do? let's see what is in the UV and set the material accordingly + * light and visible is always on */ + if (layer_uv[0] != -1) { + tface_to_uv_bge(mface, layers[layer_uv[0]].face, uv); + if (layer_uv[1] != -1) { + tface_to_uv_bge(mface, layers[layer_uv[1]].face, uv2); + } + } + else if (validface) { + tface_to_uv_bge(mface, tface, uv); + } + else { + // nothing at all + uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f); + } +} + // ------------------------------------ static bool ConvertMaterial( BL_Material *material, @@ -496,30 +526,25 @@ static bool ConvertMaterial( MTFace* tface, const char *tfaceName, MFace* mface, - MCol* mmcol, + MCol* mmcol, /* only for text, use first mcol, weak */ MTF_localLayer *layers, - bool glslmat) + int layer_uv[2], + const bool glslmat) { material->Initialize(); int numchan = -1, texalpha = 0; bool validmat = (mat!=0); bool validface = (tface!=0); - short type = 0; - if ( validmat ) - type = 1; // material color - material->IdMode = DEFAULT_BLENDER; material->glslmat = (validmat)? glslmat: false; material->materialindex = mface->mat_nr; + /* default value for being unset */ + layer_uv[0] = layer_uv[1] = -1; + // -------------------------------- if (validmat) { - - // use vertex colors by explicitly setting - if (mat->mode &MA_VERTEXCOLP || glslmat) - type = 0; - // use lighting? material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT; material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED; @@ -772,33 +797,19 @@ static bool ConvertMaterial( // No material - old default TexFace properties material->ras_mode |= USE_LIGHT; } - MT_Point2 uv[4]; - MT_Point2 uv2[4]; - const char *uvName = "", *uv2Name = ""; - - uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f); + const char *uvName = "", *uv2Name = ""; /* No material, what to do? let's see what is in the UV and set the material accordingly * light and visible is always on */ if ( validface ) { material->tile = tface->tile; - - uv[0].setValue(tface->uv[0]); - uv[1].setValue(tface->uv[1]); - uv[2].setValue(tface->uv[2]); - - if (mface->v4) - uv[3].setValue(tface->uv[3]); - uvName = tfaceName; } else { // nothing at all material->alphablend = GEMAT_SOLID; material->tile = 0; - - uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f); } if (validmat && validface) { @@ -816,49 +827,30 @@ static bool ConvertMaterial( } // get uv sets - if (validmat) - { + if (validmat) { bool isFirstSet = true; // only two sets implemented, but any of the eight // sets can make up the two layers - for (int vind = 0; vindnum_enabled; vind++) - { + for (int vind = 0; vindnum_enabled; vind++) { BL_Mapping &map = material->mapping[vind]; - if (map.uvCoName.IsEmpty()) + if (map.uvCoName.IsEmpty()) { isFirstSet = false; - else - { - for (int lay=0; layuv[0]); - uvSet[1].setValue(layer.face->uv[1]); - uvSet[2].setValue(layer.face->uv[2]); - - if (mface->v4) - uvSet[3].setValue(layer.face->uv[3]); - else - uvSet[3].setValue(0.0f, 0.0f); - - if (isFirstSet) - { - uv[0] = uvSet[0]; uv[1] = uvSet[1]; - uv[2] = uvSet[2]; uv[3] = uvSet[3]; + if (strcmp(map.uvCoName.ReadPtr(), layer.name)==0) { + if (isFirstSet) { + layer_uv[0] = lay; isFirstSet = false; uvName = layer.name; } - else if (strcmp(layer.name, uvName) != 0) - { - uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; - uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; + else if (strcmp(layer.name, uvName) != 0) { + layer_uv[1] = lay; map.mapping |= USECUSTOMUV; uv2Name = layer.name; } @@ -868,21 +860,11 @@ static bool ConvertMaterial( } } - unsigned int rgb[4]; - GetRGB(type,mface,mmcol,mat,rgb[0],rgb[1],rgb[2], rgb[3]); - - // swap the material color, so MCol on bitmap font works - if (validmat && type==1 && (mat->game.flag & GEMAT_TEXT)) - { - rgb[0] = KX_rgbaint2uint_new(rgb[0]); - rgb[1] = KX_rgbaint2uint_new(rgb[1]); - rgb[2] = KX_rgbaint2uint_new(rgb[2]); - rgb[3] = KX_rgbaint2uint_new(rgb[3]); + if (validmat && mmcol) { /* color is only for text */ + material->m_mcol = *(unsigned int *)mmcol; } - - material->SetConversionRGB(rgb); - material->SetConversionUV(uvName, uv); - material->SetConversionUV2(uv2Name, uv2); + material->SetUVLayerName(uvName); + material->SetUVLayerName2(uv2Name); if (validmat) material->matname =(mat->id.name); @@ -928,6 +910,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, // Extract avaiable layers MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; + int layer_uv[2]; /* store uv1, uv2 layers */ for (int lay=0; layGetMaterials()) { + const bool is_bl_mat_new = (bl_mat == NULL); + //const bool is_kx_blmat_new = (kx_blmat == NULL); + const bool glslmat = converter->GetGLSLMaterials(); + const bool use_mcol = ma ? (ma->mode & MA_VERTEXCOLP || glslmat) : true; /* do Blender Multitexture and Blender GLSL materials */ - unsigned int rgb[4]; - MT_Point2 uv[4]; + MT_Point2 uv_1[4]; + MT_Point2 uv_2[4]; /* first is the BL_Material */ - if (!bl_mat) + if (!bl_mat) { bl_mat = new BL_Material(); - ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, - layers, converter->GetGLSLMaterials()); + } - /* vertex colors and uv's were stored in bl_mat temporarily */ - bl_mat->GetConversionRGB(rgb); - rgb0 = rgb[0]; rgb1 = rgb[1]; - rgb2 = rgb[2]; rgb3 = rgb[3]; + /* only */ + if (is_bl_mat_new || (bl_mat->material != ma)) { + ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, + layers, layer_uv, glslmat); + } - bl_mat->GetConversionUV(uv); - uv0 = uv[0]; uv1 = uv[1]; - uv2 = uv[2]; uv3 = uv[3]; + /* vertex colors and uv's from the faces */ + GetRGB(use_mcol, mface, mcol, ma, rgb0, rgb1, rgb2, rgb3); + GetUV(mface, tface, layers, layer_uv, uv_1, uv_2); - bl_mat->GetConversionUV2(uv); - uv20 = uv[0]; uv21 = uv[1]; - uv22 = uv[2]; uv23 = uv[3]; + uv0 = uv_1[0]; uv1 = uv_1[1]; + uv2 = uv_1[2]; uv3 = uv_1[3]; + + uv20 = uv_2[0]; uv21 = uv_2[1]; + uv22 = uv_2[2]; uv23 = uv_2[3]; /* then the KX_BlenderMaterial */ if (kx_blmat == NULL) kx_blmat = new KX_BlenderMaterial(); - kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL)); + //if (is_kx_blmat_new || !kx_blmat->IsMaterial(bl_mat)) { + kx_blmat->Initialize(scene, bl_mat, (ma ? &ma->game : NULL)); + //} + polymat = static_cast(kx_blmat); } else { diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 30a4209965e..d1684db0f5a 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -103,6 +103,7 @@ extern "C" #include "KX_MeshProxy.h" #include "RAS_MeshObject.h" extern "C" { + #include "PIL_time.h" #include "BKE_context.h" #include "BLO_readfile.h" #include "BKE_idcode.h" @@ -957,10 +958,12 @@ static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const c bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) { Main *main_newlib; /* stored as a dynamic 'main' until we free it */ - int idcode= BKE_idcode_from_name(group); + const int idcode = BKE_idcode_from_name(group); ReportList reports; static char err_local[255]; - + +// TIMEIT_START(bge_link_blend_file); + /* only scene and mesh supported right now */ if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); @@ -1059,7 +1062,9 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha } } } - + +// TIMEIT_END(bge_link_blend_file); + return true; } diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index bfd44dc90fc..b9c70910283 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -11,7 +11,7 @@ incs += ' #source/gameengine/BlenderRoutines #source/blender/imbuf' incs += ' #intern/moto/include #source/gameengine/Ketsji #source/gameengine/Ketsji/KXNetwork' incs += ' #source/blender/blenlib #source/blender/blenkernel #source/blender' incs += ' #source/blender/editors/include #source/blender/makesdna #source/gameengine/Rasterizer' -incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #source/gameengine/GameLogic' +incs += ' #source/gameengine/GameLogic' incs += ' #source/gameengine/Expressions #source/gameengine/Network #source/gameengine/SceneGraph' incs += ' #source/gameengine/Physics/common #source/gameengine/Physics/Bullet' incs += ' #source/gameengine/Physics/Dummy' diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp index cb6bc556bab..2cacea98467 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/IntValue.cpp @@ -286,7 +286,7 @@ cInt CIntValue::GetInt() double CIntValue::GetNumber() { - return (float) m_int; + return (double) m_int; } @@ -323,9 +323,6 @@ void CIntValue::SetValue(CValue* newval) #ifdef WITH_PYTHON PyObject *CIntValue::ConvertValueToPython() { - if ((m_int > INT_MIN) && (m_int < INT_MAX)) - return PyLong_FromSsize_t(m_int); - else - return PyLong_FromLongLong(m_int); + return PyLong_FromLongLong(m_int); } #endif // WITH_PYTHON diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 8cff5a01c0e..5f97b03fed4 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -365,7 +365,7 @@ static PyObject *listvalue_mapping_subscript(PyObject *self, PyObject *key) } } else if (PyIndex_Check(key)) { - int index = PyLong_AsSsize_t(key); + Py_ssize_t index = PyLong_AsSsize_t(key); return listvalue_buffer_item(self, index); /* wont add a ref */ } else if (PySlice_Check(key)) { @@ -602,10 +602,10 @@ PyObject *CListValue::Pyindex(PyObject *value) int numelem = GetCount(); for (int i=0;iRelease(); - return PyLong_FromSsize_t(numfound); + return PyLong_FromLong(numfound); } /* Matches python dict.get(key, [default]) */ diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index bb1d0a31c1f..11b00b7bbf5 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -259,7 +259,7 @@ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods ------------------------------*/ PyMethodDef PyObjectPlus::Methods[] = { - {NULL, NULL} /* Sentinel */ + {NULL, NULL} /* Sentinel */ }; #define BGE_PY_ATTR_INVALID (&(PyObjectPlus::Attributes[0])) @@ -311,14 +311,14 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * { bool *val = reinterpret_cast(ptr); ptr += sizeof(bool); - PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); + PyList_SET_ITEM(resultlist,i,PyBool_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast(ptr); ptr += sizeof(short int); - PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_ENUM: @@ -333,7 +333,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * { int *val = reinterpret_cast(ptr); ptr += sizeof(int); - PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_FLOAT: @@ -381,17 +381,17 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * } if (attrdef->m_imax) bval = !bval; - return PyLong_FromSsize_t(bval); + return PyBool_FromLong(bval); } case KX_PYATTRIBUTE_TYPE_BOOL: { bool *val = reinterpret_cast(ptr); - return PyLong_FromSsize_t(*val); + return PyBool_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast(ptr); - return PyLong_FromSsize_t(*val); + return PyLong_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_ENUM: // enum are like int, just make sure the field size is the same @@ -403,7 +403,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast(ptr); - return PyLong_FromSsize_t(*val); + return PyLong_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_FLOAT: { @@ -486,8 +486,8 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * static bool py_check_attr_float(float *var, PyObject *value, const PyAttributeDef *attrdef) { - double val = PyFloat_AsDouble(value); - if (val == -1.0 && PyErr_Occurred()) + float val = PyFloat_AsDouble(value); + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name); return false; @@ -583,7 +583,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt ptr += sizeof(bool); if (PyLong_Check(item)) { - *var = (PyLong_AsSsize_t(item) != 0); + *var = (PyLong_AsLong(item) != 0); } else if (PyBool_Check(item)) { @@ -602,7 +602,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt ptr += sizeof(short int); if (PyLong_Check(item)) { - long val = PyLong_AsSsize_t(item); + int val = PyLong_AsLong(item); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -638,7 +638,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt ptr += sizeof(int); if (PyLong_Check(item)) { - long val = PyLong_AsSsize_t(item); + int val = PyLong_AsLong(item); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -664,13 +664,13 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt { float *var = reinterpret_cast(ptr); ptr += sizeof(float); - double val = PyFloat_AsDouble(item); - if (val == -1.0 && PyErr_Occurred()) + float val = PyFloat_AsDouble(item); + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name); goto UNDO_AND_ERROR; } - else if (attrdef->m_clamp) + else if (attrdef->m_clamp) { if (val < attrdef->m_fmin) val = attrdef->m_fmin; @@ -786,7 +786,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt bool *var = reinterpret_cast(ptr); if (PyLong_Check(value)) { - *var = (PyLong_AsSsize_t(value) != 0); + *var = (PyLong_AsLong(value) != 0); } else if (PyBool_Check(value)) { @@ -804,7 +804,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt bool bval; if (PyLong_Check(value)) { - bval = (PyLong_AsSsize_t(value) != 0); + bval = (PyLong_AsLong(value) != 0); } else if (PyBool_Check(value)) { @@ -847,7 +847,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt short int *var = reinterpret_cast(ptr); if (PyLong_Check(value)) { - long val = PyLong_AsSsize_t(value); + int val = PyLong_AsLong(value); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -882,7 +882,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt int *var = reinterpret_cast(ptr); if (PyLong_Check(value)) { - long val = PyLong_AsSsize_t(value); + int val = PyLong_AsLong(value); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -985,10 +985,10 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt for (int i=0; i<3; i++) { item = PySequence_GetItem(value, i); /* new ref */ - double val = PyFloat_AsDouble(item); + float val = PyFloat_AsDouble(item); Py_DECREF(item); item = NULL; - if (val == -1.0 && PyErr_Occurred()) + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name); goto RESTORE_AND_ERROR; diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 83b7c8c8771..37e26e88750 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -526,7 +526,7 @@ typedef struct KX_PYATTRIBUTE_DEF { /*------------------------------ * PyObjectPlus -------------------------------*/ + *------------------------------ */ typedef PyTypeObject *PyParentObject; /* Define the PyParent Object */ #else // WITH_PYTHON diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index 57f7dd64287..f922e617367 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -241,7 +241,7 @@ PyAttributeDef SCA_IController::Attributes[] = { PyObject *SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_IController* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_statemask); + return PyLong_FromLong(self->m_statemask); } PyObject *SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index ab0e6c5edcb..34fa1c98a73 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -202,7 +202,7 @@ PyTypeObject SCA_ILogicBrick::Type = { }; PyMethodDef SCA_ILogicBrick::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; PyAttributeDef SCA_ILogicBrick::Attributes[] = { @@ -256,7 +256,7 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg) PyObject *SCA_ILogicBrick::BoolToPyArg(bool boolarg) { - return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE); + return PyLong_FromLong(boolarg ? KX_TRUE: KX_FALSE); } #endif // WITH_PYTHON diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index bfb78abef04..1cb17af8325 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -383,16 +383,16 @@ PyAttributeDef SCA_ISensor::Attributes[] = { PyObject *SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self = static_cast(self_v); - int retval = 0; + bool retval = false; if (SCA_PythonController::m_sCurrentController) retval = SCA_PythonController::m_sCurrentController->IsTriggered(self); - return PyLong_FromSsize_t(retval); + return PyBool_FromLong(retval); } PyObject *SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self = static_cast(self_v); - return PyLong_FromSsize_t(self->GetState()); + return PyBool_FromLong(self->GetState()); } PyObject *SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -414,7 +414,7 @@ PyObject *SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF { status = 3; } - return PyLong_FromSsize_t(status); + return PyLong_FromLong(status); } PyObject *SCA_ISensor::pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 0c4dcae16f7..c7e31f75306 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -319,7 +319,7 @@ PyObject *SCA_JoystickSensor::PyGetButtonActiveList( ) if (joy) { for (i=0; i < joy->GetNumberOfButtons(); i++) { if (joy->aButtonPressIsPositive(i)) { - value = PyLong_FromSsize_t(i); + value = PyLong_FromLong(i); PyList_Append(ls, value); Py_DECREF(value); } @@ -355,7 +355,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYAT PyObject *list= PyList_New(axis_index); while (axis_index--) { - PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index))); + PyList_SET_ITEM(list, axis_index, PyLong_FromLong(joy->GetAxisPosition(axis_index))); } return list; @@ -371,7 +371,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT return NULL; } - return PyLong_FromSsize_t(joy->GetAxisPosition(self->m_axis-1)); + return PyLong_FromLong(joy->GetAxisPosition(self->m_axis-1)); } PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -383,7 +383,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATT PyObject *list= PyList_New(hat_index); while (hat_index--) { - PyList_SET_ITEM(list, hat_index, PyLong_FromSsize_t(joy->GetHat(hat_index))); + PyList_SET_ITEM(list, hat_index, PyLong_FromLong(joy->GetHat(hat_index))); } return list; @@ -394,28 +394,28 @@ PyObject *SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATT SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromSsize_t(joy->GetHat(self->m_hat-1)); + return PyLong_FromLong(joy->GetHat(self->m_hat-1)); } PyObject *SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 ); + return PyLong_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); } PyObject *SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 ); + return PyLong_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); } PyObject *SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 ); + return PyLong_FromLong( joy ? joy->GetNumberOfHats() : 0 ); } PyObject *SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index b3346270b61..7005ea1ba5b 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -439,17 +439,18 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, return NULL; } - int keycode = PyLong_AsSsize_t(value); + SCA_IInputDevice::KX_EnumInputs keycode = (SCA_IInputDevice::KX_EnumInputs)PyLong_AsLong(value); - if ((keycode < SCA_IInputDevice::KX_BEGINKEY) - || (keycode > SCA_IInputDevice::KX_ENDKEY)) { + if ((keycode < SCA_IInputDevice::KX_BEGINKEY) || + (keycode > SCA_IInputDevice::KX_ENDKEY)) + { PyErr_SetString(PyExc_AttributeError, "sensor.getKeyStatus(int): Keyboard Sensor, invalid keycode specified!"); return NULL; } SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice(); - const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode); - return PyLong_FromSsize_t(inevent.m_status); + const SCA_InputEvent & inevent = inputdev->GetEventValue(keycode); + return PyLong_FromLong(inevent.m_status); } /* ------------------------------------------------------------------------- */ @@ -509,8 +510,8 @@ PyObject *SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) { PyObject *keypair = PyList_New(2); - PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); - PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); + PyList_SET_ITEM(keypair,0,PyLong_FromLong(i)); + PyList_SET_ITEM(keypair,1,PyLong_FromLong(inevent.m_status)); PyList_Append(resultlist,keypair); } } diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 51e0bc6550b..a7cf4963f04 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -250,17 +250,18 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, { if (PyLong_Check(value)) { - int button = PyLong_AsSsize_t(value); + SCA_IInputDevice::KX_EnumInputs button = (SCA_IInputDevice::KX_EnumInputs)PyLong_AsLong(value); - if ((button < SCA_IInputDevice::KX_LEFTMOUSE) - || (button > SCA_IInputDevice::KX_RIGHTMOUSE)) { + if ((button < SCA_IInputDevice::KX_LEFTMOUSE) || + (button > SCA_IInputDevice::KX_RIGHTMOUSE)) + { PyErr_SetString(PyExc_ValueError, "sensor.getButtonStatus(int): Mouse Sensor, invalid button specified!"); return NULL; } SCA_IInputDevice* mousedev = ((SCA_MouseManager *)m_eventmgr)->GetInputDevice(); - const SCA_InputEvent& event = mousedev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) button); - return PyLong_FromSsize_t(event.m_status); + const SCA_InputEvent& event = mousedev->GetEventValue(button); + return PyLong_FromLong(event.m_status); } Py_RETURN_NONE; diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 5dd4cc501ca..f02ac495233 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -126,7 +126,6 @@ bool SCA_PropertySensor::Evaluate() bool SCA_PropertySensor::CheckPropertyCondition() { - m_recentresult=false; bool result=false; bool reverse = false; @@ -153,13 +152,11 @@ bool SCA_PropertySensor::CheckPropertyCondition() */ if (result==false && dynamic_cast(orgprop) != NULL) { float f; - - if (EOF == sscanf(m_checkpropval.ReadPtr(), "%f", &f)) - { - //error + if (sscanf(m_checkpropval.ReadPtr(), "%f", &f) == 1) { + result = (f == ((CFloatValue *)orgprop)->GetFloat()); } else { - result = (f == ((CFloatValue *)orgprop)->GetFloat()); + /* error */ } } /* end patch */ @@ -174,7 +171,7 @@ bool SCA_PropertySensor::CheckPropertyCondition() case KX_PROPSENSOR_EXPRESSION: { - /* +#if 0 if (m_rightexpr) { CValue* resultval = m_rightexpr->Calculate(); @@ -189,7 +186,7 @@ bool SCA_PropertySensor::CheckPropertyCondition() result = resultval->GetNumber() != 0; } } - */ +#endif break; } case KX_PROPSENSOR_INTERVAL: @@ -197,7 +194,16 @@ bool SCA_PropertySensor::CheckPropertyCondition() CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { - float val = orgprop->GetText().ToFloat(), min = m_checkpropval.ToFloat(), max = m_checkpropmaxval.ToFloat(); + const float min = m_checkpropval.ToFloat(); + const float max = m_checkpropmaxval.ToFloat(); + float val; + + if (dynamic_cast(orgprop) == NULL) { + val = orgprop->GetNumber(); + } + else { + val = orgprop->GetText().ToFloat(); + } result = (min <= val) && (val <= max); } diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index ece9d7b6c8f..c2b1470ae7a 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -168,12 +168,16 @@ void SCA_PythonController::SetNamespace(PyObject* pythondictionary) } #endif -int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) +bool SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) { if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) != m_triggeredSensors.end()) - return 1; - return 0; + { + return true; + } + else { + return false; + } } #ifdef WITH_PYTHON diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index f1f10d22711..d2549318c2e 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -90,7 +90,7 @@ class SCA_PythonController : public SCA_IController void SetDebug(bool debug) { m_debug = debug; } void AddTriggeredSensor(class SCA_ISensor* sensor) { m_triggeredSensors.push_back(sensor); } - int IsTriggered(class SCA_ISensor* sensor); + bool IsTriggered(class SCA_ISensor* sensor); bool Compile(); bool Import(); void ErrorPrint(const char *error_msg); diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp index 42cda9433b8..19aae46f2a3 100644 --- a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp +++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp @@ -117,7 +117,7 @@ PyObject *SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBU { const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); - PyDict_SetItem(self->m_event_dict, PyLong_FromSsize_t(i), PyLong_FromSsize_t(inevent.m_status)); + PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); } Py_INCREF(self->m_event_dict); return self->m_event_dict; @@ -134,7 +134,7 @@ PyObject *SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PY const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) - PyDict_SetItem(self->m_event_dict, PyLong_FromSsize_t(i), PyLong_FromSsize_t(inevent.m_status)); + PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); } Py_INCREF(self->m_event_dict); return self->m_event_dict; diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.cpp b/source/gameengine/GameLogic/SCA_PythonMouse.cpp index 0806bda072b..1617f714113 100644 --- a/source/gameengine/GameLogic/SCA_PythonMouse.cpp +++ b/source/gameengine/GameLogic/SCA_PythonMouse.cpp @@ -100,7 +100,7 @@ PyObject *SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_ { const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); - PyDict_SetItem(self->m_event_dict, PyLong_FromSsize_t(i), PyLong_FromSsize_t(inevent.m_status)); + PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); } Py_INCREF(self->m_event_dict); return self->m_event_dict; @@ -117,7 +117,7 @@ PyObject *SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATT const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) - PyDict_SetItem(self->m_event_dict, PyLong_FromSsize_t(i), PyLong_FromSsize_t(inevent.m_status)); + PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); } Py_INCREF(self->m_event_dict); return self->m_event_dict; diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 2d51a45fe55..5568072abcf 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -220,11 +220,11 @@ bool SCA_RandomActuator::Update() * this will be quite sufficient here. */ do { - x = 2.0 * m_base->DrawFloat() - 1.0; - y = 2.0 * m_base->DrawFloat() - 1.0; - s = x*x + y*y; - } while ( (s >= 1.0) || (s == 0.0) ); - t = x * sqrt( (-2.0 * log(s)) / s); + x = 2.0f * m_base->DrawFloat() - 1.0f; + y = 2.0f * m_base->DrawFloat() - 1.0f; + s = x * x + y * y; + } while ((s >= 1.0f) || (s == 0.0f)); + t = x * sqrtf((-2.0 * log(s)) / s); tmpval = new CFloatValue(m_parameter1 + m_parameter2 * t); } } @@ -363,17 +363,17 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = { PyObject *SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomActuator* act = static_cast(self); - return PyLong_FromSsize_t(act->m_base->GetSeed()); + return PyLong_FromLong(act->m_base->GetSeed()); } int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { SCA_RandomActuator* act = static_cast(self); - if (PyLong_Check(value)) { - int ival = PyLong_AsSsize_t(value); - act->m_base->SetSeed(ival); + if (PyLong_Check(value)) { + act->m_base->SetSeed(PyLong_AsLong(value)); return PY_SET_ATTR_SUCCESS; - } else { + } + else { PyErr_SetString(PyExc_TypeError, "actuator.seed = int: Random Actuator, expected an integer"); return PY_SET_ATTR_FAIL; } diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 7199ee6cf22..4e93556453a 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -168,7 +168,7 @@ PyAttributeDef SCA_RandomSensor::Attributes[] = { PyObject *SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomSensor* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_basegenerator->GetSeed()); + return PyLong_FromLong(self->m_basegenerator->GetSeed()); } int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -178,7 +178,7 @@ int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *at PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer"); return PY_SET_ATTR_FAIL; } - self->m_basegenerator->SetSeed(PyLong_AsSsize_t(value)); + self->m_basegenerator->SetSeed(PyLong_AsLong(value)); return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index d5e1f081d21..6a1f47c51af 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -31,7 +31,6 @@ incs = ['.', '#source/blender', '#source/blender/include', '#source/blender/makesdna', - '#source/gameengine/BlenderRoutines', '#source/gameengine/Rasterizer', '#source/gameengine/GameLogic', '#source/gameengine/Expressions', diff --git a/source/gameengine/GamePlayer/common/bmfont.cpp b/source/gameengine/GamePlayer/common/bmfont.cpp index fe6f2187138..8ffbe757222 100644 --- a/source/gameengine/GamePlayer/common/bmfont.cpp +++ b/source/gameengine/GamePlayer/common/bmfont.cpp @@ -73,9 +73,6 @@ void printfGlyph(bmGlyph * glyph) } */ -#define MAX2(x,y) ( (x)>(y) ? (x) : (y) ) -#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) ) - void calcAlpha(ImBuf * ibuf) { int i; diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 40b52c3212a..92db1fe790e 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -555,7 +555,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool showPhysics = (gm->flag & GAME_SHOW_PHYSICS); SYS_WriteCommandLineInt(syshandle, "show_physics", showPhysics); - bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0); + bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixedtime", fixedFr) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0); bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 725c23c60e3..a82f9ce1779 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -60,6 +60,7 @@ extern "C" #include "BKE_blender.h" #include "BKE_global.h" #include "BKE_icons.h" +#include "BKE_image.h" #include "BKE_node.h" #include "BKE_report.h" #include "BKE_library.h" @@ -172,7 +173,7 @@ static BOOL scr_saver_init(int argc, char **argv) #endif /* WIN32 */ -void usage(const char* program, bool isBlenderPlayer) +static void usage(const char* program, bool isBlenderPlayer) { const char * consoleoption; const char * example_filename = ""; @@ -332,7 +333,7 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL return bfd; } -bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs) +static bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs) { bool run = true; system->processEvents(false); @@ -352,7 +353,7 @@ struct GPG_NextFrameState { GlobalSettings *gs; } gpg_nextframestate; -int GPG_PyNextFrame(void *state0) +static int GPG_PyNextFrame(void *state0) { GPG_NextFrameState *state = (GPG_NextFrameState *) state0; int exitcode; @@ -446,11 +447,11 @@ int main(int argc, char** argv) G.main = NULL; IMB_init(); + BKE_images_init(); // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c) BLF_init(11, U.dpi); BLF_lang_init(); - BLF_lang_encoding(""); BLF_lang_set(""); BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); @@ -755,6 +756,7 @@ int main(int argc, char** argv) } GPU_set_anisotropic(U.anisotropic_filter); + GPU_set_gpu_mipmapping(U.use_gpu_mipmap); // Create the system if (GHOST_ISystem::createSystem() == GHOST_kSuccess) @@ -1068,6 +1070,7 @@ int main(int argc, char** argv) #endif IMB_exit(); + BKE_images_exit(); free_nodesystem(); SYS_DeleteSystem(syshandle); diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 9fb0f053ed8..fb046d0fdf8 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -26,7 +26,6 @@ incs = ['.', '#source/blender/include', '#source/blender/makesdna', '#source/blender/makesrna', - '#source/gameengine/BlenderRoutines', '#source/gameengine/Rasterizer', '#source/gameengine/GameLogic', '#source/gameengine/Expressions', diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index 4c7518769e1..0954aa0f7ab 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -36,10 +36,7 @@ BL_Material::BL_Material() void BL_Material::Initialize() { - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 0; - rgb[3] = 0; + m_mcol = 0xFFFFFFFFL; IdMode = 0; ras_mode = 0; glslmat = 0; @@ -66,11 +63,6 @@ void BL_Material::Initialize() share = false; int i; - for (i=0; i<4; i++) - { - uv[i] = MT_Point2(0.f,1.f); - uv2[i] = MT_Point2(0.f, 1.f); - } for (i=0; i 1 ) diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index b67bd95f878..ef180ed2126 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -87,22 +87,13 @@ public: MTFace tface; /* copy of the derived meshes tface */ Image* img[MAXTEX]; EnvMap* cubemap[MAXTEX]; - - unsigned int rgb[4]; - MT_Point2 uv[4]; - MT_Point2 uv2[4]; + unsigned int m_mcol; /* for text color (only) */ STR_String uvName; STR_String uv2Name; - void SetConversionRGB(unsigned int *rgb); - void GetConversionRGB(unsigned int *rgb); - - void SetConversionUV(const STR_String& name, MT_Point2 *uv); - void GetConversionUV(MT_Point2 *uv); - - void SetConversionUV2(const STR_String& name, MT_Point2 *uv); - void GetConversionUV2(MT_Point2 *uv); + void SetUVLayerName(const STR_String &name); + void SetUVLayerName2(const STR_String &name); void SetSharedMaterial(bool v); bool IsShared(); diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index fb8e7beb157..4a74024b5bb 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -571,41 +571,39 @@ void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) } -int BL_Shader::GetAttribLocation(const STR_String& name) +int BL_Shader::GetAttribLocation(const char *name) { - if ( GLEW_ARB_fragment_shader && - GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects - ) + if (GLEW_ARB_fragment_shader && + GLEW_ARB_vertex_shader && + GLEW_ARB_shader_objects) { - return glGetAttribLocationARB(mShader, name.ReadPtr()); + return glGetAttribLocationARB(mShader, name); } return -1; } -void BL_Shader::BindAttribute(const STR_String& attr, int loc) +void BL_Shader::BindAttribute(const char *attr, int loc) { - if ( GLEW_ARB_fragment_shader && - GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects - ) + if (GLEW_ARB_fragment_shader && + GLEW_ARB_vertex_shader && + GLEW_ARB_shader_objects ) { - glBindAttribLocationARB(mShader, loc, attr.ReadPtr()); + glBindAttribLocationARB(mShader, loc, attr); } } -int BL_Shader::GetUniformLocation(const STR_String& name) +int BL_Shader::GetUniformLocation(const char *name) { if ( GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects + GLEW_ARB_shader_objects ) { MT_assert(mShader!=0); - int location = glGetUniformLocationARB(mShader, name.ReadPtr()); + int location = glGetUniformLocationARB(mShader, name); if (location == -1) - spit("Invalid uniform value: " << name.ReadPtr() << "."); + spit("Invalid uniform value: " << name << "."); return location; } @@ -851,7 +849,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" ) KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" ) { - return PyLong_FromSsize_t( ( mShader !=0 && mOk ) ); + return PyBool_FromLong(( mShader !=0 && mOk )); } KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg, "getVertexProg( )" ) @@ -900,7 +898,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" ) Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int index=-1; if (PyArg_ParseTuple(args, "si:setSampler", &uniform, &index)) { @@ -941,7 +939,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float value=0; if (PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value )) { @@ -965,7 +963,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f, "setUniform2f(name, fx, fy)") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[2] = {0, 0}; if (PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] )) { @@ -989,7 +987,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[3] = {0, 0, 0}; if (PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2])) { @@ -1014,7 +1012,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) " if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[4] = {0, 0, 0, 0}; if (PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3])) { @@ -1038,7 +1036,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" ) if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int value=0; if (PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value )) { @@ -1062,7 +1060,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i, "setUniform2i(name, ix, iy)") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[2] = {0, 0}; if (PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] )) { @@ -1087,7 +1085,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[3] = {0, 0, 0}; if (PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2])) { @@ -1110,7 +1108,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) " if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[4] = {0, 0, 0, 0}; if (PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] )) { @@ -1226,7 +1224,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 for (unsigned int i=0; (iok = 0; @@ -128,6 +128,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) if (mTexture != 0) { glBindTexture(GL_TEXTURE_2D, mTexture ); Validate(); + BKE_image_release_ibuf(img, ibuf, NULL); return mOk; } @@ -140,6 +141,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_2D, mTexture); mOk = IsValid(); + BKE_image_release_ibuf(img, ibuf, NULL); return mOk; } } @@ -166,6 +168,9 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) glDisable(GL_TEXTURE_2D); ActivateUnit(0); Validate(); + + BKE_image_release_ibuf(img, ibuf, NULL); + return mOk; } @@ -251,7 +256,7 @@ bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) return mOk; } - ImBuf *ibuf= BKE_image_get_ibuf(cubemap->ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(cubemap->ima, NULL, NULL); if (ibuf==0) { cubemap->ima->ok = 0; @@ -274,6 +279,7 @@ bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); mOk = IsValid(); + BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; } } @@ -307,6 +313,7 @@ bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) my_free_envmapdata(cubemap); mOk = false; + BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; } @@ -341,6 +348,9 @@ bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) ActivateUnit(0); mOk = IsValid(); + + BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); + return mOk; } @@ -646,9 +656,11 @@ int BL_Texture::GetPow2(int n) void BL_Texture::SplitEnvMap(EnvMap *map) { if (!map || !map->ima || (map->ima && !map->ima->ok)) return; - ImBuf *ibuf= BKE_image_get_ibuf(map->ima, NULL); - if (ibuf) + ImBuf *ibuf= BKE_image_acquire_ibuf(map->ima, NULL, NULL); + if (ibuf) { my_envmap_split_ima(map, ibuf); + BKE_image_release_ibuf(map->ima, ibuf, NULL); + } } unsigned int BL_Texture::mDisableState = 0; diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 2eada3e5071..524a38a4c26 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -101,7 +101,6 @@ set(SRC KX_ObstacleSimulation.cpp KX_OrientationInterpolator.cpp KX_ParentActuator.cpp - KX_PhysicsObjectWrapper.cpp KX_PolyProxy.cpp KX_PolygonMaterial.cpp KX_PositionInterpolator.cpp @@ -184,7 +183,6 @@ set(SRC KX_OrientationInterpolator.h KX_ParentActuator.h KX_PhysicsEngineEnums.h - KX_PhysicsObjectWrapper.h KX_PhysicsPropertiesobsolete.h KX_PolyProxy.h KX_PolygonMaterial.h diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 2154beeb205..20c36c2cc44 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -124,7 +124,7 @@ MTFace* KX_BlenderMaterial::GetMTFace(void) const unsigned int* KX_BlenderMaterial::GetMCol(void) const { // fonts on polys - return mMaterial->rgb; + return &mMaterial->m_mcol; } void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const @@ -138,6 +138,11 @@ void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); } +bool KX_BlenderMaterial::IsMaterial(const BL_Material *bl_mat) const +{ + return (mMaterial == bl_mat); +} + Material *KX_BlenderMaterial::GetBlenderMaterial() const { return mMaterial->material; @@ -844,7 +849,7 @@ PyObject *KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBU PyObject *KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_BlenderMaterial* self = static_cast(self_v); - return PyLong_FromSsize_t(self->GetMaterialIndex()); + return PyLong_FromLong(self->GetMaterialIndex()); } PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -926,7 +931,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") { - return PyLong_FromSsize_t( GetMaterialIndex() ); + return PyLong_FromLong(GetMaterialIndex()); } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" ) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 1653669ebcc..7bc9c7c3863 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -76,6 +76,8 @@ public: TCachingInfo& cachingInfo )const; + /* mMaterial is private, but need this for conversion */ + bool IsMaterial(const BL_Material *bl_mat) const; Material* GetBlenderMaterial() const; MTFace* GetMTFace(void) const; unsigned int* GetMCol(void) const; diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 39b0a24865e..e56dbfdcac8 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -593,7 +593,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, MT_Point3 center; if (PyVecTo(pycenter, center)) { - return PyLong_FromSsize_t(SphereInsideFrustum(center, radius)); /* new ref */ + return PyLong_FromLong(SphereInsideFrustum(center, radius)); /* new ref */ } } @@ -644,7 +644,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, return NULL; } - return PyLong_FromSsize_t(BoxInsideFrustum(box)); /* new ref */ + return PyLong_FromLong(BoxInsideFrustum(box)); /* new ref */ } KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, @@ -666,7 +666,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, MT_Point3 point; if (PyVecTo(value, point)) { - return PyLong_FromSsize_t(PointInsideFrustum(point)); /* new ref */ + return PyLong_FromLong(PointInsideFrustum(point)); /* new ref */ } PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument."); @@ -869,11 +869,11 @@ PyObject *KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBU PyObject *KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromSsize_t(INSIDE); } +{ return PyLong_FromLong(INSIDE); } PyObject *KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromSsize_t(OUTSIDE); } +{ return PyLong_FromLong(OUTSIDE); } PyObject *KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromSsize_t(INTERSECT); } +{ return PyLong_FromLong(INTERSECT); } bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix) diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index a37b1b0c396..59ca0d8d326 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -388,8 +388,8 @@ PyAttributeDef KX_CameraActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW("min",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_minHeight), KX_PYATTRIBUTE_FLOAT_RW("max",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_maxHeight), KX_PYATTRIBUTE_FLOAT_RW("height",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_height), - KX_PYATTRIBUTE_SHORT_RW("axis", 0, 3, true, KX_CameraActuator,m_axis), - KX_PYATTRIBUTE_RW_FUNCTION("object", KX_CameraActuator, pyattr_get_object, pyattr_set_object), + KX_PYATTRIBUTE_SHORT_RW("axis", 0, 5, true, KX_CameraActuator, m_axis), + KX_PYATTRIBUTE_RW_FUNCTION("object", KX_CameraActuator, pyattr_get_object, pyattr_set_object), KX_PYATTRIBUTE_FLOAT_RW("damping",0.f,10.f,KX_CameraActuator,m_damping), {NULL} }; diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h index cc99aba99f6..3b0058aca6f 100644 --- a/source/gameengine/Ketsji/KX_CharacterWrapper.h +++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h @@ -32,4 +32,4 @@ private: PHY_ICharacter* m_character; }; -#endif //__KX_CHARACTERWRAPPER_H__ +#endif /* __KX_CHARACTERWRAPPER_H__ */ diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index 662db974ee8..e09449c4f1d 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -52,7 +52,7 @@ KX_ConstraintWrapper::~KX_ConstraintWrapper() PyObject *KX_ConstraintWrapper::PyGetConstraintId() { - return PyLong_FromSsize_t(m_constraintId); + return PyLong_FromLong(m_constraintId); } diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp index fca407f6398..9f530f80e37 100644 --- a/source/gameengine/Ketsji/KX_Dome.cpp +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -1,25 +1,27 @@ /* - * ----------------------------------------------------------------------------- + * ***** BEGIN GPL LICENSE BLOCK ***** * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser 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 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 Lesser General Public License for more details. + * 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 Lesser General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307, USA, or go to - * http://www.gnu.org/copyleft/lesser.txt. + * 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): Dalai Felinto * * This code is originally inspired on some of the ideas and codes from Paul Bourke. - * Developed as part of a Research and Development project for SAT - La Société des arts technologiques. - * ----------------------------------------------------------------------------- + * Developed as part of a Research and Development project for + * SAT - La Société des arts technologiques. + * + * ***** END GPL LICENSE BLOCK ***** */ /** \file gameengine/Ketsji/KX_Dome.cpp diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h index 17eec3a5fcb..3bc90bf6c35 100644 --- a/source/gameengine/Ketsji/KX_Dome.h +++ b/source/gameengine/Ketsji/KX_Dome.h @@ -1,26 +1,28 @@ /* ------------------------------------------------------------------------------ - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. - -Contributor(s): Dalai Felinto - -This source uses some of the ideas and code from Paul Bourke. -Developed as part of a Research and Development project for SAT - La Société des arts technologiques. ------------------------------------------------------------------------------ -*/ + * ***** 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): Dalai Felinto + * + * This source uses some of the ideas and code from Paul Bourke. + * Developed as part of a Research and Development project for + * SAT - La Société des arts technologiques. + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file KX_Dome.h * \ingroup ketsji diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index a669f4346ea..c7f6954fd6c 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -99,6 +99,7 @@ KX_GameObject::KX_GameObject( m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), + m_objectColor(1.0, 1.0, 1.0, 1.0), m_bVisible(true), m_bCulled(true), m_bOccluder(false), @@ -1692,8 +1693,8 @@ PyMethodDef KX_GameObject::Methods[] = { PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), - KX_PYATTRIBUTE_RO_FUNCTION("group_children", KX_GameObject, pyattr_get_group_children), - KX_PYATTRIBUTE_RO_FUNCTION("group_parent", KX_GameObject, pyattr_get_group_parent), + KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members), + KX_PYATTRIBUTE_RO_FUNCTION("groupObject", KX_GameObject, pyattr_get_group_object), KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene), KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), @@ -1990,7 +1991,7 @@ PyObject *KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE Py_RETURN_NONE; } -PyObject *KX_GameObject::pyattr_get_group_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_group_members(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast(self_v); CListValue* instances = self->GetInstanceObjects(); @@ -2011,7 +2012,7 @@ PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF Py_RETURN_NONE; } -PyObject *KX_GameObject::pyattr_get_group_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_group_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast(self_v); KX_GameObject* pivot = self->GetDupliGroupObject(); @@ -2474,13 +2475,13 @@ PyObject *KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF KX_GameObject* self = static_cast(self_v); int state = 0; state |= self->GetState(); - return PyLong_FromSsize_t(state); + return PyLong_FromLong(state); } int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_GameObject* self = static_cast(self_v); - int state_i = PyLong_AsSsize_t(value); + int state_i = PyLong_AsLong(value); unsigned int state = 0; if (state_i == -1 && PyErr_Occurred()) { @@ -2896,7 +2897,7 @@ PyObject *KX_GameObject::PyGetPhysicsId() { physid= (uint_ptr)ctrl->GetUserData(); } - return PyLong_FromSsize_t((long)physid); + return PyLong_FromLong((long)physid); } PyObject *KX_GameObject::PyGetPropertyNames() diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index d5ae13eb702..e71af674a79 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -989,8 +989,8 @@ public: static PyObject* pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_group_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_group_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_group_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_group_members(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_scene(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 0ab7b9ec9e5..a12e12ccef2 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -534,29 +534,27 @@ bool KX_KetsjiEngine::NextFrame() { double timestep = 1.0/m_ticrate; double framestep = timestep; -// static hidden::Clock sClock; + // static hidden::Clock sClock; -m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); + m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); -//float dt = sClock.getTimeMicroseconds() * 0.000001f; -//sClock.reset(); + //float dt = sClock.getTimeMicroseconds() * 0.000001f; + //sClock.reset(); -if (m_bFixedTime) - m_clockTime += timestep; -else -{ - -// m_clockTime += dt; - m_clockTime = m_kxsystem->GetTimeInSeconds(); -} + if (m_bFixedTime) { + m_clockTime += timestep; + } + else { + // m_clockTime += dt; + m_clockTime = m_kxsystem->GetTimeInSeconds(); + } double deltatime = m_clockTime - m_frameTime; if (deltatime<0.f) { - printf("problem with clock\n"); - deltatime = 0.f; - m_clockTime = 0.f; - m_frameTime = 0.f; + // We got here too quickly, which means there is nothing todo, just return and don't render. + // Not sure if this is the best fix, but it seems to stop the jumping framerate issue (#33088) + return false; } diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index a4e90cb1e83..cf58d18838a 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -372,11 +372,11 @@ PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT const char* type = attrdef->m_name; if (!strcmp(type, "SPOT")) { - retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SPOT); + retvalue = PyLong_FromLong(RAS_LightObject::LIGHT_SPOT); } else if (!strcmp(type, "SUN")) { - retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SUN); + retvalue = PyLong_FromLong(RAS_LightObject::LIGHT_SUN); } else if (!strcmp(type, "NORMAL")) { - retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_NORMAL); + retvalue = PyLong_FromLong(RAS_LightObject::LIGHT_NORMAL); } else { /* should never happen */ @@ -390,13 +390,13 @@ PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT PyObject *KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_LightObject* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_lightobj.m_type); + return PyLong_FromLong(self->m_lightobj.m_type); } int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_LightObject* self = static_cast(self_v); - int val = PyLong_AsSsize_t(value); + const int val = PyLong_AsLong(value); if ((val==-1 && PyErr_Occurred()) || val<0 || val>2) { PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2"); return PY_SET_ATTR_FAIL; diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 87c366046ad..d83e98d4712 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -70,13 +70,15 @@ PyTypeObject KX_MeshProxy::Type = { }; PyMethodDef KX_MeshProxy::Methods[] = { -{"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, -{"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, -{"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, -{"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, -{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, -//{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, - {NULL,NULL} //Sentinel + {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, + {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, + {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, + {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, + {"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, + {"transform", (PyCFunction)KX_MeshProxy::sPyTransform,METH_VARARGS}, + {"transformUV", (PyCFunction)KX_MeshProxy::sPyTransformUV,METH_VARARGS}, + //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_MeshProxy::Attributes[] = { @@ -170,7 +172,7 @@ PyObject *KX_MeshProxy::PyGetVertexArrayLength(PyObject *args, PyObject *kwds) length = m_meshobj->NumVertices(mat); } - return PyLong_FromSsize_t(length); + return PyLong_FromLong(length); } @@ -218,6 +220,160 @@ PyObject *KX_MeshProxy::PyGetPolygon(PyObject *args, PyObject *kwds) return polyob; } +PyObject *KX_MeshProxy::PyTransform(PyObject *args, PyObject *kwds) +{ + int matindex; + PyObject *pymat; + bool ok = false; + + MT_Matrix4x4 transform; + + if (!PyArg_ParseTuple(args,"iO:transform", &matindex, &pymat) || + !PyMatTo(pymat, transform)) + { + return NULL; + } + + MT_Matrix4x4 ntransform = transform.inverse().transposed(); + ntransform[0][3] = ntransform[1][3] = ntransform[2][3] = 0.0f; + + /* transform mesh verts */ + unsigned int mit_index = 0; + for (list::iterator mit = m_meshobj->GetFirstMaterial(); + (mit != m_meshobj->GetLastMaterial()); + ++mit, ++mit_index) + { + if (matindex == -1) { + /* always transform */ + } + else if (matindex == mit_index) { + /* we found the right index! */ + } + else { + continue; + } + + RAS_MeshSlot *slot = mit->m_baseslot; + RAS_MeshSlot::iterator it; + ok = true; + + for (slot->begin(it); !slot->end(it); slot->next(it)) { + size_t i; + for (i = it.startvertex; i < it.endvertex; i++) { + RAS_TexVert *vert = &it.vertex[i]; + vert->Transform(transform, ntransform); + } + } + + /* if we set a material index, quit when done */ + if (matindex == mit_index) { + break; + } + } + + if (ok == false) { + PyErr_Format(PyExc_ValueError, + "mesh.transform(...): invalid material index %d", matindex); + return NULL; + } + + m_meshobj->SetMeshModified(true); + + Py_RETURN_NONE; +} + +PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds) +{ + int matindex; + PyObject *pymat; + int uvindex = -1; + int uvindex_from = -1; + bool ok = false; + + MT_Matrix4x4 transform; + + if (!PyArg_ParseTuple(args,"iO|iii:transformUV", &matindex, &pymat, &uvindex, &uvindex_from) || + !PyMatTo(pymat, transform)) + { + return NULL; + } + + if (uvindex < -1 || uvindex > 1) { + PyErr_Format(PyExc_ValueError, + "mesh.transformUV(...): invalid uv_index %d", uvindex); + return NULL; + } + if (uvindex_from < -1 || uvindex_from > 1 || uvindex == -1) { + PyErr_Format(PyExc_ValueError, + "mesh.transformUV(...): invalid uv_index_from %d", uvindex); + return NULL; + } + if (uvindex_from == uvindex) { + uvindex_from = -1; + } + + /* transform mesh verts */ + unsigned int mit_index = 0; + for (list::iterator mit = m_meshobj->GetFirstMaterial(); + (mit != m_meshobj->GetLastMaterial()); + ++mit, ++mit_index) + { + if (matindex == -1) { + /* always transform */ + } + else if (matindex == mit_index) { + /* we found the right index! */ + } + else { + continue; + } + + RAS_MeshSlot *slot = mit->m_baseslot; + RAS_MeshSlot::iterator it; + ok = true; + + for (slot->begin(it); !slot->end(it); slot->next(it)) { + size_t i; + + for (i = it.startvertex; i < it.endvertex; i++) { + RAS_TexVert *vert = &it.vertex[i]; + if (uvindex_from != -1) { + if (uvindex_from == 0) vert->SetUV2(vert->getUV1()); + else vert->SetUV1(vert->getUV2()); + } + + switch (uvindex) { + case 0: + vert->TransformUV1(transform); + break; + case 1: + vert->TransformUV2(transform); + break; + case -1: + vert->TransformUV1(transform); + vert->TransformUV2(transform); + break; + } + } + } + + /* if we set a material index, quit when done */ + if (matindex == mit_index) { + break; + } + } + + if (ok == false) { + PyErr_Format(PyExc_ValueError, + "mesh.transformUV(...): invalid material index %d", matindex); + return NULL; + } + + m_meshobj->SetMeshModified(true); + + Py_RETURN_NONE; +} + PyObject *KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_MeshProxy* self = static_cast(self_v); @@ -250,13 +406,13 @@ PyObject *KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_ PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { KX_MeshProxy * self = static_cast (selfv); - return PyLong_FromSsize_t(self->m_meshobj->NumMaterials()); + return PyLong_FromLong(self->m_meshobj->NumMaterials()); } PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { KX_MeshProxy * self = static_cast (selfv); - return PyLong_FromSsize_t(self->m_meshobj->NumPolygons()); + return PyLong_FromLong(self->m_meshobj->NumPolygons()); } /* a close copy of ConvertPythonToGameObject but for meshes */ diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 98e73aa626f..5366634ef98 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -71,8 +71,10 @@ public: KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength); KX_PYMETHOD(KX_MeshProxy,GetVertex); KX_PYMETHOD(KX_MeshProxy,GetPolygon); + KX_PYMETHOD(KX_MeshProxy,Transform); + KX_PYMETHOD(KX_MeshProxy,TransformUV); - static PyObject* pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject *pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef); static PyObject *pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef); }; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index e5f7ea22b36..931039bc54c 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -529,7 +529,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE { self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.Torque = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.Torque = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { @@ -565,7 +565,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE { self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.DLoc = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.DLoc = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { @@ -601,7 +601,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE { self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.DRot = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.DRot = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { diff --git a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp index 99d9fc7f9ee..8798f42fa07 100644 --- a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp +++ b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp @@ -1,6 +1,4 @@ /* - * Simulation for obstacle avoidance behavior - * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -22,6 +20,12 @@ * ***** END GPL LICENSE BLOCK ***** */ +/** \file gameengine/Ketsji/KX_ObstacleSimulation.cpp + * \ingroup ketsji + * + * Simulation for obstacle avoidance behavior + */ + #include "KX_ObstacleSimulation.h" #include "KX_NavMeshObject.h" #include "KX_PythonInit.h" diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp deleted file mode 100644 index f18c35c0c78..00000000000 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ /dev/null @@ -1,145 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp - * \ingroup ketsji - */ - - -#include "PyObjectPlus.h" - -#include "KX_PhysicsObjectWrapper.h" -#include "PHY_IPhysicsEnvironment.h" -#include "PHY_IPhysicsController.h" - -KX_PhysicsObjectWrapper::KX_PhysicsObjectWrapper( - PHY_IPhysicsController* ctrl, - PHY_IPhysicsEnvironment* physenv) : - PyObjectPlus(), - m_ctrl(ctrl), - m_physenv(physenv) -{ -} - -KX_PhysicsObjectWrapper::~KX_PhysicsObjectWrapper() -{ -} - -#ifdef WITH_PYTHON - -PyObject *KX_PhysicsObjectWrapper::PySetPosition(PyObject *args) -{ - float x,y,z; - if (PyArg_ParseTuple(args,"fff:setPosition",&x,&y,&z)) - { - m_ctrl->setPosition(x,y,z); - } - else { - return NULL; - } - Py_RETURN_NONE; -} - - -PyObject *KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject *args) -{ - float x,y,z; - int local; - if (PyArg_ParseTuple(args,"fffi:setLinearVelocity",&x,&y,&z,&local)) - { - m_ctrl->SetLinearVelocity(x,y,z,local != 0); - } - else { - return NULL; - } - Py_RETURN_NONE; -} - -PyObject *KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject *args) -{ - float x,y,z; - int local; - if (PyArg_ParseTuple(args,"fffi:setAngularVelocity",&x,&y,&z,&local)) - { - m_ctrl->SetAngularVelocity(x,y,z,local != 0); - } - else { - return NULL; - } - Py_RETURN_NONE; -} - -PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject *args) -{ - int active; - if (PyArg_ParseTuple(args,"i:setActive",&active)) - { - m_ctrl->SetActive(active!=0); - } - else { - return NULL; - } - Py_RETURN_NONE; -} - - -PyAttributeDef KX_PhysicsObjectWrapper::Attributes[] = { - { NULL } //Sentinel -}; - -//python specific stuff -PyTypeObject KX_PhysicsObjectWrapper::Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "KX_PhysicsObjectWrapper", - sizeof(PyObjectPlus_Proxy), - 0, - py_base_dealloc, - 0, - 0, - 0, - 0, - py_base_repr, - 0,0,0,0,0,0,0,0,0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - 0,0,0,0,0,0,0, - Methods, - 0, - 0, - &PyObjectPlus::Type, - 0,0,0,0,0,0, - py_base_new -}; - -PyMethodDef KX_PhysicsObjectWrapper::Methods[] = { - {"setPosition",(PyCFunction) KX_PhysicsObjectWrapper::sPySetPosition, METH_VARARGS}, - {"setLinearVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetLinearVelocity, METH_VARARGS}, - {"setAngularVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetAngularVelocity, METH_VARARGS}, - {"setActive",(PyCFunction) KX_PhysicsObjectWrapper::sPySetActive, METH_VARARGS}, - {NULL,NULL} //Sentinel -}; - -#endif diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h deleted file mode 100644 index 171416c5e8f..00000000000 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ /dev/null @@ -1,59 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file KX_PhysicsObjectWrapper.h - * \ingroup ketsji - */ - -#ifndef __KX_PHYSICSOBJECTWRAPPER_H__ -#define __KX_PHYSICSOBJECTWRAPPER_H__ - -#include "Value.h" -#include "PHY_DynamicTypes.h" - -class KX_PhysicsObjectWrapper : public PyObjectPlus -{ - Py_Header -public: - KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv); - virtual ~KX_PhysicsObjectWrapper(); - -#ifdef WITH_PYTHON - - KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetPosition); - KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetLinearVelocity); - KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetAngularVelocity); - KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetActive); - -#endif /* WITH_PYTHON */ - -private: - class PHY_IPhysicsController* m_ctrl; - PHY_IPhysicsEnvironment* m_physenv; -}; - -#endif /* __KX_PHYSICSOBJECTWRAPPER_H__ */ diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index 465e91ffb32..840ffdde165 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -140,21 +140,21 @@ PyObject *KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *at { KX_PolyProxy* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 0)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 0)); } PyObject *KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolyProxy* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 1)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 1)); } PyObject *KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolyProxy* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 2)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 2)); } PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -163,9 +163,9 @@ PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *at if (3 < self->m_polygon->VertexCount()) { - return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 3)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 3)); } - return PyLong_FromSsize_t(0); + return PyLong_FromLong(0); } PyObject *KX_PolyProxy::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -192,25 +192,25 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, // found it break; } - return PyLong_FromSsize_t(matid); + return PyLong_FromLong(matid); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex, "getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n") { - return PyLong_FromSsize_t(m_polygon->VertexCount()); + return PyLong_FromLong(m_polygon->VertexCount()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isVisible, "isVisible() : returns whether the polygon is visible or not\n") { - return PyLong_FromSsize_t(m_polygon->IsVisible()); + return PyLong_FromLong(m_polygon->IsVisible()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isCollider, "isCollider() : returns whether the polygon is receives collision or not\n") { - return PyLong_FromSsize_t(m_polygon->IsCollider()); + return PyLong_FromLong(m_polygon->IsCollider()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName, @@ -243,9 +243,9 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, } if (index < m_polygon->VertexCount()) { - return PyLong_FromSsize_t(m_polygon->GetVertexOffsetAbs(m_mesh, index)); + return PyLong_FromLong(m_polygon->GetVertexOffsetAbs(m_mesh, index)); } - return PyLong_FromSsize_t(0); + return PyLong_FromLong(0); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh, diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 36c94dc997b..f157d9ed20a 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -109,7 +109,7 @@ void KX_PolygonMaterial::Initialize( m_mcol = *mcol; } else { - memset(&m_mcol, 0, sizeof(m_mcol)); + m_mcol = 0; } m_material = ma; @@ -146,7 +146,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI PyObject *ret = PyObject_CallMethod(m_pymaterial, (char *)"activate", (char *)"(NNO)", pyRasty, pyCachingInfo, (PyObject *) this->m_proxy); if (ret) { - bool value = PyLong_AsSsize_t(ret); + bool value = PyLong_AsLong(ret); Py_DECREF(ret); dopass = value; } @@ -266,8 +266,6 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("tface", KX_PolygonMaterial, pyattr_get_tface), /* How the heck is this even useful??? - Campbell */ KX_PYATTRIBUTE_RO_FUNCTION("gl_texture", KX_PolygonMaterial, pyattr_get_gl_texture), /* could be called 'bindcode' */ - - /* triangle used to be an attribute, removed for 2.49, nobody should be using it */ { NULL } //Sentinel }; @@ -381,7 +379,7 @@ PyObject *KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATT if (self->m_tface.tpage) bindcode= self->m_tface.tpage->bindcode; - return PyLong_FromSsize_t(bindcode); + return PyLong_FromLong(bindcode); } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 89bfb4ff9fb..2ce8f480c1c 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -60,7 +60,7 @@ class KX_PolygonMaterial : public PyObjectPlus, public RAS_IPolyMaterial private: /** Blender texture face structure. */ mutable MTFace m_tface; - mutable unsigned int m_mcol; + mutable unsigned int m_mcol; /* for text color (only) */ Material* m_material; #ifdef WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 4475ac8ec96..9bb09d56de6 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -34,7 +34,6 @@ #include "KX_ConstraintWrapper.h" #include "KX_VehicleWrapper.h" #include "KX_CharacterWrapper.h" -#include "KX_PhysicsObjectWrapper.h" #include "PHY_IPhysicsController.h" #include "PHY_IVehicle.h" #include "PHY_DynamicTypes.h" @@ -51,7 +50,7 @@ #ifdef WITH_PYTHON // macro copied from KX_PythonInit.cpp -#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item) +#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name2)); Py_DECREF(item) // nasty glob variable to connect scripting language // if there is a better way (without global), please do so! @@ -729,7 +728,7 @@ PyObject *initPythonConstraintBinding() KX_MACRO_addTypesToDict(d, DBG_PROFILETIMINGS, btIDebugDraw::DBG_ProfileTimings); KX_MACRO_addTypesToDict(d, DBG_ENABLESATCOMPARISION, btIDebugDraw::DBG_EnableSatComparison); KX_MACRO_addTypesToDict(d, DBG_DISABLEBULLETLCP, btIDebugDraw::DBG_DisableBulletLCP); - KX_MACRO_addTypesToDict(d, DBG_ENABLECDD, btIDebugDraw::DBG_EnableCCD); + KX_MACRO_addTypesToDict(d, DBG_ENABLECCD, btIDebugDraw::DBG_EnableCCD); KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints); KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits); KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 7f6655861f1..996be97c474 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -193,10 +193,10 @@ static PyObject *gp_OrigPythonSysPath= NULL; static PyObject *gp_OrigPythonSysModules= NULL; /* Macro for building the keyboard translation */ -//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromSsize_t(SCA_IInputDevice::KX_##name)) -#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name)); Py_DECREF(item) +//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromLong(SCA_IInputDevice::KX_##name)) +#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name)); Py_DECREF(item) /* For the defines for types from logic bricks, we do stuff explicitly... */ -#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item) +#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name2)); Py_DECREF(item) // temporarily python stuff, will be put in another place later ! @@ -429,7 +429,7 @@ static PyObject *gPySetExitKey(PyObject *, PyObject *args) static PyObject *gPyGetExitKey(PyObject *) { - return PyLong_FromSsize_t(KX_KetsjiEngine::GetExitKey()); + return PyLong_FromLong(KX_KetsjiEngine::GetExitKey()); } static PyObject *gPySetMaxLogicFrame(PyObject *, PyObject *args) @@ -444,7 +444,7 @@ static PyObject *gPySetMaxLogicFrame(PyObject *, PyObject *args) static PyObject *gPyGetMaxLogicFrame(PyObject *) { - return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxLogicFrame()); + return PyLong_FromLong(KX_KetsjiEngine::GetMaxLogicFrame()); } static PyObject *gPySetMaxPhysicsFrame(PyObject *, PyObject *args) @@ -459,7 +459,7 @@ static PyObject *gPySetMaxPhysicsFrame(PyObject *, PyObject *args) static PyObject *gPyGetMaxPhysicsFrame(PyObject *) { - return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxPhysicsFrame()); + return PyLong_FromLong(KX_KetsjiEngine::GetMaxPhysicsFrame()); } static PyObject *gPySetPhysicsTicRate(PyObject *, PyObject *args) @@ -862,14 +862,14 @@ static struct PyMethodDef game_methods[] = { static PyObject *gPyGetWindowHeight(PyObject *, PyObject *args) { - return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetHeight() : 0)); + return PyLong_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); } static PyObject *gPyGetWindowWidth(PyObject *, PyObject *args) { - return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetWidth() : 0)); + return PyLong_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0)); } @@ -1203,7 +1203,7 @@ static PyObject *gPyGetGLSLMaterialSetting(PyObject *, } enabled = ((gs->glslflag & flag) != 0); - return PyLong_FromSsize_t(enabled); + return PyLong_FromLong(enabled); } #define KX_TEXFACE_MATERIAL 0 @@ -1246,7 +1246,7 @@ static PyObject *gPyGetMaterialType(PyObject *) else flag = KX_TEXFACE_MATERIAL; - return PyLong_FromSsize_t(flag); + return PyLong_FromLong(flag); } static PyObject *gPySetAnisotropicFiltering(PyObject *, PyObject *args) @@ -1688,6 +1688,7 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_ACT_ARMATURE_DISABLE, ACT_ARM_DISABLE); KX_MACRO_addTypesToDict(d, KX_ACT_ARMATURE_SETTARGET, ACT_ARM_SETTARGET); KX_MACRO_addTypesToDict(d, KX_ACT_ARMATURE_SETWEIGHT, ACT_ARM_SETWEIGHT); + KX_MACRO_addTypesToDict(d, KX_ACT_ARMATURE_SETINFLUENCE, ACT_ARM_SETINFLUENCE); /* BL_Armature Channel rotation_mode */ KX_MACRO_addTypesToDict(d, ROT_MODE_QUAT, ROT_MODE_QUAT); diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 805b9ce2fc2..971730672db 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -40,6 +40,7 @@ #include "BL_ArmatureConstraint.h" #include "BL_ArmatureObject.h" #include "BL_ArmatureChannel.h" +#include "KX_ArmatureSensor.h" #include "KX_BlenderMaterial.h" #include "KX_CameraActuator.h" #include "KX_CharacterWrapper.h" @@ -54,7 +55,6 @@ #include "KX_NetworkMessageSensor.h" #include "KX_ObjectActuator.h" #include "KX_ParentActuator.h" -#include "KX_PhysicsObjectWrapper.h" #include "KX_PolyProxy.h" #include "KX_PolygonMaterial.h" #include "KX_PythonSeq.h" @@ -185,8 +185,10 @@ void initPyTypes(void) PyType_Ready_Attr(dict, BL_ArmatureConstraint, init_getset); PyType_Ready_AttrPtr(dict, BL_ArmatureBone, init_getset); PyType_Ready_AttrPtr(dict, BL_ArmatureChannel, init_getset); + // PyType_Ready_Attr(dict, CPropValue, init_getset); // doesn't use Py_Header PyType_Ready_Attr(dict, CListValue, init_getset); PyType_Ready_Attr(dict, CValue, init_getset); + PyType_Ready_Attr(dict, KX_ArmatureSensor, init_getset); PyType_Ready_Attr(dict, KX_BlenderMaterial, init_getset); PyType_Ready_Attr(dict, KX_Camera, init_getset); PyType_Ready_Attr(dict, KX_CameraActuator, init_getset); @@ -205,7 +207,6 @@ void initPyTypes(void) PyType_Ready_Attr(dict, KX_NetworkMessageSensor, init_getset); PyType_Ready_Attr(dict, KX_ObjectActuator, init_getset); PyType_Ready_Attr(dict, KX_ParentActuator, init_getset); - PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper, init_getset); PyType_Ready_Attr(dict, KX_PolyProxy, init_getset); PyType_Ready_Attr(dict, KX_PolygonMaterial, init_getset); PyType_Ready_Attr(dict, KX_RadarSensor, init_getset); @@ -228,6 +229,7 @@ void initPyTypes(void) PyType_Ready_Attr(dict, PyObjectPlus, init_getset); PyType_Ready_Attr(dict, SCA_2DFilterActuator, init_getset); PyType_Ready_Attr(dict, SCA_ANDController, init_getset); + // PyType_Ready_Attr(dict, SCA_Actuator, init_getset); // doesn't use Py_Header PyType_Ready_Attr(dict, SCA_ActuatorSensor, init_getset); PyType_Ready_Attr(dict, SCA_AlwaysSensor, init_getset); PyType_Ready_Attr(dict, SCA_DelaySensor, init_getset); diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp index 6b4d88709e8..f0e11645bc1 100644 --- a/source/gameengine/Ketsji/KX_PythonSeq.cpp +++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp @@ -100,7 +100,7 @@ static Py_ssize_t KX_PythonSeq_len( PyObject *self ) } } -static PyObject *KX_PythonSeq_getIndex(PyObject *self, int index) +static PyObject *KX_PythonSeq_getIndex(PyObject *self, Py_ssize_t index) { PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); @@ -273,8 +273,8 @@ static PyObject * KX_PythonSeq_subscript(PyObject *self, PyObject *key) return NULL; } - if (PyLong_Check(key)) { - return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t( key )); + if (PyIndex_Check(key)) { + return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t(key)); } else if ( PyUnicode_Check(key) ) { const char *name = _PyUnicode_AsString(key); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index d850168afdf..56dccc1d045 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -190,8 +190,8 @@ PyTypeObject KX_SCA_AddObjectActuator::Type = { }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { - {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"}, - {NULL,NULL} //Sentinel + {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS, NULL}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = { diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index e6209d2d47b..81c9dc91603 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -113,7 +113,7 @@ PyTypeObject KX_SCA_EndObjectActuator::Type = { }; PyMethodDef KX_SCA_EndObjectActuator::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = { diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 96b4a21a36c..72be5f57b95 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -55,7 +55,7 @@ #include "SCA_BasicEventManager.h" #include "KX_Camera.h" #include "SCA_JoystickManager.h" - +#include "KX_PyMath.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" @@ -1706,6 +1706,17 @@ void KX_Scene::SetGravity(const MT_Vector3& gravity) GetPhysicsEnvironment()->setGravity(gravity[0],gravity[1],gravity[2]); } +MT_Vector3 KX_Scene::GetGravity() +{ + PHY__Vector3 gravity; + MT_Vector3 vec; + + GetPhysicsEnvironment()->getGravity(gravity); + vec = gravity.m_vec; + + return vec; +} + void KX_Scene::SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter) { m_sceneConverter = sceneConverter; @@ -2270,6 +2281,25 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } +PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast(self_v); + + return PyObjectFrom(self->GetGravity()); +} + +int KX_Scene::pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Scene* self = static_cast(self_v); + + MT_Vector3 vec; + if (!PyVecTo(value, vec)) + return PY_SET_ATTR_FAIL; + + self->SetGravity(vec); + return PY_SET_ATTR_SUCCESS; +} + PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects), @@ -2280,6 +2310,7 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), + KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity), KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius), diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index c2e468e6da6..29473949535 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -573,6 +573,7 @@ public: void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv); void SetGravity(const MT_Vector3& gravity); + MT_Vector3 GetGravity(); short GetAnimationFPS(); @@ -616,6 +617,8 @@ public: static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(GetName()); } diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index b5d6f11a2d5..9cc91a33886 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -126,13 +126,13 @@ PyObject *KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject *args) PyObject *KX_VehicleWrapper::PyGetNumWheels(PyObject *args) { - return PyLong_FromSsize_t(m_vehicle->GetNumWheels()); + return PyLong_FromLong(m_vehicle->GetNumWheels()); } PyObject *KX_VehicleWrapper::PyGetConstraintId(PyObject *args) { - return PyLong_FromSsize_t(m_vehicle->GetUserConstraintId()); + return PyLong_FromLong(m_vehicle->GetUserConstraintId()); } @@ -263,7 +263,7 @@ PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args) PyObject *KX_VehicleWrapper::PyGetConstraintType(PyObject *args) { - return PyLong_FromSsize_t(m_vehicle->GetUserConstraintType()); + return PyLong_FromLong(m_vehicle->GetUserConstraintType()); } diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index dabb79b357d..2354359af18 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -61,19 +61,19 @@ PyTypeObject KX_VertexProxy::Type = { }; PyMethodDef KX_VertexProxy::Methods[] = { -{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, -{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, -{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS}, -{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O}, + {"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, + {"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, + {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV1, METH_NOARGS}, + {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV1, METH_O}, -{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, -{"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, + {"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, + {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, -{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, -{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, -{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS}, -{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O}, - {NULL,NULL} //Sentinel + {"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, + {"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, + {"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS}, + {"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_VertexProxy::Attributes[] = { @@ -247,7 +247,7 @@ int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF * float val = PyFloat_AsDouble(value); MT_Point2 uv = self->m_vertex->getUV1(); uv[0] = val; - self->m_vertex->SetUV(uv); + self->m_vertex->SetUV1(uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -262,7 +262,7 @@ int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF * float val = PyFloat_AsDouble(value); MT_Point2 uv = self->m_vertex->getUV1(); uv[1] = val; - self->m_vertex->SetUV(uv); + self->m_vertex->SetUV1(uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -389,9 +389,8 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF if (PySequence_Check(value)) { MT_Point2 vec; - if (PyVecTo(value, vec)) - { - self->m_vertex->SetUV(vec); + if (PyVecTo(value, vec)) { + self->m_vertex->SetUV1(vec); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -495,13 +494,13 @@ PyObject *KX_VertexProxy::PySetNormal(PyObject *value) PyObject *KX_VertexProxy::PyGetRGBA() { int *rgba = (int *) m_vertex->getRGBA(); - return PyLong_FromSsize_t(*rgba); + return PyLong_FromLong(*rgba); } PyObject *KX_VertexProxy::PySetRGBA(PyObject *value) { if (PyLong_Check(value)) { - int rgba = PyLong_AsSsize_t(value); + int rgba = PyLong_AsLong(value); m_vertex->SetRGBA(rgba); m_mesh->SetMeshModified(true); Py_RETURN_NONE; @@ -521,18 +520,18 @@ PyObject *KX_VertexProxy::PySetRGBA(PyObject *value) } -PyObject *KX_VertexProxy::PyGetUV() +PyObject *KX_VertexProxy::PyGetUV1() { return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); } -PyObject *KX_VertexProxy::PySetUV(PyObject *value) +PyObject *KX_VertexProxy::PySetUV1(PyObject *value) { MT_Point2 vec; if (!PyVecTo(value, vec)) return NULL; - m_vertex->SetUV(vec); + m_vertex->SetUV1(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 6e193d35b4c..4247d138a66 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -92,8 +92,8 @@ public: KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); - KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV); - KX_PYMETHOD_O(KX_VertexProxy,SetUV); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV1); + KX_PYMETHOD_O(KX_VertexProxy,SetUV1); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV2); KX_PYMETHOD_VARARGS(KX_VertexProxy,SetUV2); diff --git a/source/gameengine/Network/NG_NetworkDeviceInterface.h b/source/gameengine/Network/NG_NetworkDeviceInterface.h index 48edbdfc7fe..6da478ecda5 100644 --- a/source/gameengine/Network/NG_NetworkDeviceInterface.h +++ b/source/gameengine/Network/NG_NetworkDeviceInterface.h @@ -43,8 +43,8 @@ private: // candidates for shared/common implementation class bool m_online; public: - NG_NetworkDeviceInterface() {}; - virtual ~NG_NetworkDeviceInterface() {}; + NG_NetworkDeviceInterface() {} + virtual ~NG_NetworkDeviceInterface() {} virtual void NextFrame()=0; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 8d587cf39f6..6c6ce94d8d5 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1507,8 +1507,8 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == false) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; @@ -1816,8 +1816,8 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == false) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } MFace *mf; diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index d1a8143fa88..d1fabba18f9 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -85,8 +85,9 @@ void DummyPhysicsEnvironment::setGravity(float x,float y,float z) { } - - +void DummyPhysicsEnvironment::getGravity(PHY__Vector3& grav) +{ +} diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index 233c4412d9e..5ce34bdf7cf 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -56,6 +56,7 @@ public: virtual float getFixedTimeStep(); virtual void setGravity(float x,float y,float z); + virtual void getGravity(PHY__Vector3& grav); virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, float pivotX,float pivotY,float pivotZ, diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 077d225903c..bfbe570ad0c 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -143,6 +143,7 @@ class PHY_IPhysicsEnvironment virtual void setUseEpa(bool epa) {} virtual void setGravity(float x,float y,float z)=0; + virtual void getGravity(PHY__Vector3& grav) = 0; virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, float pivotX,float pivotY,float pivotZ, diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h index 53195d79768..60b9f052075 100644 --- a/source/gameengine/Rasterizer/RAS_ICanvas.h +++ b/source/gameengine/Rasterizer/RAS_ICanvas.h @@ -59,7 +59,7 @@ public: virtual ~RAS_ICanvas( ) { - }; + } virtual void diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 16ecffb9a32..4c72f128817 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -189,6 +189,8 @@ class RAS_MeshMaterial public: RAS_MeshSlot *m_baseslot; class RAS_MaterialBucket *m_bucket; + + /* the KX_GameObject is used as a key here */ CTR_Map m_slots; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index 5f3af7360ff..63b28a90412 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -8,7 +8,7 @@ defs = [ 'GLEW_STATIC' ] incs = '. #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines ' incs += ' #intern/container #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC'] incs += ' #source/blender/gameengine/Ketsji #source/gameengine/SceneGraph #source/blender/makesdna #source/blender/blenkernel' -incs += ' #intern/guardedalloc #source/blender/blenlib #source/gameengine/BlenderRoutines' +incs += ' #intern/guardedalloc #source/blender/blenlib' if env['WITH_BF_CXX_GUARDEDALLOC']: defs.append('WITH_CXX_GUARDEDALLOC') diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index b60fae73e2a..945644ff3e6 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -63,10 +63,10 @@ const MT_Point3& RAS_TexVert::xyz() void RAS_TexVert::SetRGBA(const MT_Vector4& rgba) { unsigned char *colp = (unsigned char*) &m_rgba; - colp[0] = (unsigned char) (rgba[0]*255.0f); - colp[1] = (unsigned char) (rgba[1]*255.0f); - colp[2] = (unsigned char) (rgba[2]*255.0f); - colp[3] = (unsigned char) (rgba[3]*255.0f); + colp[0] = (unsigned char) (rgba[0] * 255.0); + colp[1] = (unsigned char) (rgba[1] * 255.0); + colp[2] = (unsigned char) (rgba[2] * 255.0); + colp[3] = (unsigned char) (rgba[3] * 255.0); } @@ -75,21 +75,32 @@ void RAS_TexVert::SetXYZ(const MT_Point3& xyz) xyz.getValue(m_localxyz); } -void RAS_TexVert::SetXYZ(const float *xyz) +void RAS_TexVert::SetXYZ(const float xyz[3]) { m_localxyz[0] = xyz[0]; m_localxyz[1] = xyz[1]; m_localxyz[2] = xyz[2]; } -void RAS_TexVert::SetUV(const MT_Point2& uv) +void RAS_TexVert::SetUV1(const MT_Point2& uv) { uv.getValue(m_uv1); } +void RAS_TexVert::SetUV1(const float uv[3]) +{ + m_uv1[0] = uv[0]; + m_uv1[1] = uv[1]; +} + void RAS_TexVert::SetUV2(const MT_Point2& uv) { uv.getValue(m_uv2); } +void RAS_TexVert::SetUV2(const float uv[3]) +{ + m_uv2[0] = uv[0]; + m_uv2[1] = uv[1]; +} void RAS_TexVert::SetRGBA(const unsigned int rgba) { @@ -151,3 +162,12 @@ void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat) SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue()); } +void RAS_TexVert::TransformUV1(const MT_Matrix4x4& mat) +{ + SetUV1((mat * MT_Vector4(m_uv1[0], m_uv1[1], 0.0, 1.0)).getValue()); +} + +void RAS_TexVert::TransformUV2(const MT_Matrix4x4& mat) +{ + SetUV2((mat * MT_Vector4(m_uv2[0], m_uv2[1], 0.0, 1.0)).getValue()); +} diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index 889769da5ed..98ea4dd60aa 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -122,9 +122,11 @@ public: } void SetXYZ(const MT_Point3& xyz); - void SetXYZ(const float *xyz); - void SetUV(const MT_Point2& uv); + void SetXYZ(const float xyz[3]); + void SetUV1(const MT_Point2& uv); void SetUV2(const MT_Point2& uv); + void SetUV1(const float uv[2]); + void SetUV2(const float uv[2]); void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); @@ -137,6 +139,8 @@ public: void Transform(const class MT_Matrix4x4& mat, const class MT_Matrix4x4& nmat); + void TransformUV1(const MT_Matrix4x4& mat); + void TransformUV2(const MT_Matrix4x4& mat); // compare two vertices, to test if they can be shared, used for // splitting up based on uv's, colors, etc diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h index 885eb8e1e90..72a04064834 100644 --- a/source/gameengine/SceneGraph/SG_IObject.h +++ b/source/gameengine/SceneGraph/SG_IObject.h @@ -127,8 +127,8 @@ struct SG_Callbacks m_schedulefunc(NULL), m_reschedulefunc(NULL) { - }; - + } + SG_Callbacks( SG_ReplicationNewCallback repfunc, SG_DestructionNewCallback destructfunc, @@ -142,7 +142,7 @@ struct SG_Callbacks m_schedulefunc(schedulefunc), m_reschedulefunc(reschedulefunc) { - }; + } SG_ReplicationNewCallback m_replicafunc; SG_DestructionNewCallback m_destructionfunc; @@ -152,8 +152,8 @@ struct SG_Callbacks }; /** -base object that can be part of the scenegraph. -*/ + * base object that can be part of the scenegraph. + */ class SG_IObject : public SG_QList { private : diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h index e19aadc49d2..28eebe07789 100644 --- a/source/gameengine/VideoTexture/BlendType.h +++ b/source/gameengine/VideoTexture/BlendType.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file BlendType.h * \ingroup bgevideotex */ - + #ifndef __BLENDTYPE_H__ #define __BLENDTYPE_H__ diff --git a/source/gameengine/VideoTexture/Common.h b/source/gameengine/VideoTexture/Common.h index e6e0ffa1ebc..90f7e66452a 100644 --- a/source/gameengine/VideoTexture/Common.h +++ b/source/gameengine/VideoTexture/Common.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file VideoTexture/Common.h * \ingroup bgevideotex */ - + #if defined WIN32 #define WINDOWS_LEAN_AND_MEAN #endif diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp index 8609cd73875..8b8918d8141 100644 --- a/source/gameengine/VideoTexture/Exception.cpp +++ b/source/gameengine/VideoTexture/Exception.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/Exception.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/Exception.h b/source/gameengine/VideoTexture/Exception.h index bc08742de8d..e0c1fdd568d 100644 --- a/source/gameengine/VideoTexture/Exception.h +++ b/source/gameengine/VideoTexture/Exception.h @@ -1,30 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ - + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file Exception.h * \ingroup bgevideotex */ - + #ifndef __EXCEPTION_H__ #define __EXCEPTION_H__ diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp index 6ec5e237ac2..a232bcc1201 100644 --- a/source/gameengine/VideoTexture/FilterBase.cpp +++ b/source/gameengine/VideoTexture/FilterBase.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterBase.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h index 98bc495375a..f8fe2c772f0 100644 --- a/source/gameengine/VideoTexture/FilterBase.h +++ b/source/gameengine/VideoTexture/FilterBase.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterBase.h * \ingroup bgevideotex */ - + #ifndef __FILTERBASE_H__ #define __FILTERBASE_H__ diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 8559e8f87f4..662ecabd283 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterBlueScreen.cpp * \ingroup bgevideotex @@ -83,18 +87,21 @@ static PyObject *getColor (PyFilter *self, void *closure) static int setColor (PyFilter *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 3 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))) + if (value == NULL || + !(PyTuple_Check(value) || PyList_Check(value)) || + PySequence_Fast_GET_SIZE(value) != 3 || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints"); return -1; } // set color - getFilter(self)->setColor((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)))); + getFilter(self)->setColor( + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2)))); // success return 0; } @@ -110,16 +117,19 @@ static PyObject *getLimits (PyFilter *self, void *closure) static int setLimits (PyFilter *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) + if (value == NULL || + !(PyTuple_Check(value) || PyList_Check(value)) || + PySequence_Fast_GET_SIZE(value) != 2 || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set limits - getFilter(self)->setLimits((unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1)))); + getFilter(self)->setLimits( + (unsigned short)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned short)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1)))); // success return 0; } @@ -159,14 +169,14 @@ PyTypeObject FilterBlueScreenType = 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ "Filter for Blue Screen objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - NULL, /* tp_methods */ - 0, /* tp_members */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + NULL, /* tp_methods */ + 0, /* tp_members */ filterBSGetSets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.h b/source/gameengine/VideoTexture/FilterBlueScreen.h index 28ab16d966e..5a90590a39d 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.h +++ b/source/gameengine/VideoTexture/FilterBlueScreen.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterBlueScreen.h * \ingroup bgevideotex */ - + #ifndef __FILTERBLUESCREEN_H__ #define __FILTERBLUESCREEN_H__ diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index 35a6414f383..e4101b5587d 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterColor.cpp * \ingroup bgevideotex @@ -147,7 +151,7 @@ static int setMatrix (PyFilter *self, PyObject *value, void *closure) valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - mat[r][c] = short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c))); + mat[r][c] = short(PyLong_AsLong(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error @@ -280,7 +284,7 @@ static int setLevels (PyFilter *self, PyObject *value, void *closure) valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - lev[r][c] = (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c))); + lev[r][c] = (unsigned short)(PyLong_AsLong(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error diff --git a/source/gameengine/VideoTexture/FilterColor.h b/source/gameengine/VideoTexture/FilterColor.h index cd61900bbda..350f7270874 100644 --- a/source/gameengine/VideoTexture/FilterColor.h +++ b/source/gameengine/VideoTexture/FilterColor.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterColor.h * \ingroup bgevideotex */ - + #ifndef __FILTERCOLOR_H__ #define __FILTERCOLOR_H__ diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index 03c500a7e14..ba963d93079 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterNormal.cpp * \ingroup bgevideotex @@ -81,7 +85,7 @@ static int setColor (PyFilter *self, PyObject *value, void *closure) return -1; } // set color index - getFilter(self)->setColor((unsigned short)(PyLong_AsSsize_t(value))); + getFilter(self)->setColor((unsigned short)(PyLong_AsLong(value))); // success return 0; } diff --git a/source/gameengine/VideoTexture/FilterNormal.h b/source/gameengine/VideoTexture/FilterNormal.h index 19664e8b5f2..b21afb3ec26 100644 --- a/source/gameengine/VideoTexture/FilterNormal.h +++ b/source/gameengine/VideoTexture/FilterNormal.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterNormal.h * \ingroup bgevideotex */ - + #ifndef __FILTERNORMAL_H__ #define __FILTERNORMAL_H__ diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp index e5fe4711cff..1fac87f2b04 100644 --- a/source/gameengine/VideoTexture/FilterSource.cpp +++ b/source/gameengine/VideoTexture/FilterSource.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterSource.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h index cb9e22a133d..f1d2615ee32 100644 --- a/source/gameengine/VideoTexture/FilterSource.h +++ b/source/gameengine/VideoTexture/FilterSource.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterSource.h * \ingroup bgevideotex */ - + #ifndef __FILTERSOURCE_H__ #define __FILTERSOURCE_H__ diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index de54d8e8940..3b6dec21e52 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageBase.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h index a9f25f61406..3bb9c8cb090 100644 --- a/source/gameengine/VideoTexture/ImageBase.h +++ b/source/gameengine/VideoTexture/ImageBase.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageBase.h * \ingroup bgevideotex */ - + #ifndef __IMAGEBASE_H__ #define __IMAGEBASE_H__ diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp index eec0bccbe56..1593a08bb4b 100644 --- a/source/gameengine/VideoTexture/ImageBuff.cpp +++ b/source/gameengine/VideoTexture/ImageBuff.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageBuff.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/ImageBuff.h b/source/gameengine/VideoTexture/ImageBuff.h index b2bdbc17dc9..19299506747 100644 --- a/source/gameengine/VideoTexture/ImageBuff.h +++ b/source/gameengine/VideoTexture/ImageBuff.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageBuff.h * \ingroup bgevideotex */ - + #ifndef __IMAGEBUFF_H__ #define __IMAGEBUFF_H__ diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp index f09454a517b..27c4fed6fe6 100644 --- a/source/gameengine/VideoTexture/ImageMix.cpp +++ b/source/gameengine/VideoTexture/ImageMix.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageMix.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/ImageMix.h b/source/gameengine/VideoTexture/ImageMix.h index 2746635c611..712efde7dd4 100644 --- a/source/gameengine/VideoTexture/ImageMix.h +++ b/source/gameengine/VideoTexture/ImageMix.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageMix.h * \ingroup bgevideotex */ - + #ifndef __IMAGEMIX_H__ #define __IMAGEMIX_H__ diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 85857165403..f778f840864 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageRender.cpp * \ingroup bgevideotex @@ -356,10 +360,11 @@ static int setBackground (PyImage *self, PyObject *value, void *closure) return -1; } // set background color - getImageRender(self)->setBackground((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 3)))); + getImageRender(self)->setBackground( + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 3)))); // success return 0; } @@ -375,7 +380,7 @@ static PyMethodDef imageRenderMethods[] = static PyGetSetDef imageRenderGetSets[] = { {(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL}, - // attribute from ImageViewport + // attribute from ImageViewport {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL}, {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL}, {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL}, diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h index df6337e1c24..27882a9d117 100644 --- a/source/gameengine/VideoTexture/ImageRender.h +++ b/source/gameengine/VideoTexture/ImageRender.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageRender.h * \ingroup bgevideotex */ - + #ifndef __IMAGERENDER_H__ #define __IMAGERENDER_H__ diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index af44e394fce..5fc388bdefb 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageViewport.cpp * \ingroup bgevideotex @@ -85,7 +89,7 @@ void ImageViewport::setWhole (bool whole) setPosition(); } -void ImageViewport::setCaptureSize (short * size) +void ImageViewport::setCaptureSize (short size[2]) { m_whole = false; if (size == NULL) @@ -105,7 +109,7 @@ void ImageViewport::setCaptureSize (short * size) } // set position of capture rectangle -void ImageViewport::setPosition (GLint * pos) +void ImageViewport::setPosition (GLint pos[2]) { // if new position is not provided, use existing position if (pos == NULL) pos = m_position; @@ -254,25 +258,30 @@ int ImageViewport_setAlpha (PyImage *self, PyObject *value, void *closure) // get position static PyObject *ImageViewport_getPosition (PyImage *self, void *closure) { - return Py_BuildValue("(ii)", getImageViewport(self)->getPosition()[0], - getImageViewport(self)->getPosition()[1]); + GLint *pos = getImageViewport(self)->getPosition(); + PyObject *ret = PyTuple_New(2); + PyTuple_SET_ITEM(ret, 0, PyLong_FromLong(pos[0])); + PyTuple_SET_ITEM(ret, 1, PyLong_FromLong(pos[1])); + return ret; } // set position static int ImageViewport_setPosition (PyImage *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) + if (value == NULL || + !(PyTuple_Check(value) || PyList_Check(value)) || + PySequence_Fast_GET_SIZE(value) != 2 || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set position - GLint pos [] = { - GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) + GLint pos[2] = { + GLint(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + GLint(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))) }; getImageViewport(self)->setPosition(pos); // success @@ -282,25 +291,30 @@ static int ImageViewport_setPosition (PyImage *self, PyObject *value, void *clos // get capture size PyObject *ImageViewport_getCaptureSize (PyImage *self, void *closure) { - return Py_BuildValue("(ii)", getImageViewport(self)->getCaptureSize()[0], - getImageViewport(self)->getCaptureSize()[1]); + short *size = getImageViewport(self)->getCaptureSize(); + PyObject *ret = PyTuple_New(2); + PyTuple_SET_ITEM(ret, 0, PyLong_FromLong(size[0])); + PyTuple_SET_ITEM(ret, 1, PyLong_FromLong(size[1])); + return ret; } // set capture size int ImageViewport_setCaptureSize (PyImage *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) + if (value == NULL || + !(PyTuple_Check(value) || PyList_Check(value)) || + PySequence_Fast_GET_SIZE(value) != 2 || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set capture size - short size [] = { - short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) + short size[2] = { + short(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + short(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))) }; try { diff --git a/source/gameengine/VideoTexture/ImageViewport.h b/source/gameengine/VideoTexture/ImageViewport.h index 198655c6ebf..5afd4654d62 100644 --- a/source/gameengine/VideoTexture/ImageViewport.h +++ b/source/gameengine/VideoTexture/ImageViewport.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageViewport.h * \ingroup bgevideotex */ - + #ifndef __IMAGEVIEWPORT_H__ #define __IMAGEVIEWPORT_H__ @@ -56,12 +60,12 @@ public: /// get capture size in viewport short * getCaptureSize (void) { return m_capSize; } /// set capture size in viewport - void setCaptureSize (short * size = NULL); + void setCaptureSize (short size[2] = NULL); /// get position in viewport GLint * getPosition (void) { return m_position; } /// set position in viewport - void setPosition (GLint * pos = NULL); + void setPosition (GLint pos[2] = NULL); protected: /// frame buffer rectangle diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp index 9fe98544961..96ac1cc5b6b 100644 --- a/source/gameengine/VideoTexture/PyTypeList.cpp +++ b/source/gameengine/VideoTexture/PyTypeList.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/PyTypeList.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/PyTypeList.h b/source/gameengine/VideoTexture/PyTypeList.h index 4872b3c3d5c..b36f11ed75a 100644 --- a/source/gameengine/VideoTexture/PyTypeList.h +++ b/source/gameengine/VideoTexture/PyTypeList.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file PyTypeList.h * \ingroup bgevideotex */ - + #ifndef __PYTYPELIST_H__ #define __PYTYPELIST_H__ diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index f58d17f949c..98d36d19ddf 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/Texture.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h index cc265725b29..157eea56c09 100644 --- a/source/gameengine/VideoTexture/Texture.h +++ b/source/gameengine/VideoTexture/Texture.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file VideoTexture/Texture.h * \ingroup bgevideotex */ - + #ifndef __TEXTURE_H__ #define __TEXTURE_H__ diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp index 1eb2e830d37..576e358fe75 100644 --- a/source/gameengine/VideoTexture/VideoBase.cpp +++ b/source/gameengine/VideoTexture/VideoBase.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/VideoBase.cpp * \ingroup bgevideotex @@ -180,7 +184,7 @@ int Video_setRepeat(PyImage *self, PyObject *value, void *closure) return -1; } // set repeat - getVideo(self)->setRepeat(int(PyLong_AsSsize_t(value))); + getVideo(self)->setRepeat(int(PyLong_AsLong(value))); // success return 0; } diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h index 4cf913d755d..9880165c198 100644 --- a/source/gameengine/VideoTexture/VideoBase.h +++ b/source/gameengine/VideoTexture/VideoBase.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file VideoBase.h * \ingroup bgevideotex */ - + #ifndef __VIDEOBASE_H__ #define __VIDEOBASE_H__ diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 3f42d5c4fed..8976a21376a 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/VideoFFmpeg.cpp * \ingroup bgevideotex @@ -1138,7 +1142,7 @@ static int VideoFFmpeg_setPreseek(PyImage *self, PyObject *value, void *closure) return -1; } // set preseek - getFFmpeg(self)->setPreseek(PyLong_AsSsize_t(value)); + getFFmpeg(self)->setPreseek(PyLong_AsLong(value)); // success return 0; } diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index d5b575851ee..92043bb1f74 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file VideoFFmpeg.h * \ingroup bgevideotex */ - + #ifndef __VIDEOFFMPEG_H__ #define __VIDEOFFMPEG_H__ diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index dd9d83c043f..72415026bb9 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/blendVideoTex.cpp * \ingroup bgevideotex diff --git a/source/tests/bl_rst_completeness.py b/source/tests/bl_rst_completeness.py new file mode 100644 index 00000000000..e9e2779bda8 --- /dev/null +++ b/source/tests/bl_rst_completeness.py @@ -0,0 +1,159 @@ +# ##### 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 ##### + +# + +# run this script in the game engine. +# or on the command line with... +# ./blender.bin --background -noaudio --python source/tests/bl_rst_completeness.py + +# Paste this into the bge and run on an always actuator. +''' +filepath = "/dsk/data/src/blender/blender/source/tests/bl_rst_completeness.py" +exec(compile(open(filepath).read(), filepath, 'exec')) +''' + +import os + +THIS_DIR = os.path.dirname(__file__) +RST_DIR = os.path.normpath(os.path.join(THIS_DIR, "..", "..", "doc", "python_api", "rst")) + +import sys +sys.path.append(THIS_DIR) + +import rst_to_doctree_mini + +try: + import bge +except: + bge = None + +# (file, module) +modules = ( + ("bge.constraints.rst", "bge.constraints", False), + ("bge.events.rst", "bge.events", False), + ("bge.logic.rst", "bge.logic", False), + ("bge.render.rst", "bge.render", False), + ("bge.texture.rst", "bge.texture", False), + ("bge.types.rst", "bge.types", False), + + ("bgl.rst", "bgl", True), + ("gpu.rst", "gpu", False), +) + +def is_directive_pydata(filepath, directive): + if directive.type in {"function", "method", "class", "attribute", "data"}: + return True + elif directive.type in {"module", "note", "warning", "code-block", "hlist", "seealso"}: + return False + elif directive.type in {"literalinclude"}: # TODO + return False + else: + print(directive_to_str(filepath, directive), end=" ") + print("unknown directive type %r" % directive.type) + return False + + +def directive_to_str(filepath, directive): + return "%s:%d:%d:" % (filepath, directive.line + 1, directive.indent) + + +def directive_members_dict(filepath, directive_members): + return {directive.value_strip: directive for directive in directive_members + if is_directive_pydata(filepath, directive)} + + +def module_validate(filepath, mod, mod_name, doctree, partial_ok): + # RST member missing from MODULE ??? + for directive in doctree: + # print(directive.type) + if is_directive_pydata(filepath, directive): + attr = directive.value_strip + has_attr = hasattr(mod, attr) + ok = False + if not has_attr: + # so we can have glNormal docs cover glNormal3f + if partial_ok: + for s in dir(mod): + if s.startswith(attr): + ok = True + break + + if not ok: + print(directive_to_str(filepath, directive), end=" ") + print("rst contains non existing member %r" % attr) + + # if its a class, scan down the class... + # print(directive.type) + if has_attr: + if directive.type == "class": + cls = getattr(mod, attr) + # print("directive: ", directive) + for directive_child in directive.members: + # print("directive_child: ", directive_child) + if is_directive_pydata(filepath, directive_child): + attr_child = directive_child.value_strip + if attr_child not in cls.__dict__: + attr_id = "%s.%s" % (attr, attr_child) + print(directive_to_str(filepath, directive_child), end=" ") + print("rst contains non existing class member %r" % attr_id) + + + # MODULE member missing from RST ??? + doctree_dict = directive_members_dict(filepath, doctree) + for attr in dir(mod): + if attr.startswith("_"): + continue + + directive = doctree_dict.get(attr) + if directive is None: + print("module contains undocumented member %r from %r" % ("%s.%s" % (mod_name, attr), filepath)) + else: + if directive.type == "class": + directive_dict = directive_members_dict(filepath, directive.members) + cls = getattr(mod, attr) + for attr_child in cls.__dict__.keys(): + if attr_child.startswith("_"): + continue + if attr_child not in directive_dict: + attr_id = "%s.%s.%s" % (mod_name, attr, attr_child), filepath + print("module contains undocumented member %r from %r" % attr_id) + + +def main(): + + if bge is None: + print("Skipping BGE modules!") + + for filename, modname, partial_ok in modules: + if bge is None and modname.startswith("bge"): + continue + + filepath = os.path.join(RST_DIR, filename) + if not os.path.exists(filepath): + raise Exception("%r not found" % filepath) + + doctree = rst_to_doctree_mini.parse_rst_py(filepath) + __import__(modname) + mod = sys.modules[modname] + + module_validate(filepath, mod, modname, doctree, partial_ok) + + +if __name__ == "__main__": + main() diff --git a/source/tests/bl_run_operators.py b/source/tests/bl_run_operators.py index f792b83a8cd..5bb25537458 100644 --- a/source/tests/bl_run_operators.py +++ b/source/tests/bl_run_operators.py @@ -35,13 +35,16 @@ op_blacklist = ( "*.open_*", "*.link_append", "render.render", + "render.play_rendered_anim", "*.*_export", "*.*_import", "wm.blenderplayer_start", "wm.url_open", "wm.doc_view", "wm.path_open", - "help.operator_cheat_sheet", + "wm.theme_install", + "wm.context_*", + "wm.operator_cheat_sheet", "wm.keyconfig_test", # just annoying - but harmless "wm.memory_statistics", # another annoying one "console.*", # just annoying - but harmless diff --git a/source/tests/rst_to_doctree_mini.py b/source/tests/rst_to_doctree_mini.py new file mode 100644 index 00000000000..181037299cf --- /dev/null +++ b/source/tests/rst_to_doctree_mini.py @@ -0,0 +1,91 @@ +# ##### 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 ##### + +# + +# Module with function to extract a doctree from an reStructuredText file. +# Named 'Mini' because we only parse the minimum data needed to check +# Python classes, methods and attributes match up to those in existing modules. +# (To test for documentation completeness) + +# note: literalinclude's are not followed. +# could be nice to add but not really needed either right now. + +import collections + +Directive = collections.namedtuple('Directive', + ("type", + "value", + "value_strip", + "line", + "indent", + "members")) + + +def parse_rst_py(filepath): + import re + + # Get the prefix assuming the line is lstrip()'d + # ..foo:: bar + # --> + # ("foo", "bar") + re_prefix = re.compile(r"^\.\.\s([a-zA-Z09\-]+)::\s*(.*)\s*$") + + tree = collections.defaultdict(list) + indent_map = {} + indent_prev = 0 + f = open(filepath, encoding="utf-8") + indent_lists = [] + for i, line in enumerate(f): + line_strip = line.lstrip() + # ^\.\.\s[a-zA-Z09\-]+::.*$ + #if line.startswith(".. "): + march = re_prefix.match(line_strip) + + if march: + directive, value = march.group(1, 2) + indent = len(line) - len(line_strip) + value_strip = value.replace("(", " ").split() + value_strip = value_strip[0] if value_strip else "" + + item = Directive(type=directive, + value=value, + value_strip=value_strip, + line=i, + indent=indent, + members=[]) + + tree[indent].append(item) + if indent_prev < indent: + indent_map[indent] = indent_prev + if indent > 0: + tree[indent_map[indent]][-1].members.append(item) + indent_prev = indent + f.close() + + return tree[0] + + +if __name__ == "__main__": + # not intended use, but may as well print rst files passed as a test. + import sys + for arg in sys.argv: + if arg.lower().endswith((".txt", ".rst")): + items = parse_rst_py(arg) + for i in items: + print(i)