diff options
259 files changed, 4511 insertions, 2596 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 751c2dd548e..0954d5ce878 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 @@ -271,6 +271,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" @@ -487,14 +490,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 @@ -522,7 +525,7 @@ if(UNIX AND NOT APPLE) 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, @@ -755,7 +758,6 @@ 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() @@ -872,7 +874,7 @@ elseif(WIN32) # Setup 64bit and 64bit windows systems 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() @@ -928,8 +930,6 @@ 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) @@ -939,9 +939,6 @@ elseif(WIN32) 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() @@ -1102,9 +1099,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}) @@ -1212,7 +1217,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() @@ -1284,9 +1289,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}") @@ -1605,9 +1610,6 @@ elseif(APPLE) find_library(LLVM_LIBRARY 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) @@ -1619,7 +1621,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() @@ -1628,8 +1629,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) @@ -1640,9 +1639,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() diff --git a/SConstruct b/SConstruct index 5a1797ec1dc..d6972de8cab 100644 --- a/SConstruct +++ b/SConstruct @@ -312,6 +312,9 @@ if env['OURPLATFORM']=='darwin': 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') diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 935f37b53da..f8cef63f301 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -188,9 +188,14 @@ detect_distro() { prepare_opt() { INFO "Ensuring $INST exists and is writable by us" - sudo mkdir -p $INST - sudo chown $USER $INST - sudo chmod 775 $INST + 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... @@ -407,6 +412,7 @@ compile_OIIO() { prepare_opt if [ ! -d $_src ]; then + mkdir -p $SRC wget -c $OIIO_SOURCE -O "$_src.tar.gz" INFO "Unpacking OpenImageIO-$OIIO_VERSION" @@ -450,12 +456,16 @@ EOF 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" - cmake_d="$cmake_d -D LINKSTATIC=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" + cmake_d="$cmake_d -D Boost_USE_STATIC_LIBS=ON" fi fi @@ -513,6 +523,7 @@ compile_LLVM() { 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" @@ -603,6 +614,8 @@ compile_OSL() { 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" @@ -692,6 +705,7 @@ compile_FFmpeg() { 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" @@ -811,6 +825,29 @@ install_DEB() { INFO "$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 + 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 @@ -825,7 +862,7 @@ install_DEB() { 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 $SCHRO_DEV $THEORA_DEV $VORBIS_DEV libsdl1.2-dev \ - libfftw3-dev libjack-dev python-dev patch + libfftw3-dev libjack-dev python-dev patch bzip2 OPENJPEG_USE=true SCHRO_USE=true diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py index e5afa2afe13..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 @@ -160,6 +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 dc901d25a92..420d9ed4db9 100644 --- a/build_files/buildbot/config/user-config-glibc211-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py @@ -159,6 +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 dd3a63d0fd7..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 @@ -145,6 +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 d9e50d258bc..7359e155586 100644 --- a/build_files/buildbot/config/user-config-glibc27-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc27-x86_64.py @@ -144,6 +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 00bfdbb16f2..96f201235c4 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py @@ -117,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 f6eef4f89d9..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 @@ -117,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 1e834c0c8d2..82b105c4527 100644 --- a/build_files/buildbot/config/user-config-player-glibc27-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc27-i686.py @@ -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 aa0a69c44d8..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 @@ -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/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py index 83ebf927b3c..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 ***** # 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 db4e762932e..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 ***** # diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py index 518b94d74a5..12369a5e8cd 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 ***** # diff --git a/build_files/cmake/cmake_static_check_smatch.py b/build_files/cmake/cmake_static_check_smatch.py index 8f7bd37d4c3..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 ***** # diff --git a/build_files/cmake/cmake_static_check_sparse.py b/build_files/cmake/cmake_static_check_sparse.py index 92d590e52ac..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 ***** # diff --git a/build_files/cmake/cmake_static_check_splint.py b/build_files/cmake/cmake_static_check_splint.py index d3f22191021..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 ***** # 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/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/freebsd7-config.py b/build_files/scons/config/freebsd7-config.py index 61358de12b4..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}' diff --git a/build_files/scons/config/freebsd8-config.py b/build_files/scons/config/freebsd8-config.py index 0f6c7f64786..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}' diff --git a/build_files/scons/config/freebsd9-config.py b/build_files/scons/config/freebsd9-config.py index c0df68f99ad..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}' diff --git a/build_files/scons/config/linuxcross-config.py b/build_files/scons/config/linuxcross-config.py index 63264807720..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' diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py index 80e3592c71e..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' diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py index 2120938ec71..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' diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py index fdfd792f180..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 diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py index 15bcdf999bd..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' diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index 2e0c81126b4..6f6308867b6 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -166,10 +166,12 @@ 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']: @@ -293,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']: diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index ab963d4543c..19f4ac9a1de 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -119,7 +119,8 @@ def validate_arguments(args, bc): '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', @@ -393,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', ''), 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/python_api/examples/bmesh.ops.1.py b/doc/python_api/examples/bmesh.ops.1.py new file mode 100644 index 00000000000..2eefb63a23d --- /dev/null +++ b/doc/python_api/examples/bmesh.ops.1.py @@ -0,0 +1,106 @@ +# 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) + +# 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 acf28706709..7d20aa31a36 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -416,9 +416,9 @@ Sensor Status .. data:: KX_SENSOR_ACTIVE .. data:: KX_SENSOR_JUST_DEACTIVATED -------------- +--------------- Armature Sensor -------------- +--------------- .. _armaturesensor-type: @@ -537,9 +537,9 @@ See :class:`bge.types.BL_ActionActuator` .. data:: KX_ACTIONACT_LOOPEND .. data:: KX_ACTIONACT_PROPERTY ---------------- +----------------- Armature Actuator ---------------- +----------------- .. _armatureactuator-constants-type: @@ -556,13 +556,13 @@ See :class:`bge.types.BL_ArmatureActuator.type` .. 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 @@ -809,9 +809,9 @@ See :class:`bge.types.KX_SoundActuator` :value: 6 --------------- +----------------- Steering Actuator --------------- +----------------- .. _logic-steering-actuator: @@ -961,9 +961,9 @@ See :class:`bge.types.BL_ArmatureChannel.rotation_mode` :value: 6 ----------------- +------------------- Armature Constraint ----------------- +------------------- .. _armatureconstraint-constants-type: See :class:`bge.types.BL_ArmatureConstraint.type` @@ -1075,9 +1075,9 @@ See :class:`bge.types.SCA_PythonKeyboard`, :class:`bge.types.SCA_PythonMouse`, : .. data:: KX_INPUT_ACTIVE .. data:: KX_INPUT_JUST_RELEASED ------------- +------------- KX_GameObject ------------ +------------- .. _gameobject-playaction-mode: See :class:`bge.types.KX_GameObject.playAction` @@ -1111,9 +1111,9 @@ See :class:`bge.types.SCA_MouseSensor` .. data:: KX_MOUSE_BUT_MIDDLE .. data:: KX_MOUSE_BUT_RIGHT ------------- +-------------------------- Navigation Mesh Draw Modes ------------- +-------------------------- .. _navmesh-draw-mode: @@ -1199,25 +1199,25 @@ 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 f7a63b48f61..8cf9ccb794c 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -759,6 +759,10 @@ 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 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 ##### + +# <pep8 compliant> + +# 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 782e0c6daaa..dd7019d43a3 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", @@ -298,7 +299,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")) @@ -1480,6 +1481,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) @@ -1541,13 +1547,17 @@ def write_rst_contents(basepath): # misc "Freestyle", "bgl", "blf", "gpu", "aud", "bpy_extras", # bmesh - "bmesh", "bmesh.types", "bmesh.utils", + "bmesh", "bmesh.types", "bmesh.utils", "bmesh.ops", ) 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)) @@ -1710,6 +1720,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", ] 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/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 7495a98aed1..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 diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index 1a127e364fe..a0e2650ddc6 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -49,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()) diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index e8fa5c0ff3d..95263ebe463 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -360,8 +360,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) bool emitter_hide = false; if(b_dup_ob.is_duplicator()) { - /* duplicators hidden by default */ - emitter_hide = true; + /* 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; diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h index a2df77c2d2b..575a798aed4 100644 --- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -131,7 +131,7 @@ __device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colors } } } - return LABEL_REFLECT; + return LABEL_REFLECT|LABEL_GLOSSY; } diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index abc63d99c74..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); 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_types.h b/intern/cycles/kernel/kernel_types.h index 977fb8c4fd4..f519fd989fa 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__ @@ -112,13 +113,9 @@ CCL_NAMESPACE_BEGIN #define __AO__ #define __CAMERA_MOTION__ #define __ANISOTROPIC__ - -#ifndef __KERNEL_CUDA__ #define __OBJECT_MOTION__ #endif -#endif - //#define __SOBOL_FULL_SCREEN__ /* Shader Evaluation */ diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index e79c509b144..e593387093c 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -80,7 +80,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 @@ -106,7 +111,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 diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index abf7c041cb3..2d025f12055 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -106,6 +106,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 */ diff --git a/intern/cycles/kernel/shaders/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl index 2884c772414..e4982975c20 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), 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/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 886fce63fd4..9c79886fdca 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -401,9 +401,13 @@ __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; 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_closure.h b/intern/cycles/kernel/svm/svm_closure.h index a4f8546f62b..564c0957c68 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -50,25 +50,41 @@ __device void svm_node_glass_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(sc->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); - - /* 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); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + + 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; } @@ -159,21 +183,23 @@ __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); - - 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); + 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; } @@ -195,32 +221,36 @@ __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_glass_setup(sd, sc, type, eta, roughness, false); + sc = svm_node_closure_get_bsdf(sd, mix_weight*fresnel); - /* refraction */ - sc = svm_node_closure_get(sd); - sc->N = N; + if(sc) { + sc->N = N; + svm_node_glass_setup(sd, sc, type, eta, roughness, false); + } + /* refraction */ + 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_glass_setup(sd, sc, type, eta, roughness, true); -#else - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; + sc = svm_node_closure_get_bsdf(sd, mix_weight*(1.0f - fresnel)); - bool refract = (randb > fresnel); + if(sc) { + sc->N = N; + svm_node_glass_setup(sd, sc, type, eta, roughness, true); + } +#else + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - svm_node_closure_set_mix_weight(sc, mix_weight); - svm_node_glass_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; @@ -230,46 +260,50 @@ __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; - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + + if(sc) { + sc->N = N; #ifdef __ANISOTROPIC__ - sc->T = stack_load_float3(stack, data_node.z); + sc->T = stack_load_float3(stack, data_node.z); - /* rotate tangent */ - float rotation = stack_load_float(stack, data_node.w); + /* rotate tangent */ + float rotation = stack_load_float(stack, data_node.w); - if(rotation != 0.0f) - sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); + 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); + /* 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); - } + 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); + sd->flag |= bsdf_ward_setup(sc); #else - sd->flag |= bsdf_diffuse_setup(sc); + sd->flag |= bsdf_diffuse_setup(sc); #endif + } break; } 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); + + if(sc) { + sc->N = N; - /* sigma */ - sc->data0 = clamp(param1, 0.0f, 1.0f); - sd->flag |= bsdf_ashikhmin_velvet_setup(sc); + /* sigma */ + sc->data0 = clamp(param1, 0.0f, 1.0f); + sd->flag |= bsdf_ashikhmin_velvet_setup(sc); + } break; } default: @@ -298,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: @@ -329,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; @@ -357,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; - } - else { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->type = CLOSURE_BACKGROUND_ID; + svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, mix_weight); } - + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, 1.0f); #else ShaderClosure *sc = &sd->closure; sc->type = CLOSURE_BACKGROUND_ID; @@ -383,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; @@ -411,15 +432,10 @@ __device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, u if(mix_weight == 0.0f) return; - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight *= mix_weight; - sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; - } - else { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; + 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; @@ -433,7 +449,8 @@ __device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, u __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_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 } } } -} - -__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]; + float4 result = make_float4(pa[n1].x, pa[n1].y, pa[n1].z, da[n1]); - voronoi(p, NODE_VORONOI_DISTANCE_SQUARED, 0, da, pa); + if(n2 != -1) + result = make_float4(pa[n2].x, pa[n2].y, pa[n2].z, da[n2]) - result; - return da[n2] - da[n1]; + return result; } -__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_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/camera.cpp b/intern/cycles/render/camera.cpp index 32c273c1248..a78ede979b2 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -202,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; } } diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index f71675dbda3..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; } } @@ -440,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(); @@ -629,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 373c7e0eaab..b79167839ab 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -118,6 +118,12 @@ 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); } @@ -134,7 +140,7 @@ public: ustring value_string; int stack_offset; /* for SVM compiler */ - bool osl_only; + int usage; }; /* Output @@ -167,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; @@ -227,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<ShaderNode* const, ShaderNode*> NodePair; @@ -241,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/nodes.cpp b/intern/cycles/render/nodes.cpp index 48a8565ed98..55fb9bf8a7e 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1124,6 +1124,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); @@ -1139,6 +1141,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); } @@ -1257,6 +1261,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); } @@ -1544,6 +1549,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); } @@ -1578,6 +1585,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); } @@ -1607,11 +1616,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()); } @@ -1625,9 +1640,10 @@ void HoldoutNode::compile(OSLCompiler& compiler) AmbientOcclusionNode::AmbientOcclusionNode() : ShaderNode("ambient_occlusion") { - add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); - + 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); } @@ -1659,6 +1675,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); } @@ -1737,7 +1754,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); @@ -1825,7 +1842,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); @@ -2315,6 +2332,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() @@ -2680,7 +2730,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); } @@ -2705,7 +2755,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); @@ -3080,7 +3130,7 @@ NormalMapNode::NormalMapNode() space = ustring("Tangent"); attribute = ustring(""); - add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + 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); @@ -3185,7 +3235,7 @@ TangentNode::TangentNode() axis = ustring("X"); attribute = ustring(""); - add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_output("Tangent", SHADER_SOCKET_NORMAL); } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 3e89c2286ad..67733142dd1 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -351,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) diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 25b4d1f08cc..d08cb07fc3c 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; @@ -222,29 +222,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) diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index c5ecddcfc15..2ec7e3d3775 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -138,6 +138,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); @@ -351,6 +352,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) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 003b722b5a5..1d1a3d54893 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -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) diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 73904eac41d..4acd174e60f 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -487,106 +487,30 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done) } } -void SVMCompiler::count_closure_users(ShaderNode *node, map<ShaderNode*, MultiClosureData>& closure_data) -{ - /* here we count the number of times each closure node is used, so that - * the last time we encounter it we can run the actually code with the - * weights from all other places added together */ - - if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { - ShaderInput *cl1in = node->input("Closure1"); - ShaderInput *cl2in = node->input("Closure2"); - - if(cl1in->link) - count_closure_users(cl1in->link->parent, closure_data); - if(cl2in->link) - count_closure_users(cl2in->link->parent, closure_data); - } - else { - MultiClosureData data; - - if(closure_data.find(node) == closure_data.end()) { - data.stack_offset = SVM_STACK_INVALID; - data.users = 1; - } - else { - data = closure_data[node]; - data.users++; - } - - closure_data[node] = data; - } -} - -void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, - map<ShaderNode*, MultiClosureData>& closure_data, uint in_offset) +void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& 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<ShaderNode*> 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, closure_data, out1_offset); - + generate_multi_closure(cl1in->link->parent, done, closure_done); if(cl2in->link) - generate_multi_closure(cl2in->link->parent, done, closure_data, out2_offset); - - if(in_offset != SVM_STACK_INVALID) - stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset); + generate_multi_closure(cl2in->link->parent, done, closure_done); } else { - MultiClosureData data = closure_data[node]; - - if(data.stack_offset == SVM_STACK_INVALID) { - /* first time using closure, use stack position for weight */ - data.stack_offset = in_offset; - } - else { - /* not first time using, add weights together */ - add_node(NODE_MATH, NODE_MATH_ADD, data.stack_offset, in_offset); - add_node(NODE_MATH, data.stack_offset); - - stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset); - } - - data.users--; - closure_data[node] = data; - - /* still users coming? skip generating closure code */ - if(data.users > 0) - return; - /* execute dependencies for closure */ foreach(ShaderInput *in, node->inputs) { if(!node_skip_input(node, in) && in->link) { @@ -596,7 +520,16 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don } } - mix_weight_offset = data.stack_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); @@ -609,12 +542,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& 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 */ - - if(data.stack_offset != SVM_STACK_INVALID) - stack_clear_offset(SHADER_SOCKET_FLOAT, data.stack_offset); } + + done.insert(node); } @@ -686,10 +616,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty set<ShaderNode*> done; if(use_multi_closure) { - map<ShaderNode*, MultiClosureData> closure_data; - - count_closure_users(clin->link->parent, closure_data); - generate_multi_closure(clin->link->parent, done, closure_data, SVM_STACK_INVALID); + set<ShaderNode*> closure_done; + generate_multi_closure(clin->link->parent, done, closure_done); } else generate_closure(clin->link->parent, done); @@ -713,9 +641,9 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& 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 c7b66d97289..0b15c5aaa1e 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -130,14 +130,7 @@ protected: void generate_closure(ShaderNode *node, set<ShaderNode*>& done); /* multi closure */ - struct MultiClosureData { - int stack_offset; - int users; - }; - - void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, - map<ShaderNode*,MultiClosureData>& closure_data, uint in_offset); - void count_closure_users(ShaderNode *node, map<ShaderNode*, MultiClosureData>& closure_data); + void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done); /* compile */ void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 4eee024990f..ca19146e125 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -246,18 +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, decomp->post.x) < 0.0f) + if(dot(decomp->mid.x, post.x) < 0.0f) decomp->mid.x = -decomp->mid.x; - if(dot(decomp->pre.x, decomp->mid.x) < 0.0f) - decomp->pre.x = -decomp->pre.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 65162ebf4e6..a1c12ddf0e1 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -41,7 +41,9 @@ typedef struct 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) */ + * rotation (4), then translation (3), then 3x3 scale matrix (9). + * + * For the DecompMotionTransform we drop scale from pre/post. */ typedef struct MotionTransform { Transform pre; @@ -49,6 +51,12 @@ typedef struct MotionTransform { Transform post; } MotionTransform; +typedef struct DecompMotionTransform { + Transform mid; + float4 pre_x, pre_y; + float4 post_x, post_y; +} DecompMotionTransform; + /* Functions */ __device_inline float3 transform_perspective(const Transform *t, const float3 a) @@ -303,6 +311,10 @@ __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); @@ -320,6 +332,7 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) float thetap = theta * t; return q1 * cosf(thetap) + qperp * sinf(thetap); } +#endif } __device_inline Transform transform_quick_inverse(Transform M) @@ -384,7 +397,7 @@ __device_inline void transform_compose(Transform *tfm, const Transform *decomp) /* Disabled for now, need arc-length parametrization for constant speed motion. * #define CURVED_MOTION_INTERPOLATE */ -__device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t) +__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 @@ -393,9 +406,9 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform #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); @@ -409,28 +422,27 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform if(t < 0.5f) { t *= 2.0f; - decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t); + 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; + 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; + decomp.y = (1.0f - t)*motion->pre_y + t*motion->mid.y; #endif - decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z; - decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w; } else { t = (t - 0.5f)*2.0f; - decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t); + 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; + 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; + decomp.y = (1.0f - t)*motion->mid.y + t*motion->post_y; #endif - 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.z = motion->mid.z; + decomp.w = motion->mid.w; + /* compose rotation, translation, scale into matrix */ transform_compose(tfm, &decomp); } @@ -442,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/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/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/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/release/datafiles/startup.blend b/release/datafiles/startup.blend Binary files differindex 3d31f9cb758..49212f6f9cb 100644 --- a/release/datafiles/startup.blend +++ b/release/datafiles/startup.blend 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 34eab11f9d4..fbe405a61c6 100644 --- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py +++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py @@ -426,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", @@ -442,6 +444,7 @@ dict_uimsgs = { "mux", "ndof", "ppc", + "precisa", "px", "qmc", "rgb", "rgba", 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_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index 2042cc1c8a1..0166f954dc9 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -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 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</%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/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() + + 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 + elif len(f_act.verts) != 4: + operator.report({'ERROR'}, "Active face must be a quad") + return - # 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 + faces = [f for f in bm.faces if f.select and len(f.verts) == 4] + + 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 - # 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]] + l_a_uv = [l[uv_act].uv for l in l_a] + l_b_uv = [l[uv_act].uv for l in l_b] - # 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': + 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 - 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]]) - + d1 = (a0 - b0).length + (a1 - b1).length + d2 = (b0 - c0).length + (b1 - c1).length + try: + fac = d2 / d1 + except ZeroDivisionError: + fac = 1.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]]) + fac = 1.0 - face_act = me.polygons.active - if face_act == -1: - operator.report({'ERROR'}, "No active face") - return + extrapolate_uv(fac, + l_a_uv[3], l_a_uv[0], + l_b_uv[3], l_b_uv[0]) - face_sel = [f for f in me.polygons if len(f.vertices) == 4 and f.select] + extrapolate_uv(fac, + l_a_uv[2], l_a_uv[1], + l_b_uv[2], l_b_uv[1]) - face_act_local_index = -1 - for i, f in enumerate(face_sel): - if f.index == face_act: - face_act_local_index = i - break + for f_triple in walk_face(f_act): + apply_uv(*f_triple) - if face_act_local_index == -1: - operator.report({'ERROR'}, "Active face not selected") - 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. - - # Edge connectivity - edge_faces = {} - for i, f in enumerate(face_sel): - for edkey in f.edge_keys: - try: - edge_faces[edkey].append(i) - except: - edge_faces[edkey] = [i] - - 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) - - # 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 - - # 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 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 eb05057de3d..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 @@ -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_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_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 0bb25e98456..f6eaf421a7a 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -437,7 +437,6 @@ class USERPREF_PT_system(Panel): col.label(text="OpenGL:") col.prop(system, "gl_clip_alpha", slider=True) col.prop(system, "use_mipmaps") - col.prop(system, "use_gpu_mipmap") col.prop(system, "use_16bit_textures") col.label(text="Anisotropic Filtering") col.prop(system, "anisotropic_filter", text="") 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 143c7c5104a..44c7b802e2c 100644 --- a/release/scripts/templates/script_stub.py +++ b/release/scripts/templates/script_stub.py @@ -9,4 +9,6 @@ filename = "my_script.py" filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename) global_namespace = {"__file__": filepath, "__name__": "__main__"} -exec(compile(open(filepath).read(), filepath, 'exec'), global_namespace) +file = open(filepath, 'rb') +exec(compile(file.read(), filepath, 'exec'), global_namespace) +file.close() 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_node.h b/source/blender/blenkernel/BKE_node.h index 65610b5c989..515bb37b249 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 */ diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 1f04f4adba3..dc1c9b5a1a2 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -41,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/blender.c b/source/blender/blenkernel/intern/blender.c index 40cd5b3d403..03698736459 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -268,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); @@ -278,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/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 9b1720787ed..54f69a49e70 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; @@ -812,8 +812,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; } @@ -1048,8 +1048,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); @@ -1349,8 +1349,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); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index a78a9af54ae..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; 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/image.c b/source/blender/blenkernel/intern/image.c index e4b9edacc7e..f09f128e874 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -663,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; } 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_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 fd5af6a20bb..036f8f5e673 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -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); 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/node.c b/source/blender/blenkernel/intern/node.c index 06b846a6df9..70867a45fd7 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -406,13 +406,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) @@ -2153,8 +2154,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); @@ -2255,8 +2254,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); @@ -2337,8 +2334,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/particle.c b/source/blender/blenkernel/intern/particle.c index 93bf5a5c0b4..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); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 3f2eb32f61c..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); diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 609724e802f..5b2e9f2bf23 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -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 e023a3e20ae..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; @@ -2343,7 +2356,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float 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(); @@ -2356,7 +2369,7 @@ 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; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index d96bece2b11..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) 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_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_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_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index a22aa0c13d7..7c3b70545d6 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -324,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/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index d725a0a9417..8b63a94951d 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" @@ -77,6 +79,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 */ @@ -383,7 +386,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) { @@ -392,6 +394,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)) { @@ -399,15 +403,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) \ { \ @@ -422,12 +431,6 @@ 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 */ #if 0 if (ob->fluidsimSettings) { @@ -465,19 +468,19 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int 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); @@ -491,17 +494,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; + } 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; @@ -547,30 +582,30 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int rewrite_path_fixed(module->module_path, visit_cb, absbase, bpath_user_data); } } + 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; diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 1b7858f7f88..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 */ @@ -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/string.c b/source/blender/blenlib/intern/string.c index 14e0dc2f049..f23f75f69d9 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -85,6 +85,10 @@ size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restri { 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) { @@ -115,6 +119,8 @@ char *BLI_sprintfN(const char *__restrict format, ...) va_list arg; char *n; + BLI_assert(format != NULL); + va_start(arg, format); ds = BLI_dynstr_new(); diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 16a5f03095d..bf98f2ae77c 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -394,10 +394,10 @@ int BLI_str_utf8_size_safe(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. @@ -536,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. * @@ -562,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. * @@ -594,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/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index f686e96cb7d..bcd6780b675 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -226,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 { diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index eabbf6f87cd..c805a91ff22 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -105,17 +105,17 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa /* 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,7 +171,7 @@ 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_DEFAULT_NGON_STACK_SIZE); @@ -282,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++) { @@ -338,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; @@ -464,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 */ @@ -493,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); @@ -856,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 */ @@ -873,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; @@ -909,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 03094873e25..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++; @@ -80,17 +83,20 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) 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); } } @@ -105,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); @@ -136,20 +142,26 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, BM_elem_flag_enable(e, BM_ELEM_SMOOTH | BM_ELEM_DRAW); - CustomData_bmesh_set_default(&bm->edata, &e->head.data); - 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; @@ -164,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); @@ -211,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; @@ -234,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; @@ -242,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); @@ -263,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; @@ -286,7 +300,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) 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; @@ -298,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; @@ -309,7 +325,7 @@ 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(verts, len, &f); if (overlap) { @@ -320,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); @@ -1033,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"); @@ -1139,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); @@ -1223,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; @@ -1334,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: + * * <pre> * E * Before: OV-------------TV - * * E RE * After: OV------NV-----TV * </pre> @@ -1359,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); @@ -1403,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; @@ -1919,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 */ @@ -2085,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_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 dc8b52423ab..89516061f91 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -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 ec07eb5d9f7..58c6e051e48 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -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,148 +81,149 @@ * 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, "geom.out"}, //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", /* slots_in */ - {{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, "clip_dist"}, /* 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}, - }, - {{0}}, /* no output */ + {{"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", /* slots_in */ - {{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, "preserve_volume"}, /* Apply volume preservation after smooth */ - {0}, + {{"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 */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "use_flip"}, /* internal flag, used by bmesh_rationalize_normals */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_flip", BMO_OP_SLOT_BOOL}, /* Reverse the result */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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 geom.out. * - * if usefaces is 0 then geom.out 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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_BOOL, "use_constrict"}, /* find boundary inside the regions, not outside. */ - {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output slot, computed boundary geometry. */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly spun edges */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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. @@ -228,50 +231,49 @@ static BMOpDefine bmo_reverse_faces_def = { static BMOpDefine bmo_bisect_edges_def = { "bisect_edges", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_INT, "cuts"}, /* number of cuts */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, /* newly created vertices and edges */ - {0}, + {{"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 * 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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */ - {BMO_OP_SLOT_FLT, "merge_dist"}, /* maximum distance for merging. does no merging if 0. */ - {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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry, mirrored */ - {0}, + {{"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. @@ -279,21 +281,21 @@ static BMOpDefine bmo_mirror_def = { static BMOpDefine bmo_find_doubles_def = { "find_doubles", /* slots_in */ - {{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 */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_MAPPING, "targetmap.out"}, - {0}, + {{"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. @@ -301,70 +303,69 @@ static BMOpDefine bmo_find_doubles_def = { static BMOpDefine bmo_remove_doubles_def = { "remove_doubles", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_automerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Collapse Connected + * Collapse Connected. * * Collapses connected vertices */ static BMOpDefine bmo_collapse_def = { "collapse", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap vertex */ - {0}, + {{"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 */ + {{{'\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 @@ -373,67 +374,68 @@ static BMOpDefine bmo_pointmerge_facedata_def = { static BMOpDefine bmo_average_vert_facedata_def = { "average_vert_facedata", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {BMO_OP_SLOT_VEC, "merge_co"}, - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {"merge_co", BMO_OP_SLOT_VEC}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_MAPPING, "targetmap"}, /* maps welded vertices to verts they should weld to */ - {0}, + /* maps welded vertices to verts they should weld to */ + {{"targetmap", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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. @@ -441,19 +443,19 @@ static BMOpDefine bmo_weld_verts_def = { static BMOpDefine bmo_create_vert_def = { "create_vert", /* slots_in */ - {{BMO_OP_SLOT_VEC, "co"}, /* the coordinate of the new vert */ - {0}, + {{"co", BMO_OP_SLOT_VEC}, /* the coordinate of the new vert */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "vert.out"}, /* the new vert */ - {0}, + {{"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. @@ -461,29 +463,28 @@ static BMOpDefine bmo_create_vert_def = { static BMOpDefine bmo_join_triangles_def = { "join_triangles", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input geometry. */ - {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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* joined faces */ - {0}, + {{"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. @@ -491,63 +492,70 @@ static BMOpDefine bmo_join_triangles_def = { static BMOpDefine bmo_contextual_create_def = { "contextual_create", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* smooth to use */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* newly-made face(s) */ + {{"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, "edges.out"}, /* newly-made edge(s) */ - {0}, + {"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_BOOL, "use_merge"}, - {BMO_OP_SLOT_FLT, "merge_factor"}, - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new faces */ - {0}, + {{"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", /* slots_in */ - {{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, "exclude_faces"}, /* list of faces to ignore for manifold check */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_MAPPING, "face_groupmap.out"}, /* maps new faces to the group numbers they came from */ - {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new face */ - {0}, + /* 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: @@ -559,74 +567,72 @@ static BMOpDefine bmo_edgenet_fill_def = { static BMOpDefine bmo_edgenet_prepare_def = { "edgenet_prepare", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* new edges */ - {0}, + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ + {{'\0'}}, }, - bmo_edgenet_prepare, + 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", /* slots_in */ - {{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}, + {{"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 */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_VEC, "vec"}, /* translation offset */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"vec", BMO_OP_SLOT_VEC}, /* translation offset */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_translate_exec, 0, }; /* - * Scale + * Scale. * * Scales vertices by an offset. */ static BMOpDefine bmo_scale_def = { "scale", /* slots_in */ - {{BMO_OP_SLOT_VEC, "vec"}, /* scale factor */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"vec", BMO_OP_SLOT_VEC}, /* scale factor */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_scale_exec, 0, }; /* - * Transform + * Transform. * * Transforms a set of vertices by a matrix. Multiplies * the vertex coordinates with the matrix. @@ -634,17 +640,17 @@ static BMOpDefine bmo_scale_def = { static BMOpDefine bmo_transform_def = { "transform", /* slots_in */ - {{BMO_OP_SLOT_MAT, "mat"}, /* transform matrix */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"matrix", BMO_OP_SLOT_MAT}, /* transform matrix */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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. @@ -652,36 +658,39 @@ static BMOpDefine bmo_transform_def = { static BMOpDefine bmo_object_load_bmesh_def = { "object_load_bmesh", /* slots_in */ - {{BMO_OP_SLOT_PTR, "scene"}, - {BMO_OP_SLOT_PTR, "object"}, - {0}, + {{"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 */ + {{{'\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", /* slots_in */ - {{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, "skip_tessface"}, /* don't calculate mfaces */ - {0}, + { + /* 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 */ + {{{'\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. @@ -689,38 +698,40 @@ static BMOpDefine bmo_bmesh_to_mesh_def = { static BMOpDefine bmo_mesh_to_bmesh_def = { "mesh_to_bmesh", /* slots_in */ - {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a Mesh structure */ - {BMO_OP_SLOT_PTR, "object"}, /* pointer to an Object structure */ - {BMO_OP_SLOT_BOOL, "use_shapekey"}, /* load active shapekey coordinates into verts */ - {0}, + { + /* 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 */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "geom_skirt.out"}, /* output skirt geometry, faces and edges */ - {0}, + {{"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. @@ -728,247 +739,308 @@ static BMOpDefine bmo_extrude_discrete_faces_def = { static BMOpDefine bmo_extrude_edge_only_def = { "extrude_edge_only", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input vertices */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output wire edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* edges and faces */ - {BMO_OP_SLOT_MAPPING, "edges_exclude"}, - {BMO_OP_SLOT_BOOL, "use_keep_orig"}, /* keep original geometry */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_dissolve_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Edges. + */ static BMOpDefine bmo_dissolve_edges_def = { "dissolve_edges", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, - {0}, + {{"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", /* slots_in */ - {{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}, + {{"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 */ + {{{'\0'}}}, /* no output */ bmo_dissolve_limit_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Triangulate. + */ static BMOpDefine bmo_triangulate_def = { "triangulate", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "use_beauty"}, - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_beauty", BMO_OP_SLOT_BOOL}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, - {BMO_OP_SLOT_MAPPING, "facemap.out"}, - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_INT, "iterations"}, - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"iterations", BMO_OP_SLOT_INT}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{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, "cuts"}, - {BMO_OP_SLOT_INT, "seed"}, - {BMO_OP_SLOT_MAPPING, "custompatterns"}, - {BMO_OP_SLOT_MAPPING, "edgepercents"}, - - {BMO_OP_SLOT_INT, "quad_corner_type"}, /* 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}, + {{"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}}, + + {"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 */ - {BMO_OP_SLOT_ELEMENT_BUF, "geom_inner.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* contains all output geometr */ - {0}, + {"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_INT, "context"}, - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"context", BMO_OP_SLOT_INT}, /* enum DEL_VERTS ... */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom_orig.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom.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.out"}, - {BMO_OP_SLOT_MAPPING, "boundarymap.out"}, - {BMO_OP_SLOT_MAPPING, "isovertmap.out"}, - {0}, + {"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current one */ - {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {BMO_OP_SLOT_MAPPING, "boundarymap.out"}, - {BMO_OP_SLOT_MAPPING, "isovertmap.out"}, - {0}, + {{"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 @@ -976,18 +1048,18 @@ static BMOpDefine bmo_split_def = { static BMOpDefine bmo_spin_def = { "spin", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {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, "angle"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_INT, "steps"}, /* number of steps */ - {BMO_OP_SLOT_BOOL, "use_duplicate"}, /* duplicate or extrude? */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom_last.out"}, /* result of last step */ - {0}, + {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */ + {{'\0'}}, }, bmo_spin_exec, 0 @@ -995,486 +1067,490 @@ static BMOpDefine bmo_spin_def = { /* - * Similar faces search + * Similar Faces Search. * * Find similar faces (area/material/perimeter, ...). */ static BMOpDefine bmo_similar_faces_def = { "similar_faces", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input 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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input 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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output edges */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input 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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */ - {0}, + {{"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 */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */ - {0}, + {{"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 */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ + {{"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}, + {"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* old output disconnected edges */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_INT, "x_segments"}, /* number of x segments */ - {BMO_OP_SLOT_INT, "y_segments"}, /* 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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_INT, "u_segments"}, /* number of u segments */ - {BMO_OP_SLOT_INT, "v_segments"}, /* number of v segment */ - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"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", /* slots_in */ - {{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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"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", /* slots_in */ - {{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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"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", /* slots_in */ - {{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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_FLT, "size"}, /* size of the cube */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"size", BMO_OP_SLOT_FLT}, /* size of the cube */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ - {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */ - {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {0}, - }, -#if 0 /* old 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}, - }, -#endif + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "constrain_edges"}, /* edges that can't be flipped */ - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new flipped faces and edges */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new faces and edges */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"thickness", BMO_OP_SLOT_FLT}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input 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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input 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}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {0}, + {{"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", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "vert"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edge"}, - {BMO_OP_SLOT_FLT, "distance_t"}, - {0}, + {{"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 */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, }, bmo_slide_vert_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -1499,16 +1575,16 @@ static BMOpDefine bmo_slide_vert_def = { static BMOpDefine bmo_convex_hull_def = { "convex_hull", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, - {BMO_OP_SLOT_BOOL, "use_existing_faces"}, - {0}, + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"use_existing_faces", BMO_OP_SLOT_BOOL}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom_interior.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom_unused.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom_holes.out"}, - {0}, + {{"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 @@ -1516,9 +1592,9 @@ static BMOpDefine bmo_convex_hull_def = { #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. @@ -1528,19 +1604,19 @@ static BMOpDefine bmo_convex_hull_def = { static BMOpDefine bmo_symmetrize_def = { "symmetrize", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, - {BMO_OP_SLOT_INT, "direction"}, - {0}, + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"direction", BMO_OP_SLOT_INT}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {0}, + {{"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, @@ -1615,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 b87e023e63a..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,16 +108,47 @@ 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 { const char *slot_name; /* pointer to BMOpDefine.slot_args */ - int slot_type; + eBMOpSlotType slot_type; + eBMOpSlotSubType_Union slot_subtype; + int len; // int flag; /* UNUSED */ // int index; /* index within slot array */ /* UNUSED */ @@ -166,8 +197,9 @@ enum { #define MAX_SLOTNAME 32 typedef struct BMOSlotType { - int type; char name[MAX_SLOTNAME]; + eBMOpSlotType type; + eBMOpSlotSubType_Union subtype; } BMOSlotType; typedef struct BMOpDefine { @@ -208,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); @@ -385,12 +380,16 @@ 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); +void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele); +void *BMO_slot_buffer_get_single(BMOpSlot *slot); + + /* counts number of elements inside a slot array. */ int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *data, int len); + const void *element, const void *data, const int len); /* Counts the number of edges with tool flag toolflag around */ @@ -407,15 +406,18 @@ void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS] 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 * } @@ -436,6 +438,7 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_ * // *((void**)BMO_iter_map_value(&oiter)); * //or something like that. * } + * \endcode */ /* contents of this structure are private, @@ -478,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 b405ecc1841..ad116011421 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -70,14 +70,24 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor } BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, - void *element, int val) + void *element, const int val) { + 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_bool_insert(BMOperator *op, BMOpSlot *slot, + void *element, const int val) +{ + 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, float val) + 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)); } @@ -90,9 +100,26 @@ BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val) { + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); } +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) { BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -126,7 +153,10 @@ BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element) BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { - float *val = (float *) BMO_slot_map_data_get(slot, 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; @@ -134,7 +164,22 @@ BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { - int *val = (int *) BMO_slot_map_data_get(slot, 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 int BMO_slot_map_bool_get(BMOpSlot *slot, const void *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; @@ -143,6 +188,16 @@ BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) 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 157837a13c0..ba38f230f0b 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -127,12 +127,13 @@ void BMO_pop(BMesh *bm) /* use for both slot_types_in and slot_types_out */ -static void bmo_op_slots_init(BMOSlotType *slot_types, BMOpSlot *slot_args) +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_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 } } @@ -158,15 +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 */ - bmo_op_slots_init(opdefines[opcode]->slot_types_in, op->slots_in); - bmo_op_slots_init(opdefines[opcode]->slot_types_out, op->slots_out); + 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__); @@ -199,7 +200,7 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) BMO_pop(bm); } -static void bmo_op_slots_free(BMOSlotType *slot_types, BMOpSlot *slot_args) +static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args) { BMOpSlot *slot; unsigned int i; @@ -220,13 +221,13 @@ static void bmo_op_slots_free(BMOSlotType *slot_types, BMOpSlot *slot_args) */ void BMO_op_finish(BMesh *bm, BMOperator *op) { - bmo_op_slots_free(opdefines[op->type]->slot_types_in, op->slots_in); - bmo_op_slots_free(opdefines[op->type]->slot_types_out, op->slots_out); + 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]->opname); + BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname); #else (void)bm; #endif @@ -287,9 +288,49 @@ void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_n slot_dst->data.buf = NULL; slot_dst->len = slot_src->len; 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); - memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); + /* 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 (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { @@ -313,7 +354,7 @@ void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_n 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(slot_dst->data.ghash, dstmap->element, dstmap); } @@ -595,7 +636,7 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na * value, it doesn't store a reference to it. */ void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *data, int len) + const void *element, const void *data, const int len) { BMOElemMapping *mapping; BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -605,11 +646,14 @@ void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, 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, (void *)element, mapping); } @@ -631,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"); @@ -646,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"); @@ -823,6 +867,29 @@ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, 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. */ @@ -880,6 +947,7 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, 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; @@ -955,6 +1023,7 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, 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)) @@ -989,6 +1058,7 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm, 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)) @@ -1039,6 +1109,7 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, 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)) @@ -1062,6 +1133,7 @@ void BMO_slot_buffer_flag_disable(BMesh *bm, 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)) @@ -1252,35 +1324,42 @@ void *BMO_iter_new(BMOIter *iter, 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 = 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 = 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; } @@ -1393,8 +1472,8 @@ static int bmo_opname_to_opcode(const char *opname) { int i; - for (i = 0; i < bmesh_total_ops; i++) { - if (!strcmp(opname, opdefines[i]->opname)) { + for (i = 0; i < bmo_opdefines_total; i++) { + if (!strcmp(opname, bmo_opdefines[i]->opname)) { return i; } } @@ -1403,23 +1482,63 @@ static int bmo_opname_to_opcode(const char *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. + * + * This system is used to execute or initialize an operator, + * using a formatted-string system. + * + * 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) + * * - * i - int - * b - boolean (same as int but 1/0 only) - * f - float - * s - slot_in - * S - slot_out - * 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) + * **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) * - * capitals - H, F to use the flag flipped (when the flag is off) - * Hv, He, Hf, Fv, Fe, Ff, + * \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) @@ -1463,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 */ @@ -1522,14 +1641,12 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v state = 1; break; } - case 'e': + case 'e': /* single vert/edge/face */ { BMHeader *ele = va_arg(vlist, void *); BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); - slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); - slot->len = 1; - *slot->data.buf = ele; + BMO_slot_buffer_from_single(op, slot, ele); state = 1; break; diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 1c62a038f34..c98c3eae50b 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -85,29 +85,22 @@ enum { SIMVERT_EDGE }; -enum { - OPUVC_AXIS_X = 1, - OPUVC_AXIS_Y -}; - /* 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_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index ec2e90591cc..195c60c5a9c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -824,6 +824,29 @@ int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) } /** + * 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_check(BMEdge *e1, BMEdge *e2) diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index d97faebf021..7a18f69371e 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -90,6 +90,7 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2); 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); diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index b7bb57bb19d..12edffec213 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -54,6 +54,8 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) 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); diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index 987aa8cdf99..aa69806fb37 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -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; } @@ -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); } @@ -1051,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; @@ -1098,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; @@ -1249,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) { @@ -1261,7 +1261,7 @@ 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); } } @@ -1359,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); } } @@ -1420,7 +1420,7 @@ 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, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); } @@ -1461,7 +1461,7 @@ 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; @@ -1483,7 +1483,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) 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_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index c4f6c821320..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); @@ -98,14 +98,13 @@ static BMEdge *copy_edge(BMOperator *op, 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(op, slot_boundarymap_out, - source_edge, target_edge); + BMO_slot_map_elem_insert(op, slot_boundarymap_out, source_edge, target_edge); } /* Insert new edge into the edge hash */ @@ -157,9 +156,9 @@ static BMFace *copy_face(BMOperator *op, } /* create new face */ - target_face = BM_face_create(target_mesh, vtar, edar, source_face->len, FALSE); - BMO_slot_map_ptr_insert(op, slot_facemap_out, source_face, target_face); - BMO_slot_map_ptr_insert(op, slot_facemap_out, 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); @@ -200,9 +199,9 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) BMIter viter, eiter, fiter; GHash *vhash, *ehash; - BMOpSlot *slot_boundarymap_out = BMO_slot_get(op->slots_out, "boundarymap.out"); - BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "facemap.out"); - BMOpSlot *slot_isovertmap_out = BMO_slot_get(op->slots_out, "isovertmap.out"); + 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"); @@ -235,7 +234,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) } if (isolated) { - BMO_slot_map_ptr_insert(op, slot_isovertmap_out, v, v2); + BMO_slot_map_elem_insert(op, slot_isovert_map_out, v, v2); } BMO_elem_flag_enable(bm_src, v, DUPE_DONE); @@ -257,7 +256,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) BMO_elem_flag_enable(bm_src, e->v2, DUPE_DONE); } /* now copy the actual edge */ - copy_edge(op, slot_boundarymap_out, bm_src, e, bm_dst, vhash, ehash); + copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash); BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } @@ -276,7 +275,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) /* edge pass */ BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) { if (!BMO_elem_flag_test(bm_src, e, DUPE_DONE)) { - copy_edge(op, slot_boundarymap_out, bm_src, e, bm_dst, vhash, ehash); + copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash); BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } @@ -288,7 +287,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) BLI_array_grow_items(vtar, f->len); BLI_array_grow_items(edar, f->len); - copy_face(op, slot_facemap_out, bm_src, f, bm_dst, vtar, edar, vhash, ehash); + 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); } } @@ -331,7 +330,7 @@ void bmo_duplicate_exec(BMesh *bm, BMOperator *op) bm2 = bm; /* flag input */ - BMO_slot_buffer_flag_enable(bm, dupeop->slots_in, "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 */ bmo_mesh_copy(dupeop, bm, bm2); @@ -342,7 +341,7 @@ void bmo_duplicate_exec(BMesh *bm, BMOperator *op) dupeop, slots_out, "geom_orig.out"); /* Now alloc the new output buffers */ - BMO_slot_buffer_from_enabled_flag(bm, dupeop, dupeop->slots_out, "geom.out", 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 */ @@ -397,7 +396,7 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) &dupeop, slots_in, "geom"); BMO_op_exec(bm, &dupeop); - BMO_slot_buffer_flag_enable(bm, splitop->slots_in, "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; @@ -438,7 +437,7 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) /* connect outputs of dupe to delete, exluding keep geometry */ BMO_slot_int_set(delop.slots_in, "context", DEL_FACES); - BMO_slot_buffer_from_enabled_flag(bm, &delop, delop.slots_in, "geom", BM_ALL, SPLIT_INPUT); + BMO_slot_buffer_from_enabled_flag(bm, &delop, delop.slots_in, "geom", BM_ALL_NOLOOP, SPLIT_INPUT); BMO_op_exec(bm, &delop); @@ -446,11 +445,11 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) BMO_slot_copy(&dupeop, slots_out, "geom.out", splitop, slots_out, "geom.out"); - BMO_slot_copy(&dupeop, slots_out, "boundarymap.out", - splitop, slots_out, "boundarymap.out"); + BMO_slot_copy(&dupeop, slots_out, "boundary_map.out", + splitop, slots_out, "boundary_map.out"); - BMO_slot_copy(&dupeop, slots_out, "isovertmap.out", - splitop, slots_out, "isovertmap.out"); + BMO_slot_copy(&dupeop, slots_out, "isovert_map.out", + splitop, slots_out, "isovert_map.out"); /* cleanup */ @@ -466,7 +465,7 @@ void bmo_delete_exec(BMesh *bm, BMOperator *op) BMOperator *delop = op; /* Mark Buffer */ - BMO_slot_buffer_flag_enable(bm, delop->slots_in, "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->slots_in, "context")); @@ -495,7 +494,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op) BMO_slot_vec_get(op->slots_in, "dvec", dvec); usedvec = !is_zero_v3(dvec); steps = BMO_slot_int_get(op->slots_in, "steps"); - phi = BMO_slot_float_get(op->slots_in, "angle") * DEG2RADF(1.0f) / 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); @@ -507,7 +506,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op) 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", + "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"); @@ -518,7 +517,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op) op, "geom_last.out"); BMO_op_exec(bm, &extop); BMO_op_callf(bm, op->flag, - "rotate cent=%v mat=%m3 verts=%S", + "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"); diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 6a9d9c1e48b..065a1b57737 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -67,11 +67,11 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) 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); @@ -198,7 +198,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) } } - for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundarymap.out", 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, op->slots_out, "geom.out", 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) @@ -241,11 +241,11 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) const int has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); 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); + 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); @@ -352,9 +352,9 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } - slot_facemap_out = BMO_slot_get(dupeop.slots_out, "facemap.out"); + 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_ptr_get(slot_facemap_out, bm->act_face); + bm->act_face = BMO_slot_map_elem_get(slot_facemap_out, bm->act_face); } if (delorig) { @@ -374,7 +374,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) op, slots_out, "geom.out"); slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); - for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundarymap.out", 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]; /* this should always be wire, so this is mainly a speedup to avoid map lookup */ @@ -428,9 +428,9 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } /* link isolated vert */ - for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovertmap.out", 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 */ diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 117f65ae4ea..e2da4f4f89c 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -113,9 +113,9 @@ 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; @@ -604,22 +604,22 @@ 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, op->slots_out, "geom_interior.out", - BM_ALL, HULL_FLAG_INTERIOR_ELE); + 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, op->slots_out, "geom_unused.out", - BM_ALL, HULL_FLAG_DEL); + 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, op->slots_out, "geom_holes.out", - BM_ALL, HULL_FLAG_HOLE); + BM_ALL_NOLOOP, HULL_FLAG_HOLE); /* Output slot of all hull vertices, faces, and edges */ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", - BM_ALL, HULL_FLAG_OUTPUT_GEOM); + 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 9abf129a529..cef1181f63b 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -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 diff --git a/source/blender/bmesh/operators/bmo_mirror.c b/source/blender/bmesh/operators/bmo_mirror.c index 01bce976ec0..61b061dd21f 100644 --- a/source/blender/bmesh/operators/bmo_mirror.c +++ b/source/blender/bmesh/operators/bmo_mirror.c @@ -60,13 +60,13 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) ototvert = bm->totvert; /* ototedge = bm->totedge; */ /* UNUSED */ - BMO_slot_mat4_get(op->slots_in, "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.slots_out, "geom.out", 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; @@ -81,9 +81,9 @@ 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"); @@ -92,7 +92,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); for (i = 0; i < ototvert; i++) { if (fabsf(v->co[axis]) <= dist) { - BMO_slot_map_ptr_insert(&weldop, slot_targetmap, vmap[i], v); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, vmap[i], v); } v = BM_iter_step(&iter); } @@ -123,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, op->slots_out, "geom.out", 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 71f63bbaf28..c582f710f43 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -237,7 +237,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) float vec[3], mat[4][4], phi, phid; int a; - BMO_slot_mat4_get(op->slots_in, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); /* one segment first: the X axis */ phi = 1.0f; @@ -248,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); } @@ -304,7 +304,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) float phid; int a; - BMO_slot_mat4_get(op->slots_in, "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 */ @@ -317,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); } @@ -348,7 +348,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) } BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); - BMO_op_callf(bm, op->flag, "rotate cent=%v mat=%m3 verts=%S", vec, cmat, &bmop, "geom.out"); + BMO_op_callf(bm, op->flag, "rotate cent=%v matrix=%m3 verts=%S", vec, cmat, &bmop, "geom.out"); prevop = bmop; } @@ -397,7 +397,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) float vec[3], mat[4][4] /* , phi, phid */; int a; - BMO_slot_mat4_get(op->slots_in, "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 */ @@ -407,7 +407,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) 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); + eva[a] = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, eva[a], VERT_MARK); } @@ -436,7 +436,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) "subdivide_edges edges=%fe " "smooth=%f " "cuts=%i " - "use_gridfill=%b use_sphere=%b", + "use_grid_fill=%b use_sphere=%b", EDGE_MARK, dia, (1 << (subdiv - 1)) - 1, TRUE, TRUE); @@ -463,19 +463,19 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) float mat[4][4]; int i; - BMO_slot_mat4_get(op->slots_in, "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); @@ -518,7 +518,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) if (!segs) return; - BMO_slot_mat4_get(op->slots_in, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); phid = 2.0f * (float)M_PI / segs; phi = 0; @@ -527,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); } @@ -537,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; @@ -560,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; @@ -591,7 +591,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) if (!segs) return; - BMO_slot_mat4_get(op->slots_in, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); phid = 2.0f * (float)M_PI / segs; phi = 0; @@ -602,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); @@ -619,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); @@ -677,7 +677,7 @@ 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->slots_in, "size") / 2.0f; - BMO_slot_mat4_get(op->slots_in, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); if (!off) off = 0.5f; @@ -685,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 */ diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 45e678b96bb..87e26f11d4b 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -44,7 +44,7 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot int split = FALSE; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - v2 = BMO_slot_map_ptr_get(slot_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)) && @@ -110,7 +110,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) /* mark merge verts for deletion */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if ((v2 = BMO_slot_map_ptr_get(slot_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 */ @@ -126,8 +126,8 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) 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(slot_targetmap, e->v1); - v2 = BMO_slot_map_ptr_get(slot_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; @@ -136,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); @@ -175,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(slot_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(slot_targetmap, v2); + v2 = BMO_slot_map_elem_get(slot_targetmap, v2); } e2 = v != v2 ? BM_edge_exists(v, v2) : NULL; @@ -208,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(slot_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(slot_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); @@ -258,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, op->slots_in, "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; } @@ -343,7 +343,7 @@ 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; @@ -355,12 +355,12 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op) slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { - if (!snapv) { - snapv = v; - copy_v3_v3(snapv->co, vec); + if (!vert_snap) { + vert_snap = v; + copy_v3_v3(vert_snap->co, vec); } else { - BMO_slot_map_ptr_insert(&weldop, slot_targetmap, v, snapv); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, v, vert_snap); } } @@ -414,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(&weldop, slot_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(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1); } } @@ -554,7 +554,7 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMO_elem_flag_enable(bm, v_other, VERT_DOUBLE); BMO_elem_flag_enable(bm, v_check, VERT_TARGET); - BMO_slot_map_ptr_insert(optarget, optarget_slot, v_other, v_check); + BMO_slot_map_elem_insert(optarget, optarget_slot, v_other, v_check); } } } diff --git a/source/blender/bmesh/operators/bmo_slide.c b/source/blender/bmesh/operators/bmo_slide.c index 9dde2461364..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->slots_in, "distance_t"); + const float factor = BMO_slot_float_get(op->slots_in, "factor"); /* Get start vertex */ - vertex = BMO_iter_new(&oiter, op->slots_in, "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, op->slots_in, "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,7 +101,7 @@ 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 */ diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 4137c31961c..4a367a8fd6f 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -544,6 +544,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) 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; diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index f9b6611c88b..7407eb4423a 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -226,7 +226,7 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, float percent, percent2 = 0.0f; if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) { - percent = BMO_slot_map_float_get(params->slot_edgepercents, edge); + percent = BMO_slot_map_float_get(params->slot_edge_percents, edge); } else { percent = 1.0f / (float)(totpoint + 1 - curpoint); @@ -715,7 +715,7 @@ 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->slots_in, "edges", BM_EDGE, SUBD_SPLIT); @@ -727,9 +727,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) 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->slots_in, "use_singleedge"); - use_gridfill = BMO_slot_bool_get(op->slots_in, "use_gridfill"); - use_sphere = BMO_slot_bool_get(op->slots_in, "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); @@ -747,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; } @@ -756,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; } @@ -779,8 +780,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) params.numcuts = numcuts; params.op = op; - params.slot_edgepercents = BMO_slot_get(op->slots_in, "edgepercents"); - params.slot_custompatterns = BMO_slot_get(op->slots_in, "custompatterns"); + 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; @@ -793,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->slots_in, "custompatterns", + BMO_slot_map_to_flag(bm, op->slots_in, "custom_patterns", BM_FACE, FACE_CUSTOMFILL); - BMO_slot_map_to_flag(bm, op->slots_in, "edgepercents", + BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents", BM_EDGE, EDGE_PERCENT); @@ -804,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); @@ -840,7 +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(params.slot_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++) { @@ -1077,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, op->slots_out, "geom_inner.out", BM_ALL, ELE_INNER); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", 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, op->slots_out, "geom.out", 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 */ @@ -1088,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; @@ -1099,13 +1105,15 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, "smooth=%f fractal=%f along_normal=%f " "cuts=%i " "quad_corner_type=%i " - "use_singleedge=%b use_gridfill=%b " + "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); @@ -1162,7 +1170,7 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) params.numcuts = BMO_slot_int_get(op->slots_in, "cuts"); params.op = op; - params.slot_edgepercents = BMO_slot_get(op->slots_in, "edgepercents"); + 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; @@ -1174,7 +1182,7 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) bm_subdivide_multicut(bm, e, ¶ms, e->v1, e->v2); } - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", 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 d0676508917..529075aab02 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.h +++ b/source/blender/bmesh/operators/bmo_subdivide.h @@ -39,8 +39,8 @@ typedef struct SubDParams { int seed; int origkey; /* shapekey holding displaced vertex coordinates for current geometry */ BMOperator *op; - BMOpSlot *slot_edgepercents; /* BMO_slot_get(params->op->slots_in, "edgepercents"); */ - BMOpSlot *slot_custompatterns; /* BMO_slot_get(params->op->slots_in, "custompatterns"); */ + 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 8c440cae83e..248c7268ac6 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -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; @@ -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); } @@ -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) @@ -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); } } } @@ -659,5 +666,5 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) BLI_ghash_free(symm.edge_split_map, NULL, NULL); BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", - BM_ALL, SYMM_OUTPUT_GEOM); + 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 775fa0cb60d..d20d01af114 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -53,7 +53,7 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op) BLI_array_declare(projectverts); int i; const int use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty"); - BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "facemap.out"); + BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "face_map.out"); for (face = BMO_iter_new(&siter, op->slots_in, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) { @@ -65,9 +65,9 @@ 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(op, slot_facemap_out, face, face); + BMO_slot_map_elem_insert(op, slot_facemap_out, face, face); for (i = 0; newfaces[i]; i++) { - BMO_slot_map_ptr_insert(op, slot_facemap_out, newfaces[i], face); + BMO_slot_map_elem_insert(op, slot_facemap_out, newfaces[i], face); } } @@ -190,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, diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index d56b2ca0d73..64dbf0cc0e7 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -47,7 +47,7 @@ void bmo_create_vert_exec(BMesh *bm, BMOperator *op) BMO_slot_vec_get(op->slots_in, "co", vec); - BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL), 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); } @@ -57,7 +57,7 @@ void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op) BMVert *v; float mat[4][4]; - BMO_slot_mat4_get(op->slots_in, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) { mul_m4_v3(mat, v->co); @@ -73,7 +73,7 @@ void bmo_translate_exec(BMesh *bm, BMOperator *op) 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) @@ -87,7 +87,7 @@ void bmo_scale_exec(BMesh *bm, BMOperator *op) 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) @@ -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); @@ -268,14 +268,14 @@ void bmo_region_extend_exec(BMesh *bm, BMOperator *op) 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->slots_in, "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, op->slots_out, "geom.out", 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 ****** */ @@ -701,9 +701,8 @@ 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; @@ -712,13 +711,8 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) int num_total = 0 /*, num_sels = 0 */, i = 0; const int type = BMO_slot_int_get(op->slots_in, "type"); - /* BMESH_TODO use BMO_slot_buffer_elem_first here? */ - BMO_ITER (vs, &vs_iter, op->slots_in, "startv", BM_VERT) { - sv = vs; - } - BMO_ITER (vs, &vs_iter, op->slots_in, "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); diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c index 532145ab129..7401704310f 100644 --- a/source/blender/bmesh/operators/bmo_wireframe.c +++ b/source/blender/bmesh/operators/bmo_wireframe.c @@ -227,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 */ @@ -267,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) { @@ -301,7 +301,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) 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); } } } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 75e74155f66..cb35616a1f7 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -164,7 +164,7 @@ static NewVert *mesh_vert(VMesh *vm, int i, int j, int 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); + nv->v = BM_vert_create(bm, nv->co, eg, 0); } static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, @@ -264,14 +264,13 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BMF else { int i; BMEdge **ee = NULL; - BLI_array_staticdeclare(ee, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_fixedstack_declare(ee, BM_DEFAULT_NGON_STACK_SIZE, totv, __func__); - BLI_array_grow_items(ee, totv); for (i = 0; i < totv; i++) { - ee[i] = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, TRUE); + 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, FALSE); - BLI_array_free(ee); + 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); @@ -366,13 +365,19 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, } /* 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, - * but the line intersection routine will find the closest approach point. */ -static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, - BMFace *f1, BMFace *f2, float meetco[3]) + * 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], norm_perp1[3], norm_perp2[3], - off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], co[3]; + int iret; BLI_assert(f1 != NULL && f2 != NULL); @@ -398,9 +403,21 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, /* lines are parallel; off1a is a good meet point */ copy_v3_v3(meetco, off1a); } - else if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { - /* another test says they are parallel */ - 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 */ } } @@ -546,6 +563,7 @@ static void get_point_on_round_edge(const float uv[2], #else /* USE_ALTERNATE_ADJ */ +#ifdef OLD_ROUND_EDGE /* * calculation of points on the round profile * r - result, coordinate of point on round profile @@ -633,6 +651,66 @@ static void get_point_on_round_edge(EdgeHalf *e, int k, interp_v3_v3v3(r_co, va, vb, (float)k / (float)n); } } +#else + +/* + * 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. + * 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 + * However 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 vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3], p[3], angle; + float m[4][4] = MAT4_UNITY; + int n = e->seg; + + 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(&m[0][0], vmid, va); + sub_v3_v3v3(&m[1][0], vmid, vb); + add_v3_v3v3(&m[2][0], vmid, vd); + sub_v3_v3(&m[2][0], va); + sub_v3_v3(&m[2][0], vb); + add_v3_v3v3(&m[3][0], va, vb); + sub_v3_v3(&m[3][0], vmid); + + /* Now 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 { + /* planar case */ + interp_v3_v3v3(r_co, va, vb, (float)k / (float)n); + } +} +#endif /* ! OLD_ROUND_EDGE */ #endif /* !USE_ALTERNATE_ADJ */ @@ -693,8 +771,7 @@ static void build_boundary(MemArena *mem_arena, BevVert *bv) 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 */ - /* TODO: fix case when one or both faces in following are NULL */ - offset_in_two_planes(e->prev->prev, e, bv->v, + 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; @@ -987,7 +1064,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) } } while ((v = v->next) != vm->boundstart); mul_v3_fl(midco, 1.0f / nn); - bmv = BM_vert_create(bm, midco, NULL); + bmv = BM_vert_create(bm, midco, NULL, 0); v = vm->boundstart; do { i = v->index; diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index 4d382d65659..4a557c20ae3 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -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/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 781001508f2..7c054d84405 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -223,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; @@ -244,8 +244,9 @@ 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"); @@ -877,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 */ @@ -960,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) diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index d2a5c580ae6..f67f01e4585 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -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) 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/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<MemoryProxy *> *memoryProxies); 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/operations/COM_MapRangeOperation.cpp b/source/blender/compositor/operations/COM_MapRangeOperation.cpp index a18f418e48e..1fe74ade0fc 100644 --- a/source/blender/compositor/operations/COM_MapRangeOperation.cpp +++ b/source/blender/compositor/operations/COM_MapRangeOperation.cpp @@ -43,6 +43,9 @@ void MapRangeOperation::initExecution() 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 */ @@ -61,9 +64,15 @@ void MapRangeOperation::executePixel(float output[4], float x, float y, PixelSam source_max = inputs[2]; dest_min = inputs[3]; dest_max = inputs[4]; - - value = (value - source_min) / (source_max - source_min); - value = dest_min + value * (dest_max - dest_min); + + 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) { 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_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index cc313512316..d5f2c283c72 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -103,7 +103,7 @@ void ViewerBaseOperation:: updateImage(rcti *rect) 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_markers.c b/source/blender/editors/animation/anim_markers.c index 4ac7b61fccb..62ffdc7fd3a 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -732,7 +732,7 @@ static void ed_marker_move_apply(bContext *C, wmOperator *op) /* so we get view3d redraws */ BKE_scene_camera_switch_update(scene); - if(camera != scene->camera) { + if (camera != scene->camera) { BKE_screen_view3d_scene_sync(sc); WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); } @@ -860,16 +860,21 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) } 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); + 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)vec[0]); + // 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); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index bd85e93f1af..d5c9b9ef01a 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, @@ -220,6 +215,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,6 +293,7 @@ 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_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 3645f13f27a..f5c943fbb87 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -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); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 535239cd462..9037afc472a 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2826,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) { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index c1547593f96..7c099de9c1e 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -826,11 +826,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 +1197,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 +1209,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 */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 4dbdb977d36..e90fc1d4695 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -191,10 +191,12 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) } /* 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); } @@ -787,7 +789,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 */ diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 65d70e231a4..cd6063b12d0 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -86,7 +86,8 @@ static void make_prim_finish(bContext *C, Object *obedit, int *state, int enter_ * 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, enter_editmode); /* userdef */ if (*state && !enter_editmode) { @@ -109,7 +110,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "verts.out", - "create_grid x_segments=%i y_segments=%i size=%f mat=%m4", 1, 1, dia, mat)) + "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4", 1, 1, dia, mat)) { return OPERATOR_CANCELLED; } @@ -149,7 +150,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, "verts.out", "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; } @@ -199,7 +200,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "verts.out", - "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b mat=%m4", + "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") * dia, cap_end, cap_tri, mat)) { @@ -254,7 +255,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op) if (!EDBM_op_call_and_selectf( em, op, "verts.out", - "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", + "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, @@ -314,7 +315,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op) if (!EDBM_op_call_and_selectf( em, op, "verts.out", - "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", + "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") * dia, RNA_float_get(op->ptr, "radius2") * dia, cap_end, cap_tri, RNA_float_get(op->ptr, "depth") * dia, mat)) { @@ -369,7 +370,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "verts.out", - "create_grid x_segments=%i y_segments=%i size=%f mat=%m4", + "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)) @@ -427,7 +428,7 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_monkey mat=%m4", mat)) { + if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_monkey matrix=%m4", mat)) { return OPERATOR_CANCELLED; } @@ -467,7 +468,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "verts.out", - "create_uvsphere u_segments=%i v_segments=%i diameter=%f mat=%m4", + "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)) { @@ -519,7 +520,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) if (!EDBM_op_call_and_selectf( em, op, "verts.out", - "create_icosphere subdivisions=%i diameter=%f mat=%m4", + "create_icosphere subdivisions=%i diameter=%f matrix=%m4", RNA_int_get(op->ptr, "subdivisions"), RNA_float_get(op->ptr, "size") * dia, mat)) { diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index aed16be5b73..9dc68848c69 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1965,7 +1965,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 +2067,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; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index f951073155d..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; } +#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]; @@ -309,6 +313,11 @@ static void ringsel_finish(bContext *C, wmOperator *op) RingSelOpData *lcd = op->customdata; 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; @@ -322,7 +331,8 @@ static void ringsel_finish(bContext *C, wmOperator *op) BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, 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) { @@ -552,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 diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index d3a4c951e06..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], diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 2f40d281505..cb1b4ebba72 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -734,7 +734,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.slots_out, "faces.out", 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)) { @@ -775,7 +775,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.slots_out, "edges.out", 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 */ @@ -819,7 +819,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.slots_out, "verts.out", 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)) { @@ -1269,12 +1269,12 @@ static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3 /* The cost is based on the simple sum of the length of the two edgees... */ sub_v3_v3v3(d1, v2, v1); sub_v3_v3v3(d2, v3, v2); - cost = len_v3(d1) + len_v3(d2); + 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; } @@ -1881,7 +1881,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); } diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c index c32033054e0..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.slots_in, "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.slots_out, "verts.out", 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 eb98efdfea3..3ff33b79f55 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -109,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); @@ -354,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(&extop, slot_edges_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(&extop, slot_edges_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(&extop, slot_edges_exclude, edge, NULL); + BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); } } } @@ -891,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 */ @@ -900,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); @@ -1343,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.slots_out, "geom.out", 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; @@ -2018,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; } @@ -2308,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); @@ -2317,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.slots_out, "verts.out", 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)) { @@ -2889,7 +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_edgepercents; + BMOpSlot *slot_edge_percents; /* allocd vars */ float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2]; @@ -2944,7 +2946,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) } /* store percentage of edge cut for KNIFE_EXACT here.*/ - slot_edgepercents = BMO_slot_get(bmop.slots_in, "edgepercents"); + 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)) { @@ -2957,7 +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(&bmop, slot_edgepercents, be, isect); + BMO_slot_map_float_insert(&bmop, slot_edge_percents, be, isect); } } } @@ -2978,8 +2980,8 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) BMO_slot_int_set(bmop.slots_in, "cuts", numcuts); BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_STRAIGHT_CUT); - BMO_slot_bool_set(bmop.slots_in, "use_singleedge", FALSE); - BMO_slot_bool_set(bmop.slots_in, "use_gridfill", FALSE); + 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.slots_in, "radius", 0); @@ -3596,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.slots_out, "geom.out", 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; } @@ -3634,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 */ @@ -3652,13 +3654,13 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) if (!EDBM_op_init(em, &spinop, op, "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b", - BM_ELEM_SELECT, cent, axis, d, steps, degr, dupli)) + 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.slots_out, "geom_last.out", 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; } @@ -3683,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"; @@ -3699,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); @@ -3737,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) { @@ -3782,7 +3783,7 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) } BMO_op_exec(bm, &spinop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", 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; } @@ -4947,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) @@ -4973,9 +4979,9 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) if (event->val == KM_PRESS) { /* Try to handle numeric inputs... */ #ifdef NEW_BEVEL - float value; 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); @@ -4983,9 +4989,8 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } #else - float factor; - 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); @@ -5026,6 +5031,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) #ifdef NEW_BEVEL case WHEELUPMOUSE: /* change number of segments */ + case PAGEUPKEY: if (event->val == KM_RELEASE) break; @@ -5036,6 +5042,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) break; case WHEELDOWNMOUSE: /* change number of segments */ + case PAGEDOWNKEY: if (event->val == KM_RELEASE) break; @@ -5365,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]); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 22c71d5d3ca..2cf63586142 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -265,9 +265,11 @@ int EDBM_op_callf(BMEditMesh *em, wmOperator *op, 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 *select_ 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.slots_out, select_slot_out, 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); @@ -498,7 +503,7 @@ void EDBM_select_more(BMEditMesh *em) 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.slots_out, "geom.out", 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); @@ -514,7 +519,7 @@ void EDBM_select_less(BMEditMesh *em) 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.slots_out, "geom.out", 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_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/object/object_add.c b/source/blender/editors/object/object_add.c index 4d1f2bbc4e9..ad1e2816c10 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -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); } } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index e7f09b4055a..f886b52e2ce 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1225,7 +1225,7 @@ static unsigned int move_to_layer_init(bContext *C, wmOperator *op) return lay; } -static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *event) { View3D *v3d = CTX_wm_view3d(C); if (v3d && v3d->localvd) { @@ -1233,7 +1233,7 @@ static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve } else { move_to_layer_init(C, op); - return WM_operator_props_dialog_popup(C, op, 260, 30); + return WM_operator_props_popup(C, op, event); } } @@ -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_vgroup.c b/source/blender/editors/object/object_vgroup.c index d7c7d4c04ef..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} }; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 2ac5f98927c..f5754297e9f 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -431,7 +431,7 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2 #else /* faster to use depths, these are calculated in PE_set_view3d_data */ /* 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) { + 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]]; diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 7b67f63c646..9a49a1970a0 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -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_shading.c b/source/blender/editors/render/render_shading.c index ebbdc90ab04..34677650f80 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -1480,7 +1480,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; } @@ -1642,7 +1642,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 3f438c5948e..e9fbb3a0885 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -65,6 +65,8 @@ #include "render_intern.h" // own include +extern Material defmaterial; + /***************************** Render Engines ********************************/ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) @@ -266,6 +268,9 @@ static void lamp_changed(Main *bmain, Lamp *la) 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) @@ -347,6 +352,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) @@ -375,6 +383,9 @@ 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) diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 676f033af32..a929c3ef585 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -656,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]; 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/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 38dbdcd8337..25ea08a4bb1 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; @@ -3890,8 +3893,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_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 7d2374738ef..95a5bbdf5c8 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -300,6 +300,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; @@ -322,6 +323,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/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index d97b112e95d..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; diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 62e941d3148..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. * 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 61d513929ad..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); 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 f8856cb9646..ecc09a35670 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -326,15 +326,11 @@ 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_VERTEX_GROUP: diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5fefafaa54a..1a84efa0b50 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -926,7 +926,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* 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_all_except(CTX_wm_manager(C), CTX_wm_screen(C)); + WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE); } render_size = sseq->render_size; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 00d4a943626..4e2bf982ff3 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -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 */ diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index f35a844afc9..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" @@ -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/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 726fd26b11d..1c31cd23e33 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -724,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; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index fcd92cd5639..6c23635da90 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1940,7 +1940,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas * 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) + if (tbase.object->dt != OB_BOUNDBOX) tbase.object->dtx = base->object->dtx; /* negative scale flag has to propagate */ diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 0d8567b256d..d45013c40d9 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2224,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) { @@ -2236,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_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_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 714898fed21..ef15c1e734e 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -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 b26718bb516..f93cfa25120 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2427,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 ;-) @@ -2440,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 */ @@ -2489,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); } } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 5b79b69f7ec..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; } 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_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 0feaec514d2..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; @@ -2667,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); + } } } } @@ -2692,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); @@ -2707,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]; @@ -2735,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 */ @@ -2805,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; - - uv = luv->uv; - - x = (uv[0] - offset[0]) * ell[0]; - y = (uv[1] - offset[1]) * ell[1]; + float x, y; + x = (uv[0] - offset[0]) * ellipse[0]; + y = (uv[1] - offset[1]) * ellipse[1]; + return ((x * x + y * y) < 1.0f); +} - 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; @@ -2843,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); @@ -2861,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); + } } } @@ -2906,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; @@ -2923,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]; @@ -2934,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) { @@ -3395,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); @@ -3425,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) { @@ -3443,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) { @@ -3507,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. */ @@ -3520,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); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index e10d70d48d1..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); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index efe9d1fedfe..1eec06eee75 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -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; diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index b26c25558c3..5f6eb45ad70 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -116,7 +116,7 @@ void GPU_set_anisotropic(float value); float GPU_get_anisotropic(void); /* enable gpu mipmapping */ -void GPU_set_gpu_mipmapping(int gpu_mipmap); +void GPU_set_gpu_mipmapping(void); /* Image updates and free * - these deal with images bound as opengl textures */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index e3ba4cb1f95..f2ddedcd76c 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -240,16 +240,10 @@ static struct GPUTextureState { /* Mipmap settings */ -void GPU_set_gpu_mipmapping(int gpu_mipmap) +void GPU_set_gpu_mipmapping() { - int old_value = GTS.gpu_mipmap; - - /* only actually enable if it's supported */ - GTS.gpu_mipmap = gpu_mipmap && GLEW_EXT_framebuffer_object; - - if (old_value != GTS.gpu_mipmap) { - GPU_free_images(); - } + /* always enable if it's supported */ + GTS.gpu_mipmap = GLEW_EXT_framebuffer_object; } void GPU_set_mipmap(int mipmap) diff --git a/source/blender/ikplugin/intern/ikplugin_api.c b/source/blender/ikplugin/intern/ikplugin_api.c index efe07b2c48c..507d54d7526 100644 --- a/source/blender/ikplugin/intern/ikplugin_api.c +++ b/source/blender/ikplugin/intern/ikplugin_api.c @@ -86,7 +86,7 @@ static IKPlugin ikplugin_tab[] = { static IKPlugin *get_plugin(bPose *pose) { - if (!pose || pose->iksolver < 0 || pose->iksolver > (sizeof(ikplugin_tab)/sizeof(IKPlugin) - 2)) + 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/imbuf/intern/openexr/CMakeLists.txt b/source/blender/imbuf/intern/openexr/CMakeLists.txt index 6c428afe535..d5cb8e8a3b6 100644 --- a/source/blender/imbuf/intern/openexr/CMakeLists.txt +++ b/source/blender/imbuf/intern/openexr/CMakeLists.txt @@ -52,6 +52,4 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() -message(STATUS "EXR ${INC_SYS}") - blender_add_lib(bf_imbuf_openexr "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 1684cf28b3c..a05ff66e683 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -294,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; 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_object.c b/source/blender/makesrna/intern/rna_object.c index a669cb2558a..bd51af77b34 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2174,7 +2174,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); 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_texture.c b/source/blender/makesrna/intern/rna_texture.c index e67985f68c5..b212879512e 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; @@ -603,7 +603,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_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 59a3a8c2522..50341c84b8f 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -144,12 +144,6 @@ static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA rna_userdef_update(bmain, scene, ptr); } -static void rna_userdef_gl_gpu_mipmaps(Main *bmain, Scene *scene, PointerRNA *ptr) -{ - GPU_set_gpu_mipmapping(U.use_gpu_mipmap); - rna_userdef_update(bmain, scene, ptr); -} - static void rna_userdef_gl_texture_limit_update(Main *bmain, Scene *scene, PointerRNA *ptr) { GPU_free_images(); @@ -3234,11 +3228,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "16 Bit Float Textures", "Use 16 bit per component texture for float images"); RNA_def_property_update(prop, 0, "rna_userdef_gl_use_16bit_textures"); - prop = RNA_def_property(srna, "use_gpu_mipmap", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "use_gpu_mipmap", 1); - RNA_def_property_ui_text(prop, "GPU Mipmap Generation", "Generate Image Mipmaps on the GPU"); - RNA_def_property_update(prop, 0, "rna_userdef_gl_gpu_mipmaps"); - prop = RNA_def_property(srna, "use_vertex_buffer_objects", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_VBO); RNA_def_property_ui_text(prop, "VBOs", 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/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index d4463098f07..3ca2c364345 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -274,10 +274,10 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], 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(slot_targetmap, v2))) { + while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(weld_op, slot_targetmap, v, v2); + BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2); } BMO_op_finish(bm, &find_op); @@ -319,7 +319,7 @@ static void merge_first_last(BMesh *bm, 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(weld_op, slot_targetmap, v, v2); + BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2); } BMO_op_finish(bm, &find_op); @@ -494,11 +494,11 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, /* check in case the target vertex (v2) is already marked * for merging */ - while ((v3 = BMO_slot_map_ptr_get(slot_targetmap, v2))) { + while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(&weld_op, slot_targetmap, v, v2); + BMO_slot_map_elem_insert(&weld_op, slot_targetmap, v, v2); } #undef _E diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 3f8eaa438c9..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; } } } diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 9f702957fa5..a73d52a0a63 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -941,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; @@ -996,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; @@ -1093,7 +1093,7 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n, 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(&op, slot_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); @@ -1287,8 +1287,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f "weld_verts"); slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); for (i = 0; i < 4; i++) { - BMO_slot_map_ptr_insert(&op, slot_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); @@ -1310,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); } } diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index eecc1e46827..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); diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index e402924c04f..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); 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/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 0335d295fba..69256fafc3d 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -473,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) { @@ -512,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; } @@ -532,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/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..697a9259b37 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,9 +97,56 @@ 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} }; diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c index 2b82826eb04..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,335 +68,6 @@ static PyObject *bpy_bmesh_op_repr(BPy_BMeshOpFunc *self) } -static PyObject *pyrna_op_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 = BMO_slot_get(bmop.slots_in, 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 { - 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) ")", - 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 { - 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", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - 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", - 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, 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 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, bmop.slots_in, slot_name, BM_VERT); - } - else if (BPy_BMEdgeSeq_Check(value)) { - BPY_BM_GENERIC_MESH_TEST("edges"); - BMO_slot_buffer_from_all(bm, &bmop, bmop.slots_in, slot_name, BM_EDGE); - } - else if (BPy_BMFaceSeq_Check(value)) { - BPY_BM_GENERIC_MESH_TEST("faces"); - 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; - - 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, 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, 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, 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", - 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); - - /* 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 = 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_ELEMENT_BUF: - { - 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[i]; - PyList_SET_ITEM(item, j, ele ? BPy_BMElem_CreatePyObject(bm, ele) : (Py_INCREF(Py_None), Py_None)); - } - break; - } - case BMO_OP_SLOT_MAPPING: - { - GHash *slot_hash = BMO_SLOT_AS_GHASH(slot); - GHashIterator *hash_iter; - item = PyDict_New(); - - for (hash_iter = BLI_ghashIterator_new(slot_hash); - !BLI_ghashIterator_isDone(hash_iter); - BLI_ghashIterator_step(hash_iter) ) - { - BMHeader *ele_key = BLI_ghashIterator_getKey(hash_iter); - BMHeader **ele_val = BLI_ghashIterator_getValue(hash_iter); - - PyObject *py_key = ele_key ? BPy_BMElem_CreatePyObject(bm, ele_key) : (Py_INCREF(Py_None), Py_None); - PyObject *py_val = *ele_val ? BPy_BMElem_CreatePyObject(bm, *ele_val) : (Py_INCREF(Py_None), Py_None); - - PyDict_SetItem(ret, py_key, py_val); - Py_DECREF(py_key); - Py_DECREF(py_val); - } - BLI_ghashIterator_free(hash_iter); - break; - } - } - BLI_assert(item != NULL); - 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; -} - PyTypeObject bmesh_op_Type = { PyVarObject_HEAD_INIT(NULL, 0) @@ -440,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 */ @@ -501,15 +152,15 @@ 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 *opname = _PyUnicode_AsString(pyname); for (i = 0; i < tot; i++) { - if (strcmp(opdefines[i]->opname, opname) == 0) { - return bpy_bmesh_op_CreatePyObject(opdefines[i]->opname); + if (strcmp(bmo_opdefines[i]->opname, opname) == 0) { + return bpy_bmesh_op_CreatePyObject(opname); } } @@ -519,23 +170,23 @@ static PyObject *bpy_bmesh_fmod_getattro(PyObject *UNUSED(self), PyObject *pynam 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]->opname)); + 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} }; @@ -565,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 */ @@ -594,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 <Python.h> + +#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 ee4528df50d..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[] = { @@ -1232,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); @@ -1372,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); @@ -1432,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); @@ -1604,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); @@ -1708,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, @@ -1777,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, @@ -1863,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, @@ -1906,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); @@ -1936,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); @@ -1966,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); @@ -3032,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; @@ -3400,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); - -#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 +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 + +/* 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 14132d08fe6..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); - - if (self->bm != value->bm) { - PyErr_SetString(PyExc_ValueError, - "layer.copy_from(): layer is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "layer.copy_from()"); - 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"); 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/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 6993e1baab4..f87478bb663 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1708,8 +1708,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; a<totface; a++) strandbuf->totbound = max_ii(strandbuf->totbound, (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a): a); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index e35e3edfa33..1037542759f 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -360,8 +360,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 1d8949292ce..c88011aab13 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -301,6 +301,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) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index b3c9cfbc79e..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; 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_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index c9f0bbffc63..1b8bcd51564 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -183,7 +183,7 @@ void WM_init(bContext *C, int argc, const char **argv) GPU_extensions_init(); GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); GPU_set_anisotropic(U.anisotropic_filter); - GPU_set_gpu_mipmapping(U.use_gpu_mipmap); + GPU_set_gpu_mipmapping(); UI_init(); } diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 7481c01d72b..3c3e2c0feaa 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -416,6 +416,18 @@ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) } +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_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 84cfe791bce..80ceb5700e5 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -793,7 +793,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); @@ -1025,6 +1025,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; @@ -1032,7 +1049,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); @@ -1042,11 +1058,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) { @@ -1058,7 +1075,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); @@ -1207,22 +1223,21 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) * \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_operator_repeat(C, op); - } + if (do_call) + wm_block_redo_cb(C, op, 0); return OPERATOR_RUNNING_MODAL; } @@ -1566,7 +1581,7 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_ uiButSetSearchFunc(but, operator_search_cb, NULL, operator_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); diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 8e86ecbff93..67bf9599baf 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -472,14 +472,17 @@ elseif(WIN32) 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 ) @@ -503,10 +506,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() " ) @@ -514,6 +517,8 @@ 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) diff --git a/source/creator/blender.map b/source/creator/blender.map index dc7bc3151e8..928d0c2d904 100644 --- a/source/creator/blender.map +++ b/source/creator/blender.map @@ -1,11 +1,16 @@ -/* on Linux we exclude LLVM symbols, they conflict with Mesa llvmpipe */ +/* 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 26162051147..80b9ca89420 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1081,7 +1081,7 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with" "\n\t\t-j <frame>\tSet frame step to <frame>" "\n\t\t-s <frame>\tPlay from <frame>" - "\n\t\t-j <frame>\tPlay until <frame>"; + "\n\t\t-e <frame>\tPlay until <frame>"; static char game_doc[] = "Game Engine specific options" "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames" 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_BlenderKeyboardDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp index f4e325eabb8..19ba46ed6d7 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp @@ -105,7 +105,7 @@ bool KX_BlenderKeyboardDevice::ConvertBlenderEvent(unsigned short incode,short v { int previousTable = 1-m_currentTable; - if (val == KM_PRESS) + if (val == KM_PRESS || val == KM_DBL_CLICK) { if (kxevent == KX_KetsjiEngine::GetExitKey() && val != 0 && !m_hookesc) result = true; diff --git a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp index aa2392ded08..8d90eacd27f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp @@ -121,7 +121,7 @@ bool KX_BlenderMouseDevice::ConvertBlenderEvent(unsigned short incode,short val) // only process it, if it's a key if (kxevent > 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/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 4451c78b99c..475e139bfcc 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -756,6 +756,7 @@ int main(int argc, char** argv) } GPU_set_anisotropic(U.anisotropic_filter); + GPU_set_gpu_mipmapping(); // Create the system if (GHOST_ISystem::createSystem() == GHOST_kSuccess) 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/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 |