diff options
465 files changed, 24873 insertions, 9126 deletions
diff --git a/.gitignore b/.gitignore index 18b5ced86b7..8347d2d2944 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,9 @@ Desktop.ini /doc/python_api/sphinx-in-tmp/ /doc/python_api/sphinx-in/ /doc/python_api/sphinx-out/ +/doc/python_api/rst/bmesh.ops.rst +/doc/python_api/rst/in_menu.png +/doc/python_api/rst/menu_id.png +/doc/python_api/rst/op_prop.png +/doc/python_api/rst/run_script.png +/doc/python_api/rst/spacebar.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dfa838a5a2..709f8245e23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ endif() # this starts out unset list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/build_files/cmake/Modules") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/build_files/cmake/platform") # avoid having empty buildtype set(CMAKE_BUILD_TYPE_INIT "Release") @@ -323,6 +324,10 @@ option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg) option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ${_init_CODEC_FFMPEG}) option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" OFF) +# Alembic support +option(WITH_ALEMBIC "Enable Alembic Support" OFF) +option(WITH_ALEMBIC_HDF5 "Enable Legacy Alembic Support (not officially supported)" OFF) + if(APPLE) option(WITH_CODEC_QUICKTIME "Enable Quicktime Support" ON) endif() @@ -393,6 +398,7 @@ option(WITH_CYCLES "Enable Cycles Render Engine" ON) option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF) option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF) option(WITH_CYCLES_OSL "Build Cycles with OSL support" ${_init_CYCLES_OSL}) +option(WITH_CYCLES_OPENSUBDIV "Build Cycles with OpenSubdiv support" ON) option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF) set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 sm_35 sm_37 sm_50 sm_52 CACHE STRING "CUDA architectures to build binaries for") mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH) @@ -502,6 +508,19 @@ mark_as_advanced(WITH_CXX11) option(WITH_LEGACY_DEPSGRAPH "Build Blender with legacy dependency graph" ON) mark_as_advanced(WITH_LEGACY_DEPSGRAPH) +# Use hardcoded paths or find_package to find externals +option(WITH_WINDOWS_FIND_MODULES "Use find_package to locate libraries" OFF) +mark_as_advanced(WITH_WINDOWS_FIND_MODULES) + +option(WITH_WINDOWS_CODESIGN "Use signtool to sign the final binary." OFF) +mark_as_advanced(WITH_WINDOWS_CODESIGN) + +set(WINDOWS_CODESIGN_PFX CACHE FILEPATH "Path to pfx file to use for codesigning.") +mark_as_advanced(WINDOWS_CODESIGN_PFX) + +set(WINDOWS_CODESIGN_PFX_PASSWORD CACHE STRING "password for pfx file used for codesigning.") +mark_as_advanced(WINDOWS_CODESIGN_PFX_PASSWORD) + # avoid using again option_defaults_clear() @@ -720,6 +739,11 @@ if(WITH_OPENIMAGEIO) set(WITH_IMAGE_TIFF ON) endif() +# auto enable alembic linking dependencies +if(WITH_ALEMBIC) + set(WITH_IMAGE_OPENEXR ON) +endif() + # don't store paths to libs for portable distribution if(WITH_INSTALL_PORTABLE) set(CMAKE_SKIP_BUILD_RPATH TRUE) @@ -890,1537 +914,11 @@ endif() # - APPLE if(UNIX AND NOT APPLE) - macro(find_package_wrapper) - if(WITH_STATIC_LIBS) - find_package_static(${ARGV}) - else() - find_package(${ARGV}) - endif() - endmacro() - - find_package_wrapper(JPEG REQUIRED) - find_package_wrapper(PNG REQUIRED) - find_package_wrapper(ZLIB REQUIRED) - find_package_wrapper(Freetype REQUIRED) - - if(WITH_LZO AND WITH_SYSTEM_LZO) - find_package_wrapper(LZO) - if(NOT LZO_FOUND) - message(FATAL_ERROR "Failed finding system LZO version!") - endif() - endif() - - if(WITH_SYSTEM_EIGEN3) - find_package_wrapper(Eigen3) - if(NOT EIGEN3_FOUND) - message(FATAL_ERROR "Failed finding system Eigen3 version!") - endif() - endif() - # else values are set below for all platforms - - if(WITH_PYTHON) - # No way to set py35, remove for now. - # find_package(PythonLibs) - - # Use our own instead, since without py is such a rare case, - # require this package - # XXX Linking errors with debian static python :/ -# find_package_wrapper(PythonLibsUnix REQUIRED) - find_package(PythonLibsUnix REQUIRED) - endif() - - if(WITH_IMAGE_OPENEXR) - find_package_wrapper(OpenEXR) # our own module - if(NOT OPENEXR_FOUND) - set(WITH_IMAGE_OPENEXR OFF) - endif() - endif() - - if(WITH_IMAGE_OPENJPEG) - find_package_wrapper(OpenJPEG) - if(NOT OPENJPEG_FOUND) - set(WITH_IMAGE_OPENJPEG OFF) - endif() - endif() - - if(WITH_IMAGE_TIFF) - # XXX Linking errors with debian static tiff :/ -# find_package_wrapper(TIFF) - find_package(TIFF) - if(NOT TIFF_FOUND) - set(WITH_IMAGE_TIFF OFF) - endif() - endif() - - # Audio IO - if(WITH_SYSTEM_AUDASPACE) - find_package_wrapper(Audaspace) - if(NOT AUDASPACE_FOUND OR NOT AUDASPACE_C_FOUND) - message(FATAL_ERROR "Audaspace external library not found!") - endif() - endif() - - if(WITH_OPENAL) - find_package_wrapper(OpenAL) - if(NOT OPENAL_FOUND) - set(WITH_OPENAL OFF) - endif() - endif() - - if(WITH_SDL) - if(WITH_SDL_DYNLOAD) - set(SDL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extern/sdlew/include/SDL2") - set(SDL_LIBRARY) - else() - find_package_wrapper(SDL2) - if(SDL2_FOUND) - # Use same names for both versions of SDL until we move to 2.x. - set(SDL_INCLUDE_DIR "${SDL2_INCLUDE_DIR}") - set(SDL_LIBRARY "${SDL2_LIBRARY}") - set(SDL_FOUND "${SDL2_FOUND}") - else() - find_package_wrapper(SDL) - endif() - mark_as_advanced( - SDL_INCLUDE_DIR - SDL_LIBRARY - ) - # unset(SDLMAIN_LIBRARY CACHE) - if(NOT SDL_FOUND) - set(WITH_SDL OFF) - endif() - endif() - endif() - - if(WITH_JACK) - find_package_wrapper(Jack) - if(NOT JACK_FOUND) - set(WITH_JACK OFF) - endif() - endif() - - # Codecs - if(WITH_CODEC_SNDFILE) - find_package_wrapper(SndFile) - if(NOT SNDFILE_FOUND) - set(WITH_CODEC_SNDFILE OFF) - endif() - endif() - - if(WITH_CODEC_FFMPEG) - set(FFMPEG /usr CACHE PATH "FFMPEG Directory") - set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries") - - mark_as_advanced(FFMPEG) - - # lame, but until we have proper find module for ffmpeg - set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include) - if(EXISTS "${FFMPEG}/include/ffmpeg/") - list(APPEND FFMPEG_INCLUDE_DIRS "${FFMPEG}/include/ffmpeg") - endif() - # end lameness - - mark_as_advanced(FFMPEG_LIBRARIES) - set(FFMPEG_LIBPATH ${FFMPEG}/lib) - endif() - - if(WITH_FFTW3) - find_package_wrapper(Fftw3) - if(NOT FFTW3_FOUND) - set(WITH_FFTW3 OFF) - endif() - endif() - - if(WITH_OPENCOLLADA) - find_package_wrapper(OpenCOLLADA) - if(OPENCOLLADA_FOUND) - find_package_wrapper(XML2) - find_package_wrapper(PCRE) - else() - set(WITH_OPENCOLLADA OFF) - endif() - endif() - - if(WITH_MEM_JEMALLOC) - find_package_wrapper(JeMalloc) - if(NOT JEMALLOC_FOUND) - set(WITH_MEM_JEMALLOC OFF) - endif() - endif() - - if(WITH_INPUT_NDOF) - find_package_wrapper(Spacenav) - if(SPACENAV_FOUND) - # use generic names within blenders buildsystem. - set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS}) - set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES}) - else() - set(WITH_INPUT_NDOF OFF) - endif() - endif() - - if(WITH_CYCLES_OSL) - set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") - if(NOT OSL_ROOT) - set(OSL_ROOT ${CYCLES_OSL}) - endif() - find_package_wrapper(OpenShadingLanguage) - if(OSL_FOUND) - if(${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6") - # Note: --whole-archive is needed to force loading of all symbols in liboslexec, - # otherwise LLVM is missing the osl_allocate_closure_component function - set(OSL_LIBRARIES - ${OSL_OSLCOMP_LIBRARY} - -Wl,--whole-archive ${OSL_OSLEXEC_LIBRARY} - -Wl,--no-whole-archive ${OSL_OSLQUERY_LIBRARY} - ) - endif() - else() - message(STATUS "OSL not found, disabling it from Cycles") - set(WITH_CYCLES_OSL OFF) - endif() - endif() - - if(WITH_OPENVDB) - find_package_wrapper(OpenVDB) - find_package_wrapper(TBB) - if(NOT OPENVDB_FOUND OR NOT TBB_FOUND) - set(WITH_OPENVDB OFF) - set(WITH_OPENVDB_BLOSC OFF) - message(STATUS "OpenVDB not found, disabling it") - endif() - endif() - - if(WITH_BOOST) - # uses in build instructions to override include and library variables - if(NOT BOOST_CUSTOM) - if(WITH_STATIC_LIBS) - set(Boost_USE_STATIC_LIBS ON) - endif() - set(Boost_USE_MULTITHREADED ON) - set(__boost_packages filesystem regex system thread date_time) - if(WITH_CYCLES_OSL) - if(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6")) - list(APPEND __boost_packages wave) - else() - endif() - endif() - if(WITH_INTERNATIONAL) - list(APPEND __boost_packages locale) - endif() - if(WITH_CYCLES_NETWORK) - list(APPEND __boost_packages serialization) - endif() - if(WITH_OPENVDB) - list(APPEND __boost_packages iostreams) - endif() - find_package(Boost 1.48 COMPONENTS ${__boost_packages}) - if(NOT Boost_FOUND) - # try to find non-multithreaded if -mt not found, this flag - # doesn't matter for us, it has nothing to do with thread - # safety, but keep it to not disturb build setups - set(Boost_USE_MULTITHREADED OFF) - find_package(Boost 1.48 COMPONENTS ${__boost_packages}) - endif() - unset(__boost_packages) - if(Boost_USE_STATIC_LIBS AND WITH_BOOST_ICU) - find_package(IcuLinux) - endif() - mark_as_advanced(Boost_DIR) # why doesnt boost do this? - endif() - - set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS}) - set(BOOST_LIBRARIES ${Boost_LIBRARIES}) - set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS}) - set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB") - endif() - - if(WITH_OPENIMAGEIO) - find_package_wrapper(OpenImageIO) - if(NOT OPENIMAGEIO_PUGIXML_FOUND AND WITH_CYCLES_STANDALONE) - find_package_wrapper(PugiXML) - else() - set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}") - set(PUGIXML_LIBRARIES "") - endif() - - set(OPENIMAGEIO_LIBRARIES - ${OPENIMAGEIO_LIBRARIES} - ${PNG_LIBRARIES} - ${JPEG_LIBRARIES} - ${ZLIB_LIBRARIES} - ${BOOST_LIBRARIES} - ) - set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere - set(OPENIMAGEIO_DEFINITIONS "") - - if(WITH_IMAGE_TIFF) - list(APPEND OPENIMAGEIO_LIBRARIES "${TIFF_LIBRARY}") - endif() - if(WITH_IMAGE_OPENEXR) - list(APPEND OPENIMAGEIO_LIBRARIES "${OPENEXR_LIBRARIES}") - endif() - - if(NOT OPENIMAGEIO_FOUND) - set(WITH_OPENIMAGEIO OFF) - message(STATUS "OpenImageIO not found, disabling WITH_CYCLES") - endif() - endif() - - if(WITH_OPENCOLORIO) - find_package_wrapper(OpenColorIO) - - set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES}) - set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere - set(OPENCOLORIO_DEFINITIONS) - - if(NOT OPENCOLORIO_FOUND) - set(WITH_OPENCOLORIO OFF) - message(STATUS "OpenColorIO not found") - endif() - endif() - - if(WITH_LLVM) - find_package_wrapper(LLVM) - - if(NOT LLVM_FOUND) - set(WITH_LLVM OFF) - message(STATUS "LLVM not found") - endif() - endif() - - if(WITH_LLVM OR WITH_SDL_DYNLOAD) - # Fix for conflict with Mesa llvmpipe - set(PLATFORM_LINKFLAGS - "${PLATFORM_LINKFLAGS} -Wl,--version-script='${CMAKE_SOURCE_DIR}/source/creator/blender.map'" - ) - endif() - - if(WITH_OPENSUBDIV) - find_package_wrapper(OpenSubdiv) - - set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES}) - set(OPENSUBDIV_LIBPATH) # TODO, remove and reference the absolute path everywhere - - if(NOT OPENSUBDIV_FOUND) - set(WITH_OPENSUBDIV OFF) - message(STATUS "OpenSubdiv not found") - endif() - endif() - - # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed - list(APPEND PLATFORM_LINKLIBS -lutil -lc -lm) - - find_package(Threads REQUIRED) - list(APPEND PLATFORM_LINKLIBS ${CMAKE_THREAD_LIBS_INIT}) - # used by other platforms - set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - - if(CMAKE_DL_LIBS) - list(APPEND PLATFORM_LINKLIBS ${CMAKE_DL_LIBS}) - endif() - - if(CMAKE_SYSTEM_NAME MATCHES "Linux") - if(NOT WITH_PYTHON_MODULE) - # binreloc is linux only - set(BINRELOC_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/binreloc/include) - set(WITH_BINRELOC ON) - endif() - endif() - - # lfs on glibc, all compilers should use - add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) - - # GNU Compiler - if(CMAKE_COMPILER_IS_GNUCC) - set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") - - # use ld.gold linker if available, could make optional - execute_process( - COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version - ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) - if("${LD_VERSION}" MATCHES "GNU gold") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") - else() - message(STATUS "GNU gold linker isn't available, using the default system linker.") - endif() - unset(LD_VERSION) - - # CLang is the same as GCC for now. - elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") - set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") - # Solaris CC - elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro") - set(PLATFORM_CFLAGS "-pipe -features=extensions -fPIC -D__FUNCTION__=__func__") - - # Intel C++ Compiler - elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") - # think these next two are broken - find_program(XIAR xiar) - if(XIAR) - set(CMAKE_AR "${XIAR}") - endif() - mark_as_advanced(XIAR) - - find_program(XILD xild) - if(XILD) - set(CMAKE_LINKER "${XILD}") - endif() - mark_as_advanced(XILD) - - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fp-model precise -prec_div -parallel") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fp-model precise -prec_div -parallel") - - # set(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -diag-enable sc3") - set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -static-intel") - endif() - + include(platform_unix) elseif(WIN32) - - add_definitions(-DWIN32) - - if(MSVC) - # Minimum MSVC Version - if(MSVC_VERSION EQUAL 1800) - set(_min_ver "18.0.31101") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver}) - message(FATAL_ERROR - "Visual Studio 2013 (Update 4, ${_min_ver}) required, " - "found (${CMAKE_CXX_COMPILER_VERSION})") - endif() - endif() - if(MSVC_VERSION EQUAL 1900) - set(_min_ver "19.0.24210") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver}) - message(FATAL_ERROR - "Visual Studio 2015 (Update 3, ${_min_ver}) required, " - "found (${CMAKE_CXX_COMPILER_VERSION})") - endif() - endif() - unset(_min_ver) - - # needed for some MSVC installations - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") - - list(APPEND PLATFORM_LINKLIBS - ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 - advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp - ) - - if(WITH_INPUT_IME) - list(APPEND PLATFORM_LINKLIBS imm32) - endif() - - add_definitions( - -D_CRT_NONSTDC_NO_DEPRECATE - -D_CRT_SECURE_NO_DEPRECATE - -D_SCL_SECURE_NO_DEPRECATE - -D_CONSOLE - -D_LIB - ) - - # MSVC11 needs _ALLOW_KEYWORD_MACROS to build - add_definitions(-D_ALLOW_KEYWORD_MACROS) - - if(CMAKE_CL_64) - # We want to support Vista level ABI for x64 - add_definitions(-D_WIN32_WINNT=0x600) - endif() - - # Make cmake find the msvc redistributables - set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE) - include(InstallRequiredSystemLibraries) - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP") - - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MT") - set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MT") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT") - - set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO ") - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib ") - - # Ignore meaningless for us linker warnings. - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /ignore:4049 /ignore:4217 /ignore:4221") - set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") - - # MSVC only, Mingw doesnt need - if(CMAKE_CL_64) - set(PLATFORM_LINKFLAGS "/MACHINE:X64 /OPT:NOREF ${PLATFORM_LINKFLAGS}") - else() - set(PLATFORM_LINKFLAGS "/MACHINE:IX86 /LARGEADDRESSAWARE ${PLATFORM_LINKFLAGS}") - endif() - - set(PLATFORM_LINKFLAGS_DEBUG "/IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib") - - if(NOT DEFINED LIBDIR) - - # Setup 64bit and 64bit windows systems - if(CMAKE_CL_64) - message(STATUS "64 bit compiler detected.") - set(LIBDIR_BASE "win64") - else() - message(STATUS "32 bit compiler detected.") - set(LIBDIR_BASE "windows") - endif() - - if(MSVC_VERSION EQUAL 1900) - message(STATUS "Visual Studio 2015 detected.") - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14) - else() - message(STATUS "Visual Studio 2013 detected.") - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc12) - endif() - else() - message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") - endif() - if(NOT EXISTS "${LIBDIR}/") - message(FATAL_ERROR "Windows requires pre-compiled libs at: '${LIBDIR}'") - endif() - - # Add each of our libraries to our cmake_prefix_path so find_package() could work - file(GLOB children RELATIVE ${LIBDIR} ${LIBDIR}/*) - foreach(child ${children}) - if(IS_DIRECTORY ${LIBDIR}/${child}) - list(APPEND CMAKE_PREFIX_PATH ${LIBDIR}/${child}) - endif() - endforeach() - - set(ZLIB_INCLUDE_DIRS ${LIBDIR}/zlib/include) - set(ZLIB_LIBRARIES ${LIBDIR}/zlib/lib/libz_st.lib) - set(ZLIB_INCLUDE_DIR ${LIBDIR}/zlib/include) - set(ZLIB_LIBRARY ${LIBDIR}/zlib/lib/libz_st.lib) - set(ZLIB_DIR ${LIBDIR}/zlib) - #find_package(zlib) # we want to find before finding things that depend on it like png - - - find_package(png) - if(NOT PNG_FOUND) - message(WARNING "Using HARDCODED libpng locations") - set(PNG_PNG_INCLUDE_DIR ${LIBDIR}/png/include) - set(PNG_LIBRARIES libpng) - set(PNG "${LIBDIR}/png") - set(PNG_INCLUDE_DIRS "${PNG}/include") - set(PNG_LIBPATH ${PNG}/lib) # not cmake defined - endif() - - set(JPEG_NAMES ${JPEG_NAMES} libjpeg) - find_package(jpeg REQUIRED) - - set(PTHREADS_INCLUDE_DIRS ${LIBDIR}/pthreads/include) - set(PTHREADS_LIBRARIES ${LIBDIR}/pthreads/lib/pthreadVC2.lib) - - set(FREETYPE ${LIBDIR}/freetype) - set(FREETYPE_INCLUDE_DIRS - ${LIBDIR}/freetype/include - ${LIBDIR}/freetype/include/freetype2 - ) - set(FREETYPE_LIBRARY ${LIBDIR}/freetype/lib/freetype2ST.lib) - find_package(freetype REQUIRED) - - if(WITH_FFTW3) - set(FFTW3 ${LIBDIR}/fftw3) - set(FFTW3_LIBRARIES libfftw) - set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) - set(FFTW3_LIBPATH ${FFTW3}/lib) - endif() - - if(WITH_OPENCOLLADA) - set(OPENCOLLADA ${LIBDIR}/opencollada) - - set(OPENCOLLADA_INCLUDE_DIRS - ${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter - ${OPENCOLLADA}/include/opencollada/COLLADABaseUtils - ${OPENCOLLADA}/include/opencollada/COLLADAFramework - ${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader - ${OPENCOLLADA}/include/opencollada/GeneratedSaxParser - ) - - set(OPENCOLLADA_LIBRARIES - ${OPENCOLLADA}/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib - ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAFramework.lib - ${OPENCOLLADA}/lib/opencollada/OpenCOLLADABaseUtils.lib - ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter.lib - ${OPENCOLLADA}/lib/opencollada/MathMLSolver.lib - ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser.lib - ${OPENCOLLADA}/lib/opencollada/xml.lib - ${OPENCOLLADA}/lib/opencollada/buffer.lib - ${OPENCOLLADA}/lib/opencollada/ftoa.lib - ) - - if(NOT WITH_LLVM) - list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/UTF.lib) - endif() - - set(PCRE_LIBRARIES - ${OPENCOLLADA}/lib/opencollada/pcre.lib - ) - endif() - - if(WITH_CODEC_FFMPEG) - set(FFMPEG_INCLUDE_DIRS - ${LIBDIR}/ffmpeg/include - ${LIBDIR}/ffmpeg/include/msvc - ) - find_package(FFMPEG) - if(NOT FFMPEG_FOUND) - message(WARNING "Using HARDCODED ffmpeg locations") - set(FFMPEG_LIBRARY_VERSION 55) - set(FFMPEG_LIBRARY_VERSION_AVU 52) - set(FFMPEG_LIBRARIES - ${LIBDIR}/ffmpeg/lib/avcodec-${FFMPEG_LIBRARY_VERSION}.lib - ${LIBDIR}/ffmpeg/lib/avformat-${FFMPEG_LIBRARY_VERSION}.lib - ${LIBDIR}/ffmpeg/lib/avdevice-${FFMPEG_LIBRARY_VERSION}.lib - ${LIBDIR}/ffmpeg/lib/avutil-${FFMPEG_LIBRARY_VERSION_AVU}.lib - ${LIBDIR}/ffmpeg/lib/swscale-2.lib - ) - endif() - endif() - - if(WITH_IMAGE_OPENEXR) - set(OPENEXR_ROOT_DIR ${LIBDIR}/openexr) - set(OPENEXR_VERSION "2.1") - find_package(OPENEXR REQUIRED) - if(NOT OPENEXR_FOUND) - message(WARNING "Using HARDCODED OpenEXR locations") - set(OPENEXR ${LIBDIR}/openexr) - set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) - set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR}/include/OpenEXR) - set(OPENEXR_LIBPATH ${OPENEXR}/lib) - set(OPENEXR_LIBRARIES - optimized ${OPENEXR_LIBPATH}/Iex-2_2.lib - optimized ${OPENEXR_LIBPATH}/Half.lib - optimized ${OPENEXR_LIBPATH}/IlmImf-2_2.lib - optimized ${OPENEXR_LIBPATH}/Imath-2_2.lib - optimized ${OPENEXR_LIBPATH}/IlmThread-2_2.lib - debug ${OPENEXR_LIBPATH}/Iex-2_2_d.lib - debug ${OPENEXR_LIBPATH}/Half_d.lib - debug ${OPENEXR_LIBPATH}/IlmImf-2_2_d.lib - debug ${OPENEXR_LIBPATH}/Imath-2_2_d.lib - debug ${OPENEXR_LIBPATH}/IlmThread-2_2_d.lib - ) - endif() - endif() - - if(WITH_IMAGE_TIFF) - # Try to find tiff first then complain and set static and maybe wrong paths - find_package(TIFF) - if(NOT TIFF_FOUND) - message(WARNING "Using HARDCODED libtiff locations") - set(TIFF_LIBRARY ${LIBDIR}/tiff/lib/libtiff.lib) - set(TIFF_INCLUDE_DIR ${LIBDIR}/tiff/include) - endif() - endif() - - if(WITH_JACK) - set(JACK_INCLUDE_DIRS - ${LIBDIR}/jack/include/jack - ${LIBDIR}/jack/include - ) - set(JACK_LIBRARIES optimized ${LIBDIR}/jack/lib/libjack.lib debug ${LIBDIR}/jack/lib/libjack_d.lib) - endif() - - if(WITH_PYTHON) - set(PYTHON_VERSION 3.5) # CACHE STRING) - - string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) - # Use shared libs for vc2008 and vc2010 until we actually have vc2010 libs - set(PYTHON_LIBRARY ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) - unset(_PYTHON_VERSION_NO_DOTS) - - # Shared includes for both vc2008 and vc2010 - set(PYTHON_INCLUDE_DIR ${LIBDIR}/python/include/python${PYTHON_VERSION}) - - # uncached vars - set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") - set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") - endif() - - if(WITH_BOOST) - if(WITH_CYCLES_OSL) - set(boost_extra_libs wave) - endif() - if(WITH_INTERNATIONAL) - list(APPEND boost_extra_libs locale) - endif() - if(WITH_OPENVDB) - list(APPEND boost_extra_libs iostreams) - endif() - set(Boost_USE_STATIC_RUNTIME ON) # prefix lib - set(Boost_USE_MULTITHREADED ON) # suffix -mt - set(Boost_USE_STATIC_LIBS ON) # suffix -s - find_package(Boost COMPONENTS date_time filesystem thread regex system ${boost_extra_libs}) - if(NOT Boost_FOUND) - message(WARNING "USING HARDCODED boost locations") - set(BOOST ${LIBDIR}/boost) - set(BOOST_INCLUDE_DIR ${BOOST}/include) - if(MSVC12) - set(BOOST_LIBPATH ${BOOST}/lib) - set(BOOST_POSTFIX "vc120-mt-s-1_60.lib") - set(BOOST_DEBUG_POSTFIX "vc120-mt-sgd-1_60.lib") - else() - set(BOOST_LIBPATH ${BOOST}/lib) - set(BOOST_POSTFIX "vc140-mt-s-1_60.lib") - set(BOOST_DEBUG_POSTFIX "vc140-mt-sgd-1_60.lib") - endif() - set(BOOST_LIBRARIES - optimized libboost_date_time-${BOOST_POSTFIX} - optimized libboost_filesystem-${BOOST_POSTFIX} - optimized libboost_regex-${BOOST_POSTFIX} - optimized libboost_system-${BOOST_POSTFIX} - optimized libboost_thread-${BOOST_POSTFIX} - debug libboost_date_time-${BOOST_DEBUG_POSTFIX} - debug libboost_filesystem-${BOOST_DEBUG_POSTFIX} - debug libboost_regex-${BOOST_DEBUG_POSTFIX} - debug libboost_system-${BOOST_DEBUG_POSTFIX} - debug libboost_thread-${BOOST_DEBUG_POSTFIX} - ) - if(WITH_CYCLES_OSL) - set(BOOST_LIBRARIES ${BOOST_LIBRARIES} - optimized libboost_wave-${BOOST_POSTFIX} - debug libboost_wave-${BOOST_DEBUG_POSTFIX}) - endif() - if(WITH_INTERNATIONAL) - set(BOOST_LIBRARIES ${BOOST_LIBRARIES} - optimized libboost_locale-${BOOST_POSTFIX} - debug libboost_locale-${BOOST_DEBUG_POSTFIX}) - endif() - else() # we found boost using find_package - set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS}) - set(BOOST_LIBRARIES ${Boost_LIBRARIES}) - set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS}) - endif() - set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB") - endif() - - if(WITH_OPENIMAGEIO) - find_package(OpenImageIO) - set(OPENIMAGEIO ${LIBDIR}/openimageio) - set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) - set(OIIO_OPTIMIZED optimized OpenImageIO optimized OpenImageIO_Util) - set(OIIO_DEBUG debug OpenImageIO_d debug OpenImageIO_Util_d) - set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG}) - set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib) - set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0") - set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD") - set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe") - add_definitions(-DOIIO_STATIC_BUILD) - endif() - - if(WITH_LLVM) - set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") - file(GLOB LLVM_LIBRARY_OPTIMIZED ${LLVM_ROOT_DIR}/lib/*.lib) - - if(EXISTS ${LLVM_ROOT_DIR}/debug/lib) - foreach(LLVM_OPTIMIZED_LIB ${LLVM_LIBRARY_OPTIMIZED}) - get_filename_component(LIBNAME ${LLVM_OPTIMIZED_LIB} ABSOLUTE) - list(APPEND LLVM_LIBS optimized ${LIBNAME}) - endforeach(LLVM_OPTIMIZED_LIB) - - file(GLOB LLVM_LIBRARY_DEBUG ${LLVM_ROOT_DIR}/debug/lib/*.lib) - - foreach(LLVM_DEBUG_LIB ${LLVM_LIBRARY_DEBUG}) - get_filename_component(LIBNAME ${LLVM_DEBUG_LIB} ABSOLUTE) - list(APPEND LLVM_LIBS debug ${LIBNAME}) - endforeach(LLVM_DEBUG_LIB) - - set(LLVM_LIBRARY ${LLVM_LIBS}) - else() - message(WARNING "LLVM debug libs not present on this system. Using release libs for debug builds.") - set(LLVM_LIBRARY ${LLVM_LIBRARY_OPTIMIZED}) - endif() - - endif() - - if(WITH_OPENCOLORIO) - set(OPENCOLORIO ${LIBDIR}/opencolorio) - set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) - set(OPENCOLORIO_LIBRARIES OpenColorIO) - set(OPENCOLORIO_LIBPATH ${LIBDIR}/opencolorio/lib) - set(OPENCOLORIO_DEFINITIONS) - endif() - - if(WITH_OPENVDB) - set(BLOSC_LIBRARIES optimized ${LIBDIR}/blosc/lib/libblosc.lib debug ${LIBDIR}/blosc/lib/libblosc_d.lib) - set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib) - set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include) - set(OPENVDB ${LIBDIR}/openvdb) - set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include ${TBB_INCLUDE_DIR}) - set(OPENVDB_LIBRARIES optimized openvdb debug openvdb_d ${TBB_LIBRARIES} ${BLOSC_LIBRARIES}) - set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib) - endif() - - if(WITH_MOD_CLOTH_ELTOPO) - set(LAPACK ${LIBDIR}/lapack) - # set(LAPACK_INCLUDE_DIR ${LAPACK}/include) - set(LAPACK_LIBPATH ${LAPACK}/lib) - set(LAPACK_LIBRARIES - ${LIBDIR}/lapack/lib/libf2c.lib - ${LIBDIR}/lapack/lib/clapack_nowrap.lib - ${LIBDIR}/lapack/lib/BLAS_nowrap.lib - ) - endif() - - if(WITH_OPENSUBDIV) - set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include) - set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib) - set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBPATH}/osdCPU.lib ${OPENSUBDIV_LIBPATH}/osdGPU.lib) - find_package(OpenSubdiv) - endif() - - if(WITH_SDL) - set(SDL ${LIBDIR}/sdl) - set(SDL_INCLUDE_DIR ${SDL}/include) - set(SDL_LIBPATH ${SDL}/lib) - # MinGW TODO: Update MinGW to SDL2 - if(NOT CMAKE_COMPILER_IS_GNUCC) - set(SDL_LIBRARY SDL2) - else() - set(SDL_LIBRARY SDL) - endif() - endif() - - # Audio IO - if(WITH_SYSTEM_AUDASPACE) - set(AUDASPACE_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace) - set(AUDASPACE_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace.lib) - set(AUDASPACE_C_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace) - set(AUDASPACE_C_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-c.lib) - set(AUDASPACE_PY_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace) - set(AUDASPACE_PY_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-py.lib) - endif() - - # used in many places so include globally, like OpenGL - blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}") - - elseif(CMAKE_COMPILER_IS_GNUCC) - # keep GCC specific stuff here - include(CheckCSourceCompiles) - # Setup 64bit and 64bit windows systems - CHECK_C_SOURCE_COMPILES(" - #ifndef __MINGW64__ - #error - #endif - int main(void) { return 0; } - " - WITH_MINGW64 - ) - - if(NOT DEFINED LIBDIR) - if(WITH_MINGW64) - message(STATUS "Compiling for 64 bit with MinGW-w64.") - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64) - else() - message(STATUS "Compiling for 32 bit with MinGW-w32.") - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32) - - if(WITH_RAYOPTIMIZATION) - message(WARNING "MinGW-w32 is known to be unstable with 'WITH_RAYOPTIMIZATION' option enabled.") - endif() - endif() - else() - message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") - endif() - if(NOT EXISTS "${LIBDIR}/") - message(FATAL_ERROR "Windows requires pre-compiled libs at: '${LIBDIR}'") - endif() - - list(APPEND PLATFORM_LINKLIBS - -lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 - -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi -ldbghelp - ) - - if(WITH_INPUT_IME) - list(APPEND PLATFORM_LINKLIBS -limm32) - endif() - - set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing") - - if(WITH_MINGW64) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") - list(APPEND PLATFORM_LINKLIBS -lpthread) - - add_definitions(-DFREE_WINDOWS64 -DMS_WIN64) - endif() - - add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) - - add_definitions(-DFREE_WINDOWS) - - set(PNG "${LIBDIR}/png") - set(PNG_INCLUDE_DIRS "${PNG}/include") - set(PNG_LIBPATH ${PNG}/lib) # not cmake defined - - if(WITH_MINGW64) - set(JPEG_LIBRARIES jpeg) - else() - set(JPEG_LIBRARIES libjpeg) - endif() - set(PNG_LIBRARIES png) - - set(ZLIB ${LIBDIR}/zlib) - set(ZLIB_INCLUDE_DIRS ${ZLIB}/include) - set(ZLIB_LIBPATH ${ZLIB}/lib) - set(ZLIB_LIBRARIES z) - - set(JPEG "${LIBDIR}/jpeg") - set(JPEG_INCLUDE_DIR "${JPEG}/include") - set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined - - # comes with own pthread library - if(NOT WITH_MINGW64) - set(PTHREADS ${LIBDIR}/pthreads) - #set(PTHREADS_INCLUDE_DIRS ${PTHREADS}/include) - set(PTHREADS_LIBPATH ${PTHREADS}/lib) - set(PTHREADS_LIBRARIES pthreadGC2) - endif() - - set(FREETYPE ${LIBDIR}/freetype) - set(FREETYPE_INCLUDE_DIRS ${FREETYPE}/include ${FREETYPE}/include/freetype2) - set(FREETYPE_LIBPATH ${FREETYPE}/lib) - set(FREETYPE_LIBRARY freetype) - - if(WITH_FFTW3) - set(FFTW3 ${LIBDIR}/fftw3) - set(FFTW3_LIBRARIES fftw3) - set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) - set(FFTW3_LIBPATH ${FFTW3}/lib) - endif() - - if(WITH_OPENCOLLADA) - set(OPENCOLLADA ${LIBDIR}/opencollada) - set(OPENCOLLADA_INCLUDE_DIRS - ${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter - ${OPENCOLLADA}/include/opencollada/COLLADABaseUtils - ${OPENCOLLADA}/include/opencollada/COLLADAFramework - ${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader - ${OPENCOLLADA}/include/opencollada/GeneratedSaxParser - ) - set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib/opencollada) - set(OPENCOLLADA_LIBRARIES - OpenCOLLADAStreamWriter - OpenCOLLADASaxFrameworkLoader - OpenCOLLADAFramework - OpenCOLLADABaseUtils - GeneratedSaxParser - UTF MathMLSolver buffer ftoa xml - ) - set(PCRE_LIBRARIES pcre) - endif() - - if(WITH_CODEC_FFMPEG) - set(FFMPEG ${LIBDIR}/ffmpeg) - set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include) - if(WITH_MINGW64) - set(FFMPEG_LIBRARIES avcodec.dll avformat.dll avdevice.dll avutil.dll swscale.dll swresample.dll) - else() - set(FFMPEG_LIBRARIES avcodec-55 avformat-55 avdevice-55 avutil-52 swscale-2) - endif() - set(FFMPEG_LIBPATH ${FFMPEG}/lib) - endif() - - if(WITH_IMAGE_OPENEXR) - set(OPENEXR ${LIBDIR}/openexr) - set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) - set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR) - set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex) - set(OPENEXR_LIBPATH ${OPENEXR}/lib) - endif() - - if(WITH_IMAGE_TIFF) - set(TIFF ${LIBDIR}/tiff) - set(TIFF_LIBRARY tiff) - set(TIFF_INCLUDE_DIR ${TIFF}/include) - set(TIFF_LIBPATH ${TIFF}/lib) - endif() - - if(WITH_JACK) - set(JACK ${LIBDIR}/jack) - set(JACK_INCLUDE_DIRS ${JACK}/include/jack ${JACK}/include) - set(JACK_LIBRARIES jack) - set(JACK_LIBPATH ${JACK}/lib) - - # TODO, gives linking errors, force off - set(WITH_JACK OFF) - endif() - - if(WITH_PYTHON) - # normally cached but not since we include them with blender - set(PYTHON_VERSION 3.5) # CACHE STRING) - string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) - set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH) - set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}mw.lib") # CACHE FILEPATH) - unset(_PYTHON_VERSION_NO_DOTS) - - # uncached vars - set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") - set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") - endif() - - if(WITH_BOOST) - set(BOOST ${LIBDIR}/boost) - set(BOOST_INCLUDE_DIR ${BOOST}/include) - if(WITH_MINGW64) - set(BOOST_POSTFIX "mgw47-mt-s-1_49") - set(BOOST_DEBUG_POSTFIX "mgw47-mt-sd-1_49") - else() - set(BOOST_POSTFIX "mgw46-mt-s-1_49") - set(BOOST_DEBUG_POSTFIX "mgw46-mt-sd-1_49") - endif() - set(BOOST_LIBRARIES - optimized boost_date_time-${BOOST_POSTFIX} boost_filesystem-${BOOST_POSTFIX} - boost_regex-${BOOST_POSTFIX} - boost_system-${BOOST_POSTFIX} boost_thread-${BOOST_POSTFIX} - debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX} - boost_regex-${BOOST_DEBUG_POSTFIX} - boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX}) - if(WITH_INTERNATIONAL) - set(BOOST_LIBRARIES ${BOOST_LIBRARIES} - optimized boost_locale-${BOOST_POSTFIX} - debug boost_locale-${BOOST_DEBUG_POSTFIX} - ) - endif() - if(WITH_CYCLES_OSL) - set(BOOST_LIBRARIES ${BOOST_LIBRARIES} - optimized boost_wave-${BOOST_POSTFIX} - debug boost_wave-${BOOST_DEBUG_POSTFIX} - ) - endif() - set(BOOST_LIBPATH ${BOOST}/lib) - set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ") - endif() - - if(WITH_OPENIMAGEIO) - set(OPENIMAGEIO ${LIBDIR}/openimageio) - set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) - set(OPENIMAGEIO_LIBRARIES OpenImageIO) - set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib) - set(OPENIMAGEIO_DEFINITIONS "") - set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe") - endif() - - if(WITH_LLVM) - set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") - set(LLVM_LIBPATH ${LLVM_ROOT_DIR}/lib) - # Explicitly set llvm lib order. - #---- WARNING ON GCC ORDER OF LIBS IS IMPORTANT, DO NOT CHANGE! --------- - set(LLVM_LIBRARY LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMAnalysis LLVMArchive - LLVMAsmParser LLVMAsmPrinter - LLVMBitReader LLVMBitWriter - LLVMDebugInfo LLVMExecutionEngine - LLVMInstCombine LLVMInstrumentation - LLVMInterpreter LLVMJIT - LLVMLinker LLVMMC - LLVMMCDisassembler LLVMMCJIT - LLVMMCParser LLVMObject - LLVMRuntimeDyld - LLVMSupport - LLVMTableGen LLVMTarget - LLVMTransformUtils LLVMVectorize - LLVMX86AsmParser LLVMX86AsmPrinter - LLVMX86CodeGen LLVMX86Desc - LLVMX86Disassembler LLVMX86Info - LLVMX86Utils LLVMipa - LLVMipo LLVMCore) - # imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc - list(APPEND PLATFORM_LINKLIBS -limagehlp) - endif() - - if(WITH_OPENCOLORIO) - set(OPENCOLORIO ${LIBDIR}/opencolorio) - set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) - set(OPENCOLORIO_LIBRARIES OpenColorIO) - set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib) - set(OPENCOLORIO_DEFINITIONS) - endif() - - if(WITH_SDL) - set(SDL ${LIBDIR}/sdl) - set(SDL_INCLUDE_DIR ${SDL}/include) - set(SDL_LIBRARY SDL) - set(SDL_LIBPATH ${SDL}/lib) - endif() - - if(WITH_OPENVDB) - set(OPENVDB ${LIBDIR}/openvdb) - set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include) - set(OPENVDB_LIBRARIES openvdb ${TBB_LIBRARIES}) - set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib) - set(OPENVDB_DEFINITIONS) - endif() - - set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152") - - ## DISABLE - causes linking errors - ## for re-distribution, so users dont need mingw installed - # set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -static-libgcc -static-libstdc++") - - endif() - - # Things common to both mingw and MSVC should go here - - set(WINTAB_INC ${LIBDIR}/wintab/include) - - if(WITH_OPENAL) - set(OPENAL ${LIBDIR}/openal) - set(OPENALDIR ${LIBDIR}/openal) - set(OPENAL_INCLUDE_DIR ${OPENAL}/include) - if(MSVC) - set(OPENAL_LIBRARY openal32) - else() - set(OPENAL_LIBRARY wrap_oal) - endif() - set(OPENAL_LIBPATH ${OPENAL}/lib) - endif() - - if(WITH_CODEC_SNDFILE) - set(SNDFILE ${LIBDIR}/sndfile) - set(SNDFILE_INCLUDE_DIRS ${SNDFILE}/include) - set(SNDFILE_LIBRARIES libsndfile-1) - set(SNDFILE_LIBPATH ${SNDFILE}/lib) # TODO, deprecate - endif() - - if(WITH_RAYOPTIMIZATION AND SUPPORT_SSE_BUILD) - add_definitions(-D__SSE__ -D__MMX__) - endif() - - if(WITH_CYCLES_OSL) - set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") - - 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) - find_library(OSL_LIB_EXEC_DEBUG NAMES oslexec_d PATHS ${CYCLES_OSL}/lib) - find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib) - find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib) - list(APPEND OSL_LIBRARIES - optimized ${OSL_LIB_COMP} - optimized ${OSL_LIB_EXEC} - optimized ${OSL_LIB_QUERY} - debug ${OSL_LIB_EXEC_DEBUG} - debug ${OSL_LIB_COMP_DEBUG} - debug ${OSL_LIB_QUERY_DEBUG} - ) - find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) - find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) - - if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER) - set(OSL_FOUND TRUE) - else() - message(STATUS "OSL not found") - set(WITH_CYCLES_OSL OFF) - endif() - endif() - + include(platform_win32) elseif(APPLE) - - if(NOT DEFINED LIBDIR) - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-9.x.universal) - else() - message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") - endif() - if(NOT EXISTS "${LIBDIR}/") - message(FATAL_ERROR "Mac OSX requires pre-compiled libs at: '${LIBDIR}'") - endif() - - if(WITH_OPENAL) - find_package(OpenAL) - if(OPENAL_FOUND) - set(WITH_OPENAL ON) - set(OPENAL_INCLUDE_DIR "${LIBDIR}/openal/include") - else() - set(WITH_OPENAL OFF) - endif() - endif() - - if(WITH_OPENSUBDIV) - set(OPENSUBDIV ${LIBDIR}/opensubdiv) - set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib) - find_library(OSL_LIB_UTIL NAMES osdutil PATHS ${OPENSUBDIV_LIBPATH}) - find_library(OSL_LIB_CPU NAMES osdCPU PATHS ${OPENSUBDIV_LIBPATH}) - find_library(OSL_LIB_GPU NAMES osdGPU PATHS ${OPENSUBDIV_LIBPATH}) - set(OPENSUBDIV_INCLUDE_DIR ${OPENSUBDIV}/include) - set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR}) - list(APPEND OPENSUBDIV_LIBRARIES ${OSL_LIB_UTIL} ${OSL_LIB_CPU} ${OSL_LIB_GPU}) - endif() - - if(WITH_JACK) - find_library(JACK_FRAMEWORK - NAMES jackmp - ) - set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) - if(NOT JACK_FRAMEWORK) - set(WITH_JACK OFF) - endif() - endif() - - if(WITH_CODEC_SNDFILE) - set(SNDFILE ${LIBDIR}/sndfile) - set(SNDFILE_INCLUDE_DIRS ${SNDFILE}/include) - set(SNDFILE_LIBRARIES sndfile FLAC ogg vorbis vorbisenc) - set(SNDFILE_LIBPATH ${SNDFILE}/lib ${FFMPEG}/lib) # TODO, deprecate - endif() - - if(WITH_PYTHON) - # we use precompiled libraries for py 3.5 and up by default - set(PYTHON_VERSION 3.5) - if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK) - # normally cached but not since we include them with blender - set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}m") - set(PYTHON_EXECUTABLE "${LIBDIR}/python/bin/python${PYTHON_VERSION}m") - set(PYTHON_LIBRARY python${PYTHON_VERSION}m) - set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}") - # set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled - else() - # module must be compiled against Python framework - set(_py_framework "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}") - - set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}m") - set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}m") - set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}m") - #set(PYTHON_LIBRARY python${PYTHON_VERSION}) - #set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled - - unset(_py_framework) - endif() - - # uncached vars - set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") - set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") - - if(NOT EXISTS "${PYTHON_EXECUTABLE}") - message(FATAL_ERROR "Python executable missing: ${PYTHON_EXECUTABLE}") - endif() - endif() - - if(WITH_FFTW3) - set(FFTW3 ${LIBDIR}/fftw3) - set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) - set(FFTW3_LIBRARIES fftw3) - set(FFTW3_LIBPATH ${FFTW3}/lib) - endif() - - set(PNG_LIBRARIES png) - set(JPEG_LIBRARIES jpeg) - - set(ZLIB /usr) - set(ZLIB_INCLUDE_DIRS "${ZLIB}/include") - set(ZLIB_LIBRARIES z bz2) - - set(FREETYPE ${LIBDIR}/freetype) - set(FREETYPE_INCLUDE_DIRS ${FREETYPE}/include ${FREETYPE}/include/freetype2) - set(FREETYPE_LIBPATH ${FREETYPE}/lib) - set(FREETYPE_LIBRARY freetype) - - if(WITH_IMAGE_OPENEXR) - set(OPENEXR ${LIBDIR}/openexr) - set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) - set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR}/include/OpenEXR) - set(OPENEXR_LIBRARIES Iex Half IlmImf Imath IlmThread) - set(OPENEXR_LIBPATH ${OPENEXR}/lib) - endif() - - if(WITH_CODEC_FFMPEG) - set(FFMPEG ${LIBDIR}/ffmpeg) - set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include) - set(FFMPEG_LIBRARIES - avcodec avdevice avformat avutil - mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg - ) - set(FFMPEG_LIBPATH ${FFMPEG}/lib) - endif() - - find_library(SYSTEMSTUBS_LIBRARY - NAMES - SystemStubs - PATHS - ) - mark_as_advanced(SYSTEMSTUBS_LIBRARY) - if(SYSTEMSTUBS_LIBRARY) - list(APPEND PLATFORM_LINKLIBS SystemStubs) - endif() - - set(PLATFORM_CFLAGS "-pipe -funsigned-char") - set(PLATFORM_LINKFLAGS - "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -framework CoreAudio" - ) - if(WITH_CODEC_QUICKTIME) - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QTKit") - if(CMAKE_OSX_ARCHITECTURES MATCHES i386) - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime") - # libSDL still needs 32bit carbon quicktime - endif() - endif() - - if(WITH_CXX11) - list(APPEND PLATFORM_LINKLIBS c++) - else() - list(APPEND PLATFORM_LINKLIBS stdc++) - endif() - - if(WITH_JACK) - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -F/Library/Frameworks -weak_framework jackmp") - endif() - - if(WITH_PYTHON_MODULE OR WITH_PYTHON_FRAMEWORK) - # force cmake to link right framework - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/Python") - endif() - - if(WITH_OPENCOLLADA) - set(OPENCOLLADA ${LIBDIR}/opencollada) - - set(OPENCOLLADA_INCLUDE_DIRS - ${LIBDIR}/opencollada/include/COLLADAStreamWriter - ${LIBDIR}/opencollada/include/COLLADABaseUtils - ${LIBDIR}/opencollada/include/COLLADAFramework - ${LIBDIR}/opencollada/include/COLLADASaxFrameworkLoader - ${LIBDIR}/opencollada/include/GeneratedSaxParser - ) - - set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib) - set(OPENCOLLADA_LIBRARIES - OpenCOLLADASaxFrameworkLoader - -lOpenCOLLADAFramework - -lOpenCOLLADABaseUtils - -lOpenCOLLADAStreamWriter - -lMathMLSolver - -lGeneratedSaxParser - -lxml2 -lbuffer -lftoa - ) - # Use UTF functions from collada if LLVM is not enabled - if(NOT WITH_LLVM) - list(APPEND OPENCOLLADA_LIBRARIES -lUTF) - endif() - # pcre is bundled with openCollada - #set(PCRE ${LIBDIR}/pcre) - #set(PCRE_LIBPATH ${PCRE}/lib) - set(PCRE_LIBRARIES pcre) - #libxml2 is used - #set(EXPAT ${LIBDIR}/expat) - #set(EXPAT_LIBPATH ${EXPAT}/lib) - set(EXPAT_LIB) - endif() - - if(WITH_SDL) - set(SDL ${LIBDIR}/sdl) - set(SDL_INCLUDE_DIR ${SDL}/include) - set(SDL_LIBRARY SDL2) - set(SDL_LIBPATH ${SDL}/lib) - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lazy_framework ForceFeedback") - endif() - - set(PNG "${LIBDIR}/png") - set(PNG_INCLUDE_DIRS "${PNG}/include") - set(PNG_LIBPATH ${PNG}/lib) - - set(JPEG "${LIBDIR}/jpeg") - set(JPEG_INCLUDE_DIR "${JPEG}/include") - set(JPEG_LIBPATH ${JPEG}/lib) - - if(WITH_IMAGE_TIFF) - set(TIFF ${LIBDIR}/tiff) - set(TIFF_INCLUDE_DIR ${TIFF}/include) - set(TIFF_LIBRARY tiff) - set(TIFF_LIBPATH ${TIFF}/lib) - endif() - - if(WITH_BOOST) - set(BOOST ${LIBDIR}/boost) - set(BOOST_INCLUDE_DIR ${BOOST}/include) - set(BOOST_LIBRARIES - boost_date_time-mt - boost_filesystem-mt - boost_regex-mt - boost_system-mt - boost_thread-mt - boost_wave-mt - ) - if(WITH_INTERNATIONAL) - list(APPEND BOOST_LIBRARIES boost_locale-mt) - endif() - if(WITH_CYCLES_NETWORK) - list(APPEND BOOST_LIBRARIES boost_serialization-mt) - endif() - if(WITH_OPENVDB) - list(APPEND BOOST_LIBRARIES boost_iostreams-mt) - endif() - set(BOOST_LIBPATH ${BOOST}/lib) - set(BOOST_DEFINITIONS) - endif() - - if(WITH_INTERNATIONAL OR WITH_CODEC_FFMPEG) - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale and ffmpeg needs it ! - endif() - - if(WITH_OPENIMAGEIO) - set(OPENIMAGEIO ${LIBDIR}/openimageio) - set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) - set(OPENIMAGEIO_LIBRARIES - ${OPENIMAGEIO}/lib/libOpenImageIO.a - ${PNG_LIBRARIES} - ${JPEG_LIBRARIES} - ${TIFF_LIBRARY} - ${OPENEXR_LIBRARIES} - ${ZLIB_LIBRARIES} - ) - set(OPENIMAGEIO_LIBPATH - ${OPENIMAGEIO}/lib - ${JPEG_LIBPATH} - ${PNG_LIBPATH} - ${TIFF_LIBPATH} - ${OPENEXR_LIBPATH} - ${ZLIB_LIBPATH} - ) - set(OPENIMAGEIO_DEFINITIONS "-DOIIO_STATIC_BUILD") - set(OPENIMAGEIO_IDIFF "${LIBDIR}/openimageio/bin/idiff") - endif() - - if(WITH_OPENCOLORIO) - set(OPENCOLORIO ${LIBDIR}/opencolorio) - set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) - set(OPENCOLORIO_LIBRARIES OpenColorIO tinyxml yaml-cpp) - set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib) - endif() - - if(WITH_OPENVDB) - set(OPENVDB ${LIBDIR}/openvdb) - set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include) - set(TBB_INCLUDE_DIRS ${LIBDIR}/tbb/include) - set(TBB_LIBRARIES ${LIBDIR}/tbb/lib/libtbb.a) - set(OPENVDB_LIBRARIES openvdb blosc ${TBB_LIBRARIES}) - set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib) - set(OPENVDB_DEFINITIONS) - endif() - - if(WITH_LLVM) - set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") - set(LLVM_VERSION "3.4" CACHE STRING "Version of LLVM to use") - if(EXISTS "${LLVM_ROOT_DIR}/bin/llvm-config") - set(LLVM_CONFIG "${LLVM_ROOT_DIR}/bin/llvm-config") - else() - set(LLVM_CONFIG llvm-config) - endif() - execute_process(COMMAND ${LLVM_CONFIG} --version - OUTPUT_VARIABLE LLVM_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND ${LLVM_CONFIG} --prefix - OUTPUT_VARIABLE LLVM_ROOT_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND ${LLVM_CONFIG} --libdir - OUTPUT_VARIABLE LLVM_LIBPATH - OUTPUT_STRIP_TRAILING_WHITESPACE) - find_library(LLVM_LIBRARY - NAMES LLVMAnalysis # first of a whole bunch of libs to get - PATHS ${LLVM_LIBPATH}) - - if(LLVM_LIBRARY AND LLVM_ROOT_DIR AND LLVM_LIBPATH) - if(LLVM_STATIC) - # if static LLVM libraries were requested, use llvm-config to generate - # the list of what libraries we need, and substitute that in the right - # way for LLVM_LIBRARY. - execute_process(COMMAND ${LLVM_CONFIG} --libfiles - OUTPUT_VARIABLE LLVM_LIBRARY - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY}) - else() - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lLLVM-3.4") - endif() - else() - message(FATAL_ERROR "LLVM not found.") - endif() - endif() - - if(WITH_CYCLES_OSL) - set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") - - find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) - find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) - find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) - # WARNING! depends on correct order of OSL libs linking - list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) - find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) - find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) - - if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER) - set(OSL_FOUND TRUE) - else() - message(STATUS "OSL not found") - set(WITH_CYCLES_OSL OFF) - endif() - endif() - - if(WITH_OPENMP) - execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE COMPILER_VENDOR) - string(SUBSTRING "${COMPILER_VENDOR}" 0 5 VENDOR_NAME) # truncate output - if(${VENDOR_NAME} MATCHES "Apple") # Apple does not support OpenMP reliable with gcc and not with clang - set(WITH_OPENMP OFF) - else() # vanilla gcc or clang_omp support OpenMP - message(STATUS "Using special OpenMP enabled compiler !") # letting find_package(OpenMP) module work for gcc - if(CMAKE_C_COMPILER_ID MATCHES "Clang") # clang-omp in darwin libs - set(OPENMP_FOUND ON) - set(OpenMP_C_FLAGS "-fopenmp" CACHE STRING "C compiler flags for OpenMP parallization" FORCE) - set(OpenMP_CXX_FLAGS "-fopenmp" CACHE STRING "C++ compiler flags for OpenMP parallization" FORCE) - include_directories(${LIBDIR}/openmp/include) - link_directories(${LIBDIR}/openmp/lib) - # This is a workaround for our helperbinaries ( datatoc, masgfmt, ... ), - # They are linked also to omp lib, so we need it in builddir for runtime exexcution, - # TODO: remove all unneeded dependencies from these - - # for intermediate binaries, in respect to lib ID - execute_process( - COMMAND ditto -arch ${CMAKE_OSX_ARCHITECTURES} - ${LIBDIR}/openmp/lib/libiomp5.dylib - ${CMAKE_BINARY_DIR}/Resources/lib/libiomp5.dylib) - endif() - endif() - endif() - - set(EXETYPE MACOSX_BUNDLE) - - set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g") - set(CMAKE_CXX_FLAGS_DEBUG "-fno-strict-aliasing -g") - if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64" OR CMAKE_OSX_ARCHITECTURES MATCHES "i386") - set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3") - set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3") - if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller") - endif() - else() - set(CMAKE_C_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing") - set(CMAKE_CXX_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing") - endif() - - if(${XCODE_VERSION} VERSION_EQUAL 5 OR ${XCODE_VERSION} VERSION_GREATER 5) - # Xcode 5 is always using CLANG, which has too low template depth of 128 for libmv - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=1024") - endif() - # Get rid of eventually clashes, we export some symbols explicite as local - set(PLATFORM_LINKFLAGS - "${PLATFORM_LINKFLAGS} -Xlinker -unexported_symbols_list -Xlinker ${CMAKE_SOURCE_DIR}/source/creator/osx_locals.map" - ) - - if(WITH_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -stdlib=libc++") - endif() - - # Suppress ranlib "has no symbols" warnings (workaround for T48250) - set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>") - set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>") - set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>") - set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>") + include(platform_apple) endif() #----------------------------------------------------------------------------- @@ -2452,6 +950,11 @@ if(WITH_CYCLES) ) endif() endif() + + if(WITH_CYCLES_OPENSUBDIV AND NOT WITH_OPENSUBDIV) + message(STATUS "WITH_CYCLES_OPENSUBDIV requires WITH_OPENSUBDIV to be ON, turning OFF") + set(WITH_CYCLES_OPENSUBDIV OFF) + endif() endif() if(WITH_INTERNATIONAL) @@ -2504,8 +1007,6 @@ else() endif() unset(_SYSTEM_BIG_ENDIAN) endif() - - if(WITH_IMAGE_OPENJPEG) if(WITH_SYSTEM_OPENJPEG) # dealt with above @@ -3215,6 +1716,7 @@ if(FIRST_RUN) info_cfg_option(WITH_FREESTYLE) info_cfg_option(WITH_OPENCOLORIO) info_cfg_option(WITH_OPENVDB) + info_cfg_option(WITH_ALEMBIC) info_cfg_text("Compiler Options:") info_cfg_option(WITH_BUILDINFO) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 068ac665623..51928b82d8c 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -29,13 +29,13 @@ getopt \ ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\ force-all,force-python,force-numpy,force-boost,\ force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\ -force-ffmpeg,force-opencollada,\ +force-ffmpeg,force-opencollada,force-alembic,\ build-all,build-python,build-numpy,build-boost,\ build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\ -build-ffmpeg,build-opencollada,\ +build-ffmpeg,build-opencollada,build-alembic,\ skip-python,skip-numpy,skip-boost,\ skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\ -skip-ffmpeg,skip-opencollada \ +skip-ffmpeg,skip-opencollada,skip-alembic \ -- "$@" \ ) @@ -167,6 +167,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --build-openvdb Force the build of OpenVDB. + --build-alembic + Force the build of Alembic. + --build-opencollada Force the build of OpenCOLLADA. @@ -216,6 +219,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --force-openvdb Force the rebuild of OpenVDB. + --force-alembic + Force the rebuild of Alembic. + --force-opencollada Force the rebuild of OpenCOLLADA. @@ -258,6 +264,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --skip-openvdb Unconditionally skip OpenVDB installation/building. + --skip-alembic + Unconditionally skip Alembic installation/building. + --skip-opencollada Unconditionally skip OpenCOLLADA installation/building. @@ -328,7 +337,7 @@ OSL_FORCE_REBUILD=false OSL_SKIP=false # OpenSubdiv needs to be compiled for now -OSD_VERSION="3.0.2" +OSD_VERSION="3.0.5" OSD_VERSION_MIN=$OSD_VERSION OSD_FORCE_BUILD=false OSD_FORCE_REBUILD=false @@ -343,6 +352,13 @@ OPENVDB_FORCE_BUILD=false OPENVDB_FORCE_REBUILD=false OPENVDB_SKIP=false +# Alembic needs to be compiled for now +ALEMBIC_VERSION="1.6.0" +ALEMBIC_VERSION_MIN=$ALEMBIC_VERSION +ALEMBIC_FORCE_BUILD=false +ALEMBIC_FORCE_REBUILD=false +ALEMBIC_SKIP=false + # Version?? OPENCOLLADA_VERSION="1.3" OPENCOLLADA_FORCE_BUILD=false @@ -525,6 +541,7 @@ while true; do OPENVDB_FORCE_BUILD=true OPENCOLLADA_FORCE_BUILD=true FFMPEG_FORCE_BUILD=true + ALEMBIC_FORCE_BUILD=true shift; continue ;; --build-python) @@ -567,6 +584,9 @@ while true; do --build-ffmpeg) FFMPEG_FORCE_BUILD=true; shift; continue ;; + --build-alembic) + ALEMBIC_FORCE_BUILD=true; shift; continue + ;; --force-all) PYTHON_FORCE_REBUILD=true NUMPY_FORCE_REBUILD=true @@ -580,6 +600,7 @@ while true; do OPENVDB_FORCE_REBUILD=true OPENCOLLADA_FORCE_REBUILD=true FFMPEG_FORCE_REBUILD=true + ALEMBIC_FORCE_REBUILD=true shift; continue ;; --force-python) @@ -620,6 +641,9 @@ while true; do --force-ffmpeg) FFMPEG_FORCE_REBUILD=true; shift; continue ;; + --force-alembic) + ALEMBIC_FORCE_REBUILD=true; shift; continue + ;; --skip-python) PYTHON_SKIP=true; shift; continue ;; @@ -656,6 +680,9 @@ while true; do --skip-ffmpeg) FFMPEG_SKIP=true; shift; continue ;; + --skip-alembic) + ALEMBIC_SKIP=true; shift; continue + ;; --) # no more arguments to parse break @@ -683,7 +710,7 @@ NUMPY_SOURCE=( "http://sourceforge.net/projects/numpy/files/NumPy/$NUMPY_VERSION _boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'` BOOST_SOURCE=( "http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download" ) -BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams" +BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams --with-python --with-program_options" OCIO_SOURCE=( "https://github.com/imageworks/OpenColorIO/tarball/v$OCIO_VERSION" ) @@ -712,7 +739,7 @@ OSL_SOURCE_REPO=( "https://github.com/Nazg-Gul/OpenShadingLanguage.git" ) OSL_SOURCE_REPO_UID="7d40ff5fe8e47b030042afb92d0e955f5aa96f48" OSL_SOURCE_REPO_BRANCH="blender-fixes" -OSD_USE_REPO=true +OSD_USE_REPO=false # Script foo to make the version string compliant with the archive name: # ${Varname//SearchForThisChar/ReplaceWithThisChar} OSD_SOURCE=( "https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v${OSD_VERSION//./_}.tar.gz" ) @@ -727,6 +754,12 @@ OPENVDB_SOURCE=( "https://github.com/dreamworksanimation/openvdb/archive/v${OPEN #~ OPENVDB_SOURCE_REPO_UID="404659fffa659da075d1c9416e4fc939139a84ee" #~ OPENVDB_SOURCE_REPO_BRANCH="dev" +ALEMBIC_USE_REPO=false +ALEMBIC_SOURCE=( "https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.tar.gz" ) +# ALEMBIC_SOURCE_REPO=( "https://github.com/alembic/alembic.git" ) +# ALEMBIC_SOURCE_REPO_UID="e6c90d4faa32c4550adeaaf3f556dad4b73a92bb" +# ALEMBIC_SOURCE_REPO_BRANCH="master" + OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" ) OPENCOLLADA_REPO_UID="3335ac164e68b2512a40914b14c74db260e6ff7d" OPENCOLLADA_REPO_BRANCH="master" @@ -767,7 +800,8 @@ You may also want to build them yourself (optional ones are [between brackets]): * [OpenShadingLanguage $OSL_VERSION_MIN] (from $OSL_SOURCE_REPO, branch $OSL_SOURCE_REPO_BRANCH, commit $OSL_SOURCE_REPO_UID). * [OpenSubDiv $OSD_VERSION_MIN] (from $OSD_SOURCE_REPO, branch $OSD_SOURCE_REPO_BRANCH, commit $OSD_SOURCE_REPO_UID). * [OpenVDB $OPENVDB_VERSION_MIN] (from $OPENVDB_SOURCE), [Blosc $OPENVDB_BLOSC_VERSION] (from $OPENVDB_BLOSC_SOURCE). - * [OpenCollada] (from $OPENCOLLADA_SOURCE, branch $OPENCOLLADA_REPO_BRANCH, commit $OPENCOLLADA_REPO_UID).\"" + * [OpenCollada] (from $OPENCOLLADA_SOURCE, branch $OPENCOLLADA_REPO_BRANCH, commit $OPENCOLLADA_REPO_UID). + * [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).\"" if [ "$DO_SHOW_DEPS" = true ]; then PRINT "" @@ -1118,7 +1152,7 @@ compile_Boost() { fi # To be changed each time we make edits that would modify the compiled result! - boost_magic=10 + boost_magic=11 _init_boost @@ -1873,7 +1907,7 @@ compile_OSD() { fi # To be changed each time we make edits that would modify the compiled result! - osd_magic=1 + osd_magic=2 _init_osd # Clean install if needed! @@ -2138,6 +2172,102 @@ compile_OPENVDB() { run_ldconfig "openvdb" } +#### Build Alembic #### +_init_alembic() { + _src=$SRC/alembic-$ALEMBIC_VERSION + _git=false + _inst=$INST/alembic-$ALEMBIC_VERSION + _inst_shortcut=$INST/alembic +} + +clean_ALEMBIC() { + _init_alembic + _clean +} + +compile_ALEMBIC() { + if [ "$NO_BUILD" = true ]; then + WARNING "--no-build enabled, Alembic will not be compiled!" + return + fi + + compile_HDF5 + PRINT "" + + # To be changed each time we make edits that would modify the compiled result! + alembic_magic=2 + _init_alembic + + # Clean install if needed! + magic_compile_check alembic-$ALEMBIC_VERSION $alembic_magic + if [ $? -eq 1 -o "$ALEMBIC_FORCE_REBUILD" = true ]; then + clean_ALEMBIC + fi + + if [ ! -d $_inst ]; then + INFO "Building Alembic-$ALEMBIC_VERSION" + + prepare_opt + + if [ ! -d $_src -o true ]; then + mkdir -p $SRC + download ALEMBIC_SOURCE[@] "$_src.tar.gz" + + INFO "Unpacking Alembic-$ALEMBIC_VERSION" + tar -C $SRC -xf $_src.tar.gz + fi + + cd $_src + + cmake_d="-D CMAKE_INSTALL_PREFIX=$_inst" + + if [ -d $INST/boost ]; then + cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost" + cmake_d="$cmake_d -D USE_STATIC_BOOST=ON" + else + cmake_d="$cmake_d -D USE_STATIC_BOOST=OFF" + fi + + if [ "$_with_built_openexr" = true ]; then + cmake_d="$cmake_d -D ILMBASE_ROOT=$INST/openexr" + cmake_d="$cmake_d -D USE_ARNOLD=OFF" + cmake_d="$cmake_d -D USE_BINARIES=OFF" + cmake_d="$cmake_d -D USE_EXAMPLES=OFF" + cmake_d="$cmake_d -D USE_HDF5=OFF" + cmake_d="$cmake_d -D USE_MAYA=OFF" + cmake_d="$cmake_d -D USE_PRMAN=OFF" + cmake_d="$cmake_d -D USE_PYALEMBIC=OFF" + cmake_d="$cmake_d -D USE_STATIC_HDF5=OFF" + cmake_d="$cmake_d -D ALEMBIC_ILMBASE_LINK_STATIC=OFF" + cmake_d="$cmake_d -D ALEMBIC_SHARED_LIBS=OFF" + cmake_d="$cmake_d -D ALEMBIC_LIB_USES_BOOST=ON" + cmake_d="$cmake_d -D ALEMBIC_LIB_USES_TR1=OFF" + INFO "ILMBASE_ROOT=$INST/openexr" + fi + + cmake $cmake_d ./ + make -j$THREADS install + make clean + + if [ -d $_inst ]; then + _create_inst_shortcut + else + ERROR "Alembic-$ALEMBIC_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set alembic-$ALEMBIC_VERSION $alembic_magic + + cd $CWD + INFO "Done compiling Alembic-$ALEMBIC_VERSION!" + else + INFO "Own Alembic-$ALEMBIC_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-alembic option." + fi + + run_ldconfig "alembic" +} + #### Build OpenCOLLADA #### _init_opencollada() { _src=$SRC/OpenCOLLADA-$OPENCOLLADA_VERSION @@ -2746,6 +2876,17 @@ install_DEB() { fi fi + PRINT "" + if [ "$ALEMBIC_SKIP" = true ]; then + WARNING "Skipping Alembic installation, as requested..." + elif [ "$ALEMBIC_FORCE_BUILD" = true ]; then + INFO "Forced Alembic building, as requested..." + compile_ALEMBIC + else + # No package currently, only HDF5! + compile_ALEMBIC + fi + if [ "$WITH_OPENCOLLADA" = true ]; then _do_compile_collada=false @@ -3283,6 +3424,17 @@ install_RPM() { compile_OPENVDB fi + PRINT "" + if [ "$ALEMBIC_SKIP" = true ]; then + WARNING "Skipping Alembic installation, as requested..." + elif [ "$ALEMBIC_FORCE_BUILD" = true ]; then + INFO "Forced Alembic building, as requested..." + compile_ALEMBIC + else + # No package currently! + compile_ALEMBIC + fi + if [ "$WITH_OPENCOLLADA" = true ]; then PRINT "" @@ -3693,6 +3845,16 @@ install_ARCH() { fi fi + PRINT "" + if [ "$ALEMBIC_SKIP" = true ]; then + WARNING "Skipping Alembic installation, as requested..." + elif [ "$ALEMBIC_FORCE_BUILD" = true ]; then + INFO "Forced Alembic building, as requested..." + compile_ALEMBIC + else + compile_ALEMBIC + fi + if [ "$WITH_OPENCOLLADA" = true ]; then PRINT "" @@ -4000,7 +4162,7 @@ print_info() { _buildargs="-U *SNDFILE* -U *PYTHON* -U *BOOST* -U *Boost*" _buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*" - _buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG*" + _buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC*" _1="-D WITH_CODEC_SNDFILE=ON" PRINT " $_1" @@ -4106,6 +4268,17 @@ print_info() { _buildargs="$_buildargs $_1" fi + if [ "$ALEMBIC_SKIP" = false ]; then + _1="-D WITH_ALEMBIC=ON" + PRINT " $_1" + _buildargs="$_buildargs $_1" + if [ -d $INST/alembic ]; then + _1="-D ALEMBIC_ROOT_DIR=$INST/alembic" + PRINT " $_1" + _buildargs="$_buildargs $_1" + fi + fi + if [ "$NO_SYSTEM_GLEW" = true ]; then _1="-D WITH_SYSTEM_GLEW=OFF" PRINT " $_1" diff --git a/build_files/cmake/Modules/FindAlembic.cmake b/build_files/cmake/Modules/FindAlembic.cmake new file mode 100644 index 00000000000..1f61b5ef462 --- /dev/null +++ b/build_files/cmake/Modules/FindAlembic.cmake @@ -0,0 +1,70 @@ +# - Find Alembic library +# Find the native Alembic includes and libraries +# This module defines +# ALEMBIC_INCLUDE_DIRS, where to find Alembic headers, Set when +# ALEMBIC_INCLUDE_DIR is found. +# ALEMBIC_LIBRARIES, libraries to link against to use Alembic. +# ALEMBIC_ROOT_DIR, The base directory to search for Alembic. +# This can also be an environment variable. +# ALEMBIC_FOUND, If false, do not try to use Alembic. +# + +#============================================================================= +# Copyright 2016 Blender Foundation. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +# If ALEMBIC_ROOT_DIR was defined in the environment, use it. +IF(NOT ALEMBIC_ROOT_DIR AND NOT $ENV{ALEMBIC_ROOT_DIR} STREQUAL "") + SET(ALEMBIC_ROOT_DIR $ENV{ALEMBIC_ROOT_DIR}) +ENDIF() + +SET(_alembic_SEARCH_DIRS + ${ALEMBIC_ROOT_DIR} + /usr/local + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt/lib/alembic +) + +FIND_PATH(ALEMBIC_INCLUDE_DIR + NAMES + Alembic/Abc/All.h + HINTS + ${_alembic_SEARCH_DIRS} + PATH_SUFFIXES + include +) + +FIND_LIBRARY(ALEMBIC_LIBRARY + NAMES + Alembic + HINTS + ${_alembic_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib lib/static +) + +# handle the QUIETLY and REQUIRED arguments and set ALEMBIC_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALEMBIC DEFAULT_MSG ALEMBIC_LIBRARY ALEMBIC_INCLUDE_DIR) + +IF(ALEMBIC_FOUND) + SET(ALEMBIC_LIBRARIES ${ALEMBIC_LIBRARY}) + SET(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR}) +ENDIF(ALEMBIC_FOUND) + +MARK_AS_ADVANCED( + ALEMBIC_INCLUDE_DIR + ALEMBIC_LIBRARY +) + +UNSET(_alembic_SEARCH_DIRS) diff --git a/build_files/cmake/Modules/FindHDF5.cmake b/build_files/cmake/Modules/FindHDF5.cmake new file mode 100644 index 00000000000..56ceda8fb5e --- /dev/null +++ b/build_files/cmake/Modules/FindHDF5.cmake @@ -0,0 +1,69 @@ +# - Find HDF5 library +# Find the native HDF5 includes and libraries +# This module defines +# HDF5_INCLUDE_DIRS, where to find hdf5.h, Set when HDF5_INCLUDE_DIR is found. +# HDF5_LIBRARIES, libraries to link against to use HDF5. +# HDF5_ROOT_DIR, The base directory to search for HDF5. +# This can also be an environment variable. +# HDF5_FOUND, If false, do not try to use HDF5. +# + +#============================================================================= +# Copyright 2016 Blender Foundation. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +# If HDF5_ROOT_DIR was defined in the environment, use it. +IF(NOT HDF5_ROOT_DIR AND NOT $ENV{HDF5_ROOT_DIR} STREQUAL "") + SET(HDF5_ROOT_DIR $ENV{HDF5_ROOT_DIR}) +ENDIF() + +SET(_hdf5_SEARCH_DIRS + ${HDF5_ROOT_DIR} + /usr/local + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt/lib/hdf5 +) + +FIND_LIBRARY(HDF5_LIBRARY + NAMES + hdf5 + HINTS + ${_hdf5_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib +) + +FIND_PATH(HDF5_INCLUDE_DIR + NAMES + hdf5.h + HINTS + ${_hdf5_SEARCH_DIRS} + PATH_SUFFIXES + include +) + +# handle the QUIETLY and REQUIRED arguments and set HDF5_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(HDF5 DEFAULT_MSG HDF5_LIBRARY HDF5_INCLUDE_DIR) + +IF(HDF5_FOUND) + SET(HDF5_LIBRARIES ${HDF5_LIBRARY}) + SET(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR}) +ENDIF(HDF5_FOUND) + +MARK_AS_ADVANCED( + HDF5_INCLUDE_DIR + HDF5_LIBRARY +) + +UNSET(_hdf5_SEARCH_DIRS) diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index b50b42416fb..634d4f431d4 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -4,6 +4,7 @@ # cmake -C../blender/build_files/cmake/config/blender_full.cmake ../blender # +set(WITH_ALEMBIC ON CACHE BOOL "" FORCE) set(WITH_BUILDINFO ON CACHE BOOL "" FORCE) set(WITH_BULLET ON CACHE BOOL "" FORCE) set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake index 3c53ee7ae23..46b7d48b494 100644 --- a/build_files/cmake/config/blender_lite.cmake +++ b/build_files/cmake/config/blender_lite.cmake @@ -8,6 +8,7 @@ set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE) set(WITH_SYSTEM_GLEW ON CACHE BOOL "" FORCE) +set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE) set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE) set(WITH_BULLET OFF CACHE BOOL "" FORCE) set(WITH_CODEC_AVI OFF CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/bpy_module.cmake b/build_files/cmake/config/bpy_module.cmake index 41140151f04..854d6e49370 100644 --- a/build_files/cmake/config/bpy_module.cmake +++ b/build_files/cmake/config/bpy_module.cmake @@ -32,3 +32,4 @@ set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE) set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE) set(WITH_BULLET OFF CACHE BOOL "" FORCE) set(WITH_OPENVDB OFF CACHE BOOL "" FORCE) +set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index f57a6952164..fabb35c539e 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -333,6 +333,11 @@ function(SETUP_LIBDIRS) link_directories(${LLVM_LIBPATH}) endif() + if(WITH_ALEMBIC) + link_directories(${ALEMBIC_LIBPATH}) + link_directories(${HDF5_LIBPATH}) + endif() + if(WIN32 AND NOT UNIX) link_directories(${PTHREADS_LIBPATH}) endif() @@ -354,7 +359,6 @@ function(setup_liblinks target_link_libraries( ${target} ${PNG_LIBRARIES} - ${ZLIB_LIBRARIES} ${FREETYPE_LIBRARY} ) @@ -434,6 +438,9 @@ function(setup_liblinks endif() endif() target_link_libraries(${target} ${JPEG_LIBRARIES}) + if(WITH_ALEMBIC) + target_link_libraries(${target} ${ALEMBIC_LIBRARIES} ${HDF5_LIBRARIES}) + endif() if(WITH_IMAGE_OPENEXR) target_link_libraries(${target} ${OPENEXR_LIBRARIES}) endif() @@ -502,6 +509,11 @@ function(setup_liblinks endif() endif() + target_link_libraries( + ${target} + ${ZLIB_LIBRARIES} + ) + #system libraries with no dependencies such as platform link libs or opengl should go last target_link_libraries(${target} ${BLENDER_GL_LIBRARIES}) @@ -607,6 +619,7 @@ function(SETUP_BLENDER_SORTED_LIBS) bf_imbuf_openimageio bf_imbuf_dds bf_collada + bf_alembic bf_intern_elbeem bf_intern_memutil bf_intern_guardedalloc @@ -1565,3 +1578,26 @@ macro(openmp_delayload endif(WITH_OPENMP) endif(MSVC) endmacro() + +MACRO(WINDOWS_SIGN_TARGET target) + if (WITH_WINDOWS_CODESIGN) + if (!SIGNTOOL_EXE) + error("Codesigning is enabled, but signtool is not found") + else() + if (WINDOWS_CODESIGN_PFX_PASSWORD) + set(CODESIGNPASSWORD /p ${WINDOWS_CODESIGN_PFX_PASSWORD}) + else() + if ($ENV{PFXPASSWORD}) + set(CODESIGNPASSWORD /p $ENV{PFXPASSWORD}) + else() + message( FATAL_ERROR "WITH_WINDOWS_CODESIGN is on but WINDOWS_CODESIGN_PFX_PASSWORD not set, and environment variable PFXPASSWORD not found, unable to sign code.") + endif() + endif() + add_custom_command(TARGET ${target} + POST_BUILD + COMMAND ${SIGNTOOL_EXE} sign /f ${WINDOWS_CODESIGN_PFX} ${CODESIGNPASSWORD} $<TARGET_FILE:${target}> + VERBATIM + ) + endif() + endif() +ENDMACRO()
\ No newline at end of file diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake index afdbc644b4e..bc1d64f7494 100644 --- a/build_files/cmake/packaging.cmake +++ b/build_files/cmake/packaging.cmake @@ -38,7 +38,17 @@ unset(MY_WC_HASH) # Force Package Name execute_process(COMMAND date "+%Y%m%d" OUTPUT_VARIABLE CPACK_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) -set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LOWER}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-git${CPACK_DATE}.${BUILD_REV}-${CMAKE_SYSTEM_PROCESSOR}) +if (MSVC) + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(PACKAGE_ARCH windows64) + else() + set(PACKAGE_ARCH windows32) + endif() +else(MSVC) + set(PACKAGE_ARCH ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LOWER}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-git${CPACK_DATE}.${BUILD_REV}-${PACKAGE_ARCH}) if(CMAKE_SYSTEM_NAME MATCHES "Linux") # RPM packages diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake new file mode 100644 index 00000000000..b28b74804d3 --- /dev/null +++ b/build_files/cmake/platform/platform_apple.cmake @@ -0,0 +1,430 @@ +# ***** 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) 2016, Blender Foundation +# All rights reserved. +# +# Contributor(s): Sergey Sharybin. +# +# ***** END GPL LICENSE BLOCK ***** + +# Libraries configuration for Apple. + +if(NOT DEFINED LIBDIR) + set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-9.x.universal) +else() + message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") +endif() +if(NOT EXISTS "${LIBDIR}/") + message(FATAL_ERROR "Mac OSX requires pre-compiled libs at: '${LIBDIR}'") +endif() + +if(WITH_OPENAL) + find_package(OpenAL) + if(OPENAL_FOUND) + set(WITH_OPENAL ON) + set(OPENAL_INCLUDE_DIR "${LIBDIR}/openal/include") + else() + set(WITH_OPENAL OFF) + endif() +endif() + +if(WITH_ALEMBIC) + set(ALEMBIC ${LIBDIR}/alembic) + set(ALEMBIC_INCLUDE_DIR ${ALEMBIC}/include) + set(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR}) + set(ALEMBIC_LIBPATH ${ALEMBIC}/lib) + set(ALEMBIC_LIBRARIES Alembic) +endif() + +if(WITH_OPENSUBDIV) + set(OPENSUBDIV ${LIBDIR}/opensubdiv) + set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib) + find_library(OSL_LIB_UTIL NAMES osdutil PATHS ${OPENSUBDIV_LIBPATH}) + find_library(OSL_LIB_CPU NAMES osdCPU PATHS ${OPENSUBDIV_LIBPATH}) + find_library(OSL_LIB_GPU NAMES osdGPU PATHS ${OPENSUBDIV_LIBPATH}) + set(OPENSUBDIV_INCLUDE_DIR ${OPENSUBDIV}/include) + set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR}) + list(APPEND OPENSUBDIV_LIBRARIES ${OSL_LIB_UTIL} ${OSL_LIB_CPU} ${OSL_LIB_GPU}) +endif() + +if(WITH_JACK) + find_library(JACK_FRAMEWORK + NAMES jackmp + ) + set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) + if(NOT JACK_FRAMEWORK) + set(WITH_JACK OFF) + endif() +endif() + +if(WITH_CODEC_SNDFILE) + set(SNDFILE ${LIBDIR}/sndfile) + set(SNDFILE_INCLUDE_DIRS ${SNDFILE}/include) + set(SNDFILE_LIBRARIES sndfile FLAC ogg vorbis vorbisenc) + set(SNDFILE_LIBPATH ${SNDFILE}/lib ${FFMPEG}/lib) # TODO, deprecate +endif() + +if(WITH_PYTHON) + # we use precompiled libraries for py 3.5 and up by default + set(PYTHON_VERSION 3.5) + if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK) + # normally cached but not since we include them with blender + set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}m") + set(PYTHON_EXECUTABLE "${LIBDIR}/python/bin/python${PYTHON_VERSION}m") + set(PYTHON_LIBRARY python${PYTHON_VERSION}m) + set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}") + # set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled + else() + # module must be compiled against Python framework + set(_py_framework "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}") + + set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}m") + set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}m") + set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}m") + #set(PYTHON_LIBRARY python${PYTHON_VERSION}) + #set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled + + unset(_py_framework) + endif() + + # uncached vars + set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") + set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") + + if(NOT EXISTS "${PYTHON_EXECUTABLE}") + message(FATAL_ERROR "Python executable missing: ${PYTHON_EXECUTABLE}") + endif() +endif() + +if(WITH_FFTW3) + set(FFTW3 ${LIBDIR}/fftw3) + set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) + set(FFTW3_LIBRARIES fftw3) + set(FFTW3_LIBPATH ${FFTW3}/lib) +endif() + +set(PNG_LIBRARIES png) +set(JPEG_LIBRARIES jpeg) + +set(ZLIB /usr) +set(ZLIB_INCLUDE_DIRS "${ZLIB}/include") +set(ZLIB_LIBRARIES z bz2) + +set(FREETYPE ${LIBDIR}/freetype) +set(FREETYPE_INCLUDE_DIRS ${FREETYPE}/include ${FREETYPE}/include/freetype2) +set(FREETYPE_LIBPATH ${FREETYPE}/lib) +set(FREETYPE_LIBRARY freetype) + +if(WITH_IMAGE_OPENEXR) + set(OPENEXR ${LIBDIR}/openexr) + set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) + set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR}/include/OpenEXR) + set(OPENEXR_LIBRARIES Iex Half IlmImf Imath IlmThread) + set(OPENEXR_LIBPATH ${OPENEXR}/lib) +endif() + +if(WITH_CODEC_FFMPEG) + set(FFMPEG ${LIBDIR}/ffmpeg) + set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include) + set(FFMPEG_LIBRARIES + avcodec avdevice avformat avutil + mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg + ) + set(FFMPEG_LIBPATH ${FFMPEG}/lib) +endif() + +find_library(SYSTEMSTUBS_LIBRARY + NAMES + SystemStubs + PATHS +) +mark_as_advanced(SYSTEMSTUBS_LIBRARY) +if(SYSTEMSTUBS_LIBRARY) + list(APPEND PLATFORM_LINKLIBS SystemStubs) +endif() + +set(PLATFORM_CFLAGS "-pipe -funsigned-char") +set(PLATFORM_LINKFLAGS + "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -framework CoreAudio" +) +if(WITH_CODEC_QUICKTIME) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QTKit") + if(CMAKE_OSX_ARCHITECTURES MATCHES i386) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime") + # libSDL still needs 32bit carbon quicktime + endif() +endif() + +if(WITH_CXX11) + list(APPEND PLATFORM_LINKLIBS c++) +else() + list(APPEND PLATFORM_LINKLIBS stdc++) +endif() + +if(WITH_JACK) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -F/Library/Frameworks -weak_framework jackmp") +endif() + +if(WITH_PYTHON_MODULE OR WITH_PYTHON_FRAMEWORK) + # force cmake to link right framework + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/Python") +endif() + +if(WITH_OPENCOLLADA) + set(OPENCOLLADA ${LIBDIR}/opencollada) + + set(OPENCOLLADA_INCLUDE_DIRS + ${LIBDIR}/opencollada/include/COLLADAStreamWriter + ${LIBDIR}/opencollada/include/COLLADABaseUtils + ${LIBDIR}/opencollada/include/COLLADAFramework + ${LIBDIR}/opencollada/include/COLLADASaxFrameworkLoader + ${LIBDIR}/opencollada/include/GeneratedSaxParser + ) + + set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib) + set(OPENCOLLADA_LIBRARIES + OpenCOLLADASaxFrameworkLoader + -lOpenCOLLADAFramework + -lOpenCOLLADABaseUtils + -lOpenCOLLADAStreamWriter + -lMathMLSolver + -lGeneratedSaxParser + -lxml2 -lbuffer -lftoa + ) + # Use UTF functions from collada if LLVM is not enabled + if(NOT WITH_LLVM) + list(APPEND OPENCOLLADA_LIBRARIES -lUTF) + endif() + # pcre is bundled with openCollada + #set(PCRE ${LIBDIR}/pcre) + #set(PCRE_LIBPATH ${PCRE}/lib) + set(PCRE_LIBRARIES pcre) + #libxml2 is used + #set(EXPAT ${LIBDIR}/expat) + #set(EXPAT_LIBPATH ${EXPAT}/lib) + set(EXPAT_LIB) +endif() + +if(WITH_SDL) + set(SDL ${LIBDIR}/sdl) + set(SDL_INCLUDE_DIR ${SDL}/include) + set(SDL_LIBRARY SDL2) + set(SDL_LIBPATH ${SDL}/lib) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lazy_framework ForceFeedback") +endif() + +set(PNG "${LIBDIR}/png") +set(PNG_INCLUDE_DIRS "${PNG}/include") +set(PNG_LIBPATH ${PNG}/lib) + +set(JPEG "${LIBDIR}/jpeg") +set(JPEG_INCLUDE_DIR "${JPEG}/include") +set(JPEG_LIBPATH ${JPEG}/lib) + +if(WITH_IMAGE_TIFF) + set(TIFF ${LIBDIR}/tiff) + set(TIFF_INCLUDE_DIR ${TIFF}/include) + set(TIFF_LIBRARY tiff) + set(TIFF_LIBPATH ${TIFF}/lib) +endif() + +if(WITH_BOOST) + set(BOOST ${LIBDIR}/boost) + set(BOOST_INCLUDE_DIR ${BOOST}/include) + set(BOOST_LIBRARIES + boost_date_time-mt + boost_filesystem-mt + boost_regex-mt + boost_system-mt + boost_thread-mt + boost_wave-mt + ) + if(WITH_INTERNATIONAL) + list(APPEND BOOST_LIBRARIES boost_locale-mt) + endif() + if(WITH_CYCLES_NETWORK) + list(APPEND BOOST_LIBRARIES boost_serialization-mt) + endif() + if(WITH_OPENVDB) + list(APPEND BOOST_LIBRARIES boost_iostreams-mt) + endif() + set(BOOST_LIBPATH ${BOOST}/lib) + set(BOOST_DEFINITIONS) +endif() + +if(WITH_INTERNATIONAL OR WITH_CODEC_FFMPEG) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale and ffmpeg needs it ! +endif() + +if(WITH_OPENIMAGEIO) + set(OPENIMAGEIO ${LIBDIR}/openimageio) + set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) + set(OPENIMAGEIO_LIBRARIES + ${OPENIMAGEIO}/lib/libOpenImageIO.a + ${PNG_LIBRARIES} + ${JPEG_LIBRARIES} + ${TIFF_LIBRARY} + ${OPENEXR_LIBRARIES} + ${ZLIB_LIBRARIES} + ) + set(OPENIMAGEIO_LIBPATH + ${OPENIMAGEIO}/lib + ${JPEG_LIBPATH} + ${PNG_LIBPATH} + ${TIFF_LIBPATH} + ${OPENEXR_LIBPATH} + ${ZLIB_LIBPATH} + ) + set(OPENIMAGEIO_DEFINITIONS "-DOIIO_STATIC_BUILD") + set(OPENIMAGEIO_IDIFF "${LIBDIR}/openimageio/bin/idiff") +endif() + +if(WITH_OPENCOLORIO) + set(OPENCOLORIO ${LIBDIR}/opencolorio) + set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) + set(OPENCOLORIO_LIBRARIES OpenColorIO tinyxml yaml-cpp) + set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib) +endif() + +if(WITH_OPENVDB) + set(OPENVDB ${LIBDIR}/openvdb) + set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include) + set(TBB_INCLUDE_DIRS ${LIBDIR}/tbb/include) + set(TBB_LIBRARIES ${LIBDIR}/tbb/lib/libtbb.a) + set(OPENVDB_LIBRARIES openvdb blosc ${TBB_LIBRARIES}) + set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib) + set(OPENVDB_DEFINITIONS) +endif() + +if(WITH_LLVM) + set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + set(LLVM_VERSION "3.4" CACHE STRING "Version of LLVM to use") + if(EXISTS "${LLVM_ROOT_DIR}/bin/llvm-config") + set(LLVM_CONFIG "${LLVM_ROOT_DIR}/bin/llvm-config") + else() + set(LLVM_CONFIG llvm-config) + endif() + execute_process(COMMAND ${LLVM_CONFIG} --version + OUTPUT_VARIABLE LLVM_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${LLVM_CONFIG} --prefix + OUTPUT_VARIABLE LLVM_ROOT_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${LLVM_CONFIG} --libdir + OUTPUT_VARIABLE LLVM_LIBPATH + OUTPUT_STRIP_TRAILING_WHITESPACE) + find_library(LLVM_LIBRARY + NAMES LLVMAnalysis # first of a whole bunch of libs to get + PATHS ${LLVM_LIBPATH}) + + if(LLVM_LIBRARY AND LLVM_ROOT_DIR AND LLVM_LIBPATH) + if(LLVM_STATIC) + # if static LLVM libraries were requested, use llvm-config to generate + # the list of what libraries we need, and substitute that in the right + # way for LLVM_LIBRARY. + execute_process(COMMAND ${LLVM_CONFIG} --libfiles + OUTPUT_VARIABLE LLVM_LIBRARY + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY}) + else() + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lLLVM-3.4") + endif() + else() + message(FATAL_ERROR "LLVM not found.") + endif() +endif() + +if(WITH_CYCLES_OSL) + set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") + + find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) + # WARNING! depends on correct order of OSL libs linking + list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) + find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) + find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) + + if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER) + set(OSL_FOUND TRUE) + else() + message(STATUS "OSL not found") + set(WITH_CYCLES_OSL OFF) + endif() +endif() + +if(WITH_OPENMP) + execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE COMPILER_VENDOR) + string(SUBSTRING "${COMPILER_VENDOR}" 0 5 VENDOR_NAME) # truncate output + if(${VENDOR_NAME} MATCHES "Apple") # Apple does not support OpenMP reliable with gcc and not with clang + set(WITH_OPENMP OFF) + else() # vanilla gcc or clang_omp support OpenMP + message(STATUS "Using special OpenMP enabled compiler !") # letting find_package(OpenMP) module work for gcc + if(CMAKE_C_COMPILER_ID MATCHES "Clang") # clang-omp in darwin libs + set(OPENMP_FOUND ON) + set(OpenMP_C_FLAGS "-fopenmp" CACHE STRING "C compiler flags for OpenMP parallization" FORCE) + set(OpenMP_CXX_FLAGS "-fopenmp" CACHE STRING "C++ compiler flags for OpenMP parallization" FORCE) + include_directories(${LIBDIR}/openmp/include) + link_directories(${LIBDIR}/openmp/lib) + # This is a workaround for our helperbinaries ( datatoc, masgfmt, ... ), + # They are linked also to omp lib, so we need it in builddir for runtime exexcution, + # TODO: remove all unneeded dependencies from these + + # for intermediate binaries, in respect to lib ID + execute_process( + COMMAND ditto -arch ${CMAKE_OSX_ARCHITECTURES} + ${LIBDIR}/openmp/lib/libiomp5.dylib + ${CMAKE_BINARY_DIR}/Resources/lib/libiomp5.dylib) + endif() + endif() +endif() + +set(EXETYPE MACOSX_BUNDLE) + +set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g") +set(CMAKE_CXX_FLAGS_DEBUG "-fno-strict-aliasing -g") +if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64" OR CMAKE_OSX_ARCHITECTURES MATCHES "i386") + set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3") + set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3") + if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller") + endif() +else() + set(CMAKE_C_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing") + set(CMAKE_CXX_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing") +endif() + +if(${XCODE_VERSION} VERSION_EQUAL 5 OR ${XCODE_VERSION} VERSION_GREATER 5) + # Xcode 5 is always using CLANG, which has too low template depth of 128 for libmv + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=1024") +endif() +# Get rid of eventually clashes, we export some symbols explicite as local +set(PLATFORM_LINKFLAGS + "${PLATFORM_LINKFLAGS} -Xlinker -unexported_symbols_list -Xlinker ${CMAKE_SOURCE_DIR}/source/creator/osx_locals.map" +) + +if(WITH_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -stdlib=libc++") +endif() + +# Suppress ranlib "has no symbols" warnings (workaround for T48250) +set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>") +set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>") +set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>") +set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>") diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake new file mode 100644 index 00000000000..0e0dc382ca3 --- /dev/null +++ b/build_files/cmake/platform/platform_unix.cmake @@ -0,0 +1,425 @@ +# ***** 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) 2016, Blender Foundation +# All rights reserved. +# +# Contributor(s): Sergey Sharybin. +# +# ***** END GPL LICENSE BLOCK ***** + +# Libraries configuration for any *nix system including Linux and Unix. + +macro(find_package_wrapper) + if(WITH_STATIC_LIBS) + find_package_static(${ARGV}) + else() + find_package(${ARGV}) + endif() +endmacro() + +find_package_wrapper(JPEG REQUIRED) +find_package_wrapper(PNG REQUIRED) +find_package_wrapper(ZLIB REQUIRED) +find_package_wrapper(Freetype REQUIRED) + +if(WITH_LZO AND WITH_SYSTEM_LZO) + find_package_wrapper(LZO) + if(NOT LZO_FOUND) + message(FATAL_ERROR "Failed finding system LZO version!") + endif() +endif() + +if(WITH_SYSTEM_EIGEN3) + find_package_wrapper(Eigen3) + if(NOT EIGEN3_FOUND) + message(FATAL_ERROR "Failed finding system Eigen3 version!") + endif() +endif() +# else values are set below for all platforms + +if(WITH_PYTHON) + # No way to set py35, remove for now. + # find_package(PythonLibs) + + # Use our own instead, since without py is such a rare case, + # require this package + # XXX Linking errors with debian static python :/ +# find_package_wrapper(PythonLibsUnix REQUIRED) + find_package(PythonLibsUnix REQUIRED) +endif() + +if(WITH_IMAGE_OPENEXR) + find_package_wrapper(OpenEXR) # our own module + if(NOT OPENEXR_FOUND) + set(WITH_IMAGE_OPENEXR OFF) + endif() +endif() + +if(WITH_IMAGE_OPENJPEG) + find_package_wrapper(OpenJPEG) + if(NOT OPENJPEG_FOUND) + set(WITH_IMAGE_OPENJPEG OFF) + endif() +endif() + +if(WITH_IMAGE_TIFF) + # XXX Linking errors with debian static tiff :/ +# find_package_wrapper(TIFF) + find_package(TIFF) + if(NOT TIFF_FOUND) + set(WITH_IMAGE_TIFF OFF) + endif() +endif() + +# Audio IO +if(WITH_SYSTEM_AUDASPACE) + find_package_wrapper(Audaspace) + if(NOT AUDASPACE_FOUND OR NOT AUDASPACE_C_FOUND) + message(FATAL_ERROR "Audaspace external library not found!") + endif() +endif() + +if(WITH_OPENAL) + find_package_wrapper(OpenAL) + if(NOT OPENAL_FOUND) + set(WITH_OPENAL OFF) + endif() +endif() + +if(WITH_SDL) + if(WITH_SDL_DYNLOAD) + set(SDL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extern/sdlew/include/SDL2") + set(SDL_LIBRARY) + else() + find_package_wrapper(SDL2) + if(SDL2_FOUND) + # Use same names for both versions of SDL until we move to 2.x. + set(SDL_INCLUDE_DIR "${SDL2_INCLUDE_DIR}") + set(SDL_LIBRARY "${SDL2_LIBRARY}") + set(SDL_FOUND "${SDL2_FOUND}") + else() + find_package_wrapper(SDL) + endif() + mark_as_advanced( + SDL_INCLUDE_DIR + SDL_LIBRARY + ) + # unset(SDLMAIN_LIBRARY CACHE) + if(NOT SDL_FOUND) + set(WITH_SDL OFF) + endif() + endif() +endif() + +if(WITH_JACK) + find_package_wrapper(Jack) + if(NOT JACK_FOUND) + set(WITH_JACK OFF) + endif() +endif() + +# Codecs +if(WITH_CODEC_SNDFILE) + find_package_wrapper(SndFile) + if(NOT SNDFILE_FOUND) + set(WITH_CODEC_SNDFILE OFF) + endif() +endif() + +if(WITH_CODEC_FFMPEG) + set(FFMPEG /usr CACHE PATH "FFMPEG Directory") + set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries") + + mark_as_advanced(FFMPEG) + + # lame, but until we have proper find module for ffmpeg + set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include) + if(EXISTS "${FFMPEG}/include/ffmpeg/") + list(APPEND FFMPEG_INCLUDE_DIRS "${FFMPEG}/include/ffmpeg") + endif() + # end lameness + + mark_as_advanced(FFMPEG_LIBRARIES) + set(FFMPEG_LIBPATH ${FFMPEG}/lib) +endif() + +if(WITH_FFTW3) + find_package_wrapper(Fftw3) + if(NOT FFTW3_FOUND) + set(WITH_FFTW3 OFF) + endif() +endif() + +if(WITH_OPENCOLLADA) + find_package_wrapper(OpenCOLLADA) + if(OPENCOLLADA_FOUND) + find_package_wrapper(XML2) + find_package_wrapper(PCRE) + else() + set(WITH_OPENCOLLADA OFF) + endif() +endif() + +if(WITH_MEM_JEMALLOC) + find_package_wrapper(JeMalloc) + if(NOT JEMALLOC_FOUND) + set(WITH_MEM_JEMALLOC OFF) + endif() +endif() + +if(WITH_INPUT_NDOF) + find_package_wrapper(Spacenav) + if(SPACENAV_FOUND) + # use generic names within blenders buildsystem. + set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS}) + set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES}) + else() + set(WITH_INPUT_NDOF OFF) + endif() +endif() + +if(WITH_CYCLES_OSL) + set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") + if(NOT OSL_ROOT) + set(OSL_ROOT ${CYCLES_OSL}) + endif() + find_package_wrapper(OpenShadingLanguage) + if(OSL_FOUND) + if(${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6") + # Note: --whole-archive is needed to force loading of all symbols in liboslexec, + # otherwise LLVM is missing the osl_allocate_closure_component function + set(OSL_LIBRARIES + ${OSL_OSLCOMP_LIBRARY} + -Wl,--whole-archive ${OSL_OSLEXEC_LIBRARY} + -Wl,--no-whole-archive ${OSL_OSLQUERY_LIBRARY} + ) + endif() + else() + message(STATUS "OSL not found, disabling it from Cycles") + set(WITH_CYCLES_OSL OFF) + endif() +endif() + +if(WITH_OPENVDB) + find_package_wrapper(OpenVDB) + find_package_wrapper(TBB) + if(NOT OPENVDB_FOUND OR NOT TBB_FOUND) + set(WITH_OPENVDB OFF) + set(WITH_OPENVDB_BLOSC OFF) + message(STATUS "OpenVDB not found, disabling it") + endif() +endif() + +if(WITH_ALEMBIC) + find_package_wrapper(Alembic) + + if(WITH_ALEMBIC_HDF5) + set(HDF5_ROOT_DIR ${LIBDIR}/hdf5) + find_package_wrapper(HDF5) + endif() + + if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND)) + set(WITH_ALEMBIC OFF) + set(WITH_ALEMBIC_HDF5 OFF) + endif() +endif() + +if(WITH_BOOST) + # uses in build instructions to override include and library variables + if(NOT BOOST_CUSTOM) + if(WITH_STATIC_LIBS) + set(Boost_USE_STATIC_LIBS ON) + endif() + set(Boost_USE_MULTITHREADED ON) + set(__boost_packages filesystem regex system thread date_time) + if(WITH_CYCLES_OSL) + if(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6")) + list(APPEND __boost_packages wave) + else() + endif() + endif() + if(WITH_INTERNATIONAL) + list(APPEND __boost_packages locale) + endif() + if(WITH_CYCLES_NETWORK) + list(APPEND __boost_packages serialization) + endif() + if(WITH_OPENVDB) + list(APPEND __boost_packages iostreams) + endif() + find_package(Boost 1.48 COMPONENTS ${__boost_packages}) + if(NOT Boost_FOUND) + # try to find non-multithreaded if -mt not found, this flag + # doesn't matter for us, it has nothing to do with thread + # safety, but keep it to not disturb build setups + set(Boost_USE_MULTITHREADED OFF) + find_package(Boost 1.48 COMPONENTS ${__boost_packages}) + endif() + unset(__boost_packages) + if(Boost_USE_STATIC_LIBS AND WITH_BOOST_ICU) + find_package(IcuLinux) + endif() + mark_as_advanced(Boost_DIR) # why doesnt boost do this? + endif() + + set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS}) + set(BOOST_LIBRARIES ${Boost_LIBRARIES}) + set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS}) + set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB") +endif() + +if(WITH_OPENIMAGEIO) + find_package_wrapper(OpenImageIO) + if(NOT OPENIMAGEIO_PUGIXML_FOUND AND WITH_CYCLES_STANDALONE) + find_package_wrapper(PugiXML) + else() + set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}") + set(PUGIXML_LIBRARIES "") + endif() + + set(OPENIMAGEIO_LIBRARIES + ${OPENIMAGEIO_LIBRARIES} + ${PNG_LIBRARIES} + ${JPEG_LIBRARIES} + ${ZLIB_LIBRARIES} + ${BOOST_LIBRARIES} + ) + set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere + set(OPENIMAGEIO_DEFINITIONS "") + + if(WITH_IMAGE_TIFF) + list(APPEND OPENIMAGEIO_LIBRARIES "${TIFF_LIBRARY}") + endif() + if(WITH_IMAGE_OPENEXR) + list(APPEND OPENIMAGEIO_LIBRARIES "${OPENEXR_LIBRARIES}") + endif() + + if(NOT OPENIMAGEIO_FOUND) + set(WITH_OPENIMAGEIO OFF) + message(STATUS "OpenImageIO not found, disabling WITH_CYCLES") + endif() +endif() + +if(WITH_OPENCOLORIO) + find_package_wrapper(OpenColorIO) + + set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES}) + set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere + set(OPENCOLORIO_DEFINITIONS) + + if(NOT OPENCOLORIO_FOUND) + set(WITH_OPENCOLORIO OFF) + message(STATUS "OpenColorIO not found") + endif() +endif() + +if(WITH_LLVM) + find_package_wrapper(LLVM) + + if(NOT LLVM_FOUND) + set(WITH_LLVM OFF) + message(STATUS "LLVM not found") + endif() +endif() + +if(WITH_LLVM OR WITH_SDL_DYNLOAD) + # Fix for conflict with Mesa llvmpipe + set(PLATFORM_LINKFLAGS + "${PLATFORM_LINKFLAGS} -Wl,--version-script='${CMAKE_SOURCE_DIR}/source/creator/blender.map'" + ) +endif() + +if(WITH_OPENSUBDIV) + find_package_wrapper(OpenSubdiv) + + set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES}) + set(OPENSUBDIV_LIBPATH) # TODO, remove and reference the absolute path everywhere + + if(NOT OPENSUBDIV_FOUND) + set(WITH_OPENSUBDIV OFF) + message(STATUS "OpenSubdiv not found") + endif() +endif() + +# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed +list(APPEND PLATFORM_LINKLIBS -lutil -lc -lm) + +find_package(Threads REQUIRED) +list(APPEND PLATFORM_LINKLIBS ${CMAKE_THREAD_LIBS_INIT}) +# used by other platforms +set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) + +if(CMAKE_DL_LIBS) + list(APPEND PLATFORM_LINKLIBS ${CMAKE_DL_LIBS}) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Linux") + if(NOT WITH_PYTHON_MODULE) + # binreloc is linux only + set(BINRELOC_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/binreloc/include) + set(WITH_BINRELOC ON) + endif() +endif() + +# lfs on glibc, all compilers should use +add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) + +# GNU Compiler +if(CMAKE_COMPILER_IS_GNUCC) + set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") + + # use ld.gold linker if available, could make optional + execute_process( + COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version + ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) + if("${LD_VERSION}" MATCHES "GNU gold") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") + else() + message(STATUS "GNU gold linker isn't available, using the default system linker.") + endif() + unset(LD_VERSION) + +# CLang is the same as GCC for now. +elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") + set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") +# Solaris CC +elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro") + set(PLATFORM_CFLAGS "-pipe -features=extensions -fPIC -D__FUNCTION__=__func__") + +# Intel C++ Compiler +elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") + # think these next two are broken + find_program(XIAR xiar) + if(XIAR) + set(CMAKE_AR "${XIAR}") + endif() + mark_as_advanced(XIAR) + + find_program(XILD xild) + if(XILD) + set(CMAKE_LINKER "${XILD}") + endif() + mark_as_advanced(XILD) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fp-model precise -prec_div -parallel") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fp-model precise -prec_div -parallel") + + # set(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -diag-enable sc3") + set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -static-intel") +endif() diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake new file mode 100644 index 00000000000..631973b758b --- /dev/null +++ b/build_files/cmake/platform/platform_win32.cmake @@ -0,0 +1,87 @@ +# ***** 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) 2016, Blender Foundation +# All rights reserved. +# +# Contributor(s): Sergey Sharybin. +# +# ***** END GPL LICENSE BLOCK ***** + +# Libraries configuration for Windows. + +add_definitions(-DWIN32) + +if(MSVC) + include(platform_win32_msvc) +elseif(CMAKE_COMPILER_IS_GNUCC) + include(platform_win32_mingw) +endif() + +# Things common to both mingw and MSVC should go here + +set(WINTAB_INC ${LIBDIR}/wintab/include) + +if(WITH_OPENAL) + set(OPENAL ${LIBDIR}/openal) + set(OPENALDIR ${LIBDIR}/openal) + set(OPENAL_INCLUDE_DIR ${OPENAL}/include) + if(MSVC) + set(OPENAL_LIBRARY openal32) + else() + set(OPENAL_LIBRARY wrap_oal) + endif() + set(OPENAL_LIBPATH ${OPENAL}/lib) +endif() + +if(WITH_CODEC_SNDFILE) + set(SNDFILE ${LIBDIR}/sndfile) + set(SNDFILE_INCLUDE_DIRS ${SNDFILE}/include) + set(SNDFILE_LIBRARIES libsndfile-1) + set(SNDFILE_LIBPATH ${SNDFILE}/lib) # TODO, deprecate +endif() + +if(WITH_RAYOPTIMIZATION AND SUPPORT_SSE_BUILD) + add_definitions(-D__SSE__ -D__MMX__) +endif() + +if(WITH_CYCLES_OSL) + set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") + + 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) + find_library(OSL_LIB_EXEC_DEBUG NAMES oslexec_d PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib) + list(APPEND OSL_LIBRARIES + optimized ${OSL_LIB_COMP} + optimized ${OSL_LIB_EXEC} + optimized ${OSL_LIB_QUERY} + debug ${OSL_LIB_EXEC_DEBUG} + debug ${OSL_LIB_COMP_DEBUG} + debug ${OSL_LIB_QUERY_DEBUG} + ) + find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) + find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) + + if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER) + set(OSL_FOUND TRUE) + else() + message(STATUS "OSL not found") + set(WITH_CYCLES_OSL OFF) + endif() +endif() diff --git a/build_files/cmake/platform/platform_win32_mingw.cmake b/build_files/cmake/platform/platform_win32_mingw.cmake new file mode 100644 index 00000000000..216568bd069 --- /dev/null +++ b/build_files/cmake/platform/platform_win32_mingw.cmake @@ -0,0 +1,302 @@ +# ***** 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) 2016, Blender Foundation +# All rights reserved. +# +# Contributor(s): Sergey Sharybin. +# +# ***** END GPL LICENSE BLOCK ***** + +# Libraries configuration for Windows when compiling with MinGW. + +# keep GCC specific stuff here +include(CheckCSourceCompiles) +# Setup 64bit and 64bit windows systems +CHECK_C_SOURCE_COMPILES(" + #ifndef __MINGW64__ + #error + #endif + int main(void) { return 0; } + " + WITH_MINGW64 +) + +if(NOT DEFINED LIBDIR) + if(WITH_MINGW64) + message(STATUS "Compiling for 64 bit with MinGW-w64.") + set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64) + else() + message(STATUS "Compiling for 32 bit with MinGW-w32.") + set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32) + + if(WITH_RAYOPTIMIZATION) + message(WARNING "MinGW-w32 is known to be unstable with 'WITH_RAYOPTIMIZATION' option enabled.") + endif() + endif() +else() + message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") +endif() +if(NOT EXISTS "${LIBDIR}/") + message(FATAL_ERROR "Windows requires pre-compiled libs at: '${LIBDIR}'") +endif() + +list(APPEND PLATFORM_LINKLIBS + -lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 + -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi -ldbghelp +) + +if(WITH_INPUT_IME) + list(APPEND PLATFORM_LINKLIBS -limm32) +endif() + +set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing") + +if(WITH_MINGW64) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") + list(APPEND PLATFORM_LINKLIBS -lpthread) + + add_definitions(-DFREE_WINDOWS64 -DMS_WIN64) +endif() + +add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) + +add_definitions(-DFREE_WINDOWS) + +set(PNG "${LIBDIR}/png") +set(PNG_INCLUDE_DIRS "${PNG}/include") +set(PNG_LIBPATH ${PNG}/lib) # not cmake defined + +if(WITH_MINGW64) + set(JPEG_LIBRARIES jpeg) +else() + set(JPEG_LIBRARIES libjpeg) +endif() +set(PNG_LIBRARIES png) + +set(ZLIB ${LIBDIR}/zlib) +set(ZLIB_INCLUDE_DIRS ${ZLIB}/include) +set(ZLIB_LIBPATH ${ZLIB}/lib) +set(ZLIB_LIBRARIES z) + +set(JPEG "${LIBDIR}/jpeg") +set(JPEG_INCLUDE_DIR "${JPEG}/include") +set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined + +# comes with own pthread library +if(NOT WITH_MINGW64) + set(PTHREADS ${LIBDIR}/pthreads) + #set(PTHREADS_INCLUDE_DIRS ${PTHREADS}/include) + set(PTHREADS_LIBPATH ${PTHREADS}/lib) + set(PTHREADS_LIBRARIES pthreadGC2) +endif() + +set(FREETYPE ${LIBDIR}/freetype) +set(FREETYPE_INCLUDE_DIRS ${FREETYPE}/include ${FREETYPE}/include/freetype2) +set(FREETYPE_LIBPATH ${FREETYPE}/lib) +set(FREETYPE_LIBRARY freetype) + +if(WITH_FFTW3) + set(FFTW3 ${LIBDIR}/fftw3) + set(FFTW3_LIBRARIES fftw3) + set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) + set(FFTW3_LIBPATH ${FFTW3}/lib) +endif() + +if(WITH_OPENCOLLADA) + set(OPENCOLLADA ${LIBDIR}/opencollada) + set(OPENCOLLADA_INCLUDE_DIRS + ${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter + ${OPENCOLLADA}/include/opencollada/COLLADABaseUtils + ${OPENCOLLADA}/include/opencollada/COLLADAFramework + ${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader + ${OPENCOLLADA}/include/opencollada/GeneratedSaxParser + ) + set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib/opencollada) + set(OPENCOLLADA_LIBRARIES + OpenCOLLADAStreamWriter + OpenCOLLADASaxFrameworkLoader + OpenCOLLADAFramework + OpenCOLLADABaseUtils + GeneratedSaxParser + UTF MathMLSolver buffer ftoa xml + ) + set(PCRE_LIBRARIES pcre) +endif() + +if(WITH_CODEC_FFMPEG) + set(FFMPEG ${LIBDIR}/ffmpeg) + set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include) + if(WITH_MINGW64) + set(FFMPEG_LIBRARIES avcodec.dll avformat.dll avdevice.dll avutil.dll swscale.dll swresample.dll) + else() + set(FFMPEG_LIBRARIES avcodec-55 avformat-55 avdevice-55 avutil-52 swscale-2) + endif() + set(FFMPEG_LIBPATH ${FFMPEG}/lib) +endif() + +if(WITH_IMAGE_OPENEXR) + set(OPENEXR ${LIBDIR}/openexr) + set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) + set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR) + set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex) + set(OPENEXR_LIBPATH ${OPENEXR}/lib) +endif() + +if(WITH_IMAGE_TIFF) + set(TIFF ${LIBDIR}/tiff) + set(TIFF_LIBRARY tiff) + set(TIFF_INCLUDE_DIR ${TIFF}/include) + set(TIFF_LIBPATH ${TIFF}/lib) +endif() + +if(WITH_JACK) + set(JACK ${LIBDIR}/jack) + set(JACK_INCLUDE_DIRS ${JACK}/include/jack ${JACK}/include) + set(JACK_LIBRARIES jack) + set(JACK_LIBPATH ${JACK}/lib) + + # TODO, gives linking errors, force off + set(WITH_JACK OFF) +endif() + +if(WITH_PYTHON) + # normally cached but not since we include them with blender + set(PYTHON_VERSION 3.5) # CACHE STRING) + string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) + set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH) + set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}mw.lib") # CACHE FILEPATH) + unset(_PYTHON_VERSION_NO_DOTS) + + # uncached vars + set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") + set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") +endif() + +if(WITH_BOOST) + set(BOOST ${LIBDIR}/boost) + set(BOOST_INCLUDE_DIR ${BOOST}/include) + if(WITH_MINGW64) + set(BOOST_POSTFIX "mgw47-mt-s-1_49") + set(BOOST_DEBUG_POSTFIX "mgw47-mt-sd-1_49") + else() + set(BOOST_POSTFIX "mgw46-mt-s-1_49") + set(BOOST_DEBUG_POSTFIX "mgw46-mt-sd-1_49") + endif() + set(BOOST_LIBRARIES + optimized boost_date_time-${BOOST_POSTFIX} boost_filesystem-${BOOST_POSTFIX} + boost_regex-${BOOST_POSTFIX} + boost_system-${BOOST_POSTFIX} boost_thread-${BOOST_POSTFIX} + debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX} + boost_regex-${BOOST_DEBUG_POSTFIX} + boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX}) + if(WITH_INTERNATIONAL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized boost_locale-${BOOST_POSTFIX} + debug boost_locale-${BOOST_DEBUG_POSTFIX} + ) + endif() + if(WITH_CYCLES_OSL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized boost_wave-${BOOST_POSTFIX} + debug boost_wave-${BOOST_DEBUG_POSTFIX} + ) + endif() + set(BOOST_LIBPATH ${BOOST}/lib) + set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ") +endif() + +if(WITH_OPENIMAGEIO) + set(OPENIMAGEIO ${LIBDIR}/openimageio) + set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) + set(OPENIMAGEIO_LIBRARIES OpenImageIO) + set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib) + set(OPENIMAGEIO_DEFINITIONS "") + set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe") +endif() + +if(WITH_LLVM) + set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + set(LLVM_LIBPATH ${LLVM_ROOT_DIR}/lib) + # Explicitly set llvm lib order. + #---- WARNING ON GCC ORDER OF LIBS IS IMPORTANT, DO NOT CHANGE! --------- + set(LLVM_LIBRARY LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMAnalysis LLVMArchive + LLVMAsmParser LLVMAsmPrinter + LLVMBitReader LLVMBitWriter + LLVMDebugInfo LLVMExecutionEngine + LLVMInstCombine LLVMInstrumentation + LLVMInterpreter LLVMJIT + LLVMLinker LLVMMC + LLVMMCDisassembler LLVMMCJIT + LLVMMCParser LLVMObject + LLVMRuntimeDyld + LLVMSupport + LLVMTableGen LLVMTarget + LLVMTransformUtils LLVMVectorize + LLVMX86AsmParser LLVMX86AsmPrinter + LLVMX86CodeGen LLVMX86Desc + LLVMX86Disassembler LLVMX86Info + LLVMX86Utils LLVMipa + LLVMipo LLVMCore) + # imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc + list(APPEND PLATFORM_LINKLIBS -limagehlp) +endif() + +if(WITH_OPENCOLORIO) + set(OPENCOLORIO ${LIBDIR}/opencolorio) + set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) + set(OPENCOLORIO_LIBRARIES OpenColorIO) + set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib) + set(OPENCOLORIO_DEFINITIONS) +endif() + +if(WITH_SDL) + set(SDL ${LIBDIR}/sdl) + set(SDL_INCLUDE_DIR ${SDL}/include) + set(SDL_LIBRARY SDL) + set(SDL_LIBPATH ${SDL}/lib) +endif() + +if(WITH_OPENVDB) + set(OPENVDB ${LIBDIR}/openvdb) + set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include) + set(OPENVDB_LIBRARIES openvdb ${TBB_LIBRARIES}) + set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib) + set(OPENVDB_DEFINITIONS) +endif() + +if(WITH_ALEMBIC) + # TODO(sergey): For until someone drops by and compiles libraries for + # MinGW we allow users to compile their own Alembic library and use + # that via find_package(), + # + # Once precompiled libraries are there we'll use hardcoded locations. + find_package_wrapper(Alembic) + if(WITH_ALEMBIC_HDF5) + set(HDF5_ROOT_DIR ${LIBDIR}/hdf5) + find_package_wrapper(HDF5) + endif() + if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND)) + set(WITH_ALEMBIC OFF) + set(WITH_ALEMBIC_HDF5 OFF) + endif() +endif() + +set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152") + +## DISABLE - causes linking errors +## for re-distribution, so users dont need mingw installed +# set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -static-libgcc -static-libstdc++") diff --git a/build_files/cmake/platform/platform_win32_msvc.cmake b/build_files/cmake/platform/platform_win32_msvc.cmake new file mode 100644 index 00000000000..2772944214b --- /dev/null +++ b/build_files/cmake/platform/platform_win32_msvc.cmake @@ -0,0 +1,485 @@ +# ***** 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) 2016, Blender Foundation +# All rights reserved. +# +# Contributor(s): Sergey Sharybin. +# +# ***** END GPL LICENSE BLOCK ***** + +# Libraries configuration for Windows when compiling with MSVC. + +macro(warn_hardcoded_paths package_name + ) + if(WITH_WINDOWS_FIND_MODULES) + message(WARNING "Using HARDCODED ${package_name} locations") + endif(WITH_WINDOWS_FIND_MODULES) +endmacro() + +macro(windows_find_package package_name + ) + if(WITH_WINDOWS_FIND_MODULES) + find_package( ${package_name}) + endif(WITH_WINDOWS_FIND_MODULES) +endmacro() + +add_definitions(-DWIN32) +# Minimum MSVC Version +if(MSVC_VERSION EQUAL 1800) + set(_min_ver "18.0.31101") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver}) + message(FATAL_ERROR + "Visual Studio 2013 (Update 4, ${_min_ver}) required, " + "found (${CMAKE_CXX_COMPILER_VERSION})") + endif() +endif() +if(MSVC_VERSION EQUAL 1900) + set(_min_ver "19.0.24210") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver}) + message(FATAL_ERROR + "Visual Studio 2015 (Update 3, ${_min_ver}) required, " + "found (${CMAKE_CXX_COMPILER_VERSION})") + endif() +endif() +unset(_min_ver) + +# needed for some MSVC installations +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") +set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") + +list(APPEND PLATFORM_LINKLIBS + ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 + advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp +) + +if(WITH_INPUT_IME) + list(APPEND PLATFORM_LINKLIBS imm32) +endif() + +add_definitions( + -D_CRT_NONSTDC_NO_DEPRECATE + -D_CRT_SECURE_NO_DEPRECATE + -D_SCL_SECURE_NO_DEPRECATE + -D_CONSOLE + -D_LIB +) + +# MSVC11 needs _ALLOW_KEYWORD_MACROS to build +add_definitions(-D_ALLOW_KEYWORD_MACROS) + +# We want to support Vista level ABI +add_definitions(-D_WIN32_WINNT=0x600) + +# Make cmake find the msvc redistributables +set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE) +include(InstallRequiredSystemLibraries) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP") + +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") +set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MT") +set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MT") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT") + +set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO ") +set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib ") + +# Ignore meaningless for us linker warnings. +set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /ignore:4049 /ignore:4217 /ignore:4221") +set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") + +# MSVC only, Mingw doesnt need +if(CMAKE_CL_64) + set(PLATFORM_LINKFLAGS "/MACHINE:X64 /OPT:NOREF ${PLATFORM_LINKFLAGS}") +else() + set(PLATFORM_LINKFLAGS "/MACHINE:IX86 /LARGEADDRESSAWARE ${PLATFORM_LINKFLAGS}") +endif() + +set(PLATFORM_LINKFLAGS_DEBUG "/IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib") + +if(NOT DEFINED LIBDIR) + + # Setup 64bit and 64bit windows systems + if(CMAKE_CL_64) + message(STATUS "64 bit compiler detected.") + set(LIBDIR_BASE "win64") + else() + message(STATUS "32 bit compiler detected.") + set(LIBDIR_BASE "windows") + endif() + + if(MSVC_VERSION EQUAL 1900) + message(STATUS "Visual Studio 2015 detected.") + set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14) + else() + message(STATUS "Visual Studio 2013 detected.") + set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc12) + endif() +else() + message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") +endif() +if(NOT EXISTS "${LIBDIR}/") + message(FATAL_ERROR "Windows requires pre-compiled libs at: '${LIBDIR}'") +endif() + +# Add each of our libraries to our cmake_prefix_path so find_package() could work +file(GLOB children RELATIVE ${LIBDIR} ${LIBDIR}/*) +foreach(child ${children}) + if(IS_DIRECTORY ${LIBDIR}/${child}) + list(APPEND CMAKE_PREFIX_PATH ${LIBDIR}/${child}) + endif() +endforeach() + +set(ZLIB_INCLUDE_DIRS ${LIBDIR}/zlib/include) +set(ZLIB_LIBRARIES ${LIBDIR}/zlib/lib/libz_st.lib) +set(ZLIB_INCLUDE_DIR ${LIBDIR}/zlib/include) +set(ZLIB_LIBRARY ${LIBDIR}/zlib/lib/libz_st.lib) +set(ZLIB_DIR ${LIBDIR}/zlib) + +windows_find_package(zlib) # we want to find before finding things that depend on it like png +windows_find_package(png) + +if(NOT PNG_FOUND) + warn_hardcoded_paths(libpng) + set(PNG_PNG_INCLUDE_DIR ${LIBDIR}/png/include) + set(PNG_LIBRARIES libpng) + set(PNG "${LIBDIR}/png") + set(PNG_INCLUDE_DIRS "${PNG}/include") + set(PNG_LIBPATH ${PNG}/lib) # not cmake defined +endif() + +set(JPEG_NAMES ${JPEG_NAMES} libjpeg) +windows_find_package(jpeg REQUIRED) +if(NOT JPEG_FOUND) + warn_hardcoded_paths(jpeg) + set(JPEG_INCLUDE_DIR ${LIBDIR}/jpeg/include) + set(JPEG_LIBRARIES ${LIBDIR}/jpeg/lib/libjpeg.lib) +endif() + +set(PTHREADS_INCLUDE_DIRS ${LIBDIR}/pthreads/include) +set(PTHREADS_LIBRARIES ${LIBDIR}/pthreads/lib/pthreadVC2.lib) + +set(FREETYPE ${LIBDIR}/freetype) +set(FREETYPE_INCLUDE_DIRS + ${LIBDIR}/freetype/include + ${LIBDIR}/freetype/include/freetype2 +) +set(FREETYPE_LIBRARY ${LIBDIR}/freetype/lib/freetype2ST.lib) +windows_find_package(freetype REQUIRED) + +if(WITH_FFTW3) + set(FFTW3 ${LIBDIR}/fftw3) + set(FFTW3_LIBRARIES libfftw) + set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) + set(FFTW3_LIBPATH ${FFTW3}/lib) +endif() + +if(WITH_OPENCOLLADA) + set(OPENCOLLADA ${LIBDIR}/opencollada) + + set(OPENCOLLADA_INCLUDE_DIRS + ${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter + ${OPENCOLLADA}/include/opencollada/COLLADABaseUtils + ${OPENCOLLADA}/include/opencollada/COLLADAFramework + ${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader + ${OPENCOLLADA}/include/opencollada/GeneratedSaxParser + ) + + set(OPENCOLLADA_LIBRARIES + ${OPENCOLLADA}/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib + ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAFramework.lib + ${OPENCOLLADA}/lib/opencollada/OpenCOLLADABaseUtils.lib + ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter.lib + ${OPENCOLLADA}/lib/opencollada/MathMLSolver.lib + ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser.lib + ${OPENCOLLADA}/lib/opencollada/xml.lib + ${OPENCOLLADA}/lib/opencollada/buffer.lib + ${OPENCOLLADA}/lib/opencollada/ftoa.lib + ) + + if(NOT WITH_LLVM) + list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/UTF.lib) + endif() + + set(PCRE_LIBRARIES + ${OPENCOLLADA}/lib/opencollada/pcre.lib + ) +endif() + +if(WITH_CODEC_FFMPEG) + set(FFMPEG_INCLUDE_DIRS + ${LIBDIR}/ffmpeg/include + ${LIBDIR}/ffmpeg/include/msvc + ) + windows_find_package(FFMPEG) + if(NOT FFMPEG_FOUND) + warn_hardcoded_paths(ffmpeg) + set(FFMPEG_LIBRARY_VERSION 55) + set(FFMPEG_LIBRARY_VERSION_AVU 52) + set(FFMPEG_LIBRARIES + ${LIBDIR}/ffmpeg/lib/avcodec-${FFMPEG_LIBRARY_VERSION}.lib + ${LIBDIR}/ffmpeg/lib/avformat-${FFMPEG_LIBRARY_VERSION}.lib + ${LIBDIR}/ffmpeg/lib/avdevice-${FFMPEG_LIBRARY_VERSION}.lib + ${LIBDIR}/ffmpeg/lib/avutil-${FFMPEG_LIBRARY_VERSION_AVU}.lib + ${LIBDIR}/ffmpeg/lib/swscale-2.lib + ) + endif() +endif() + +if(WITH_IMAGE_OPENEXR) + set(OPENEXR_ROOT_DIR ${LIBDIR}/openexr) + set(OPENEXR_VERSION "2.1") + windows_find_package(OPENEXR REQUIRED) + if(NOT OPENEXR_FOUND) + warn_hardcoded_paths(OpenEXR) + set(OPENEXR ${LIBDIR}/openexr) + set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) + set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR}/include/OpenEXR) + set(OPENEXR_LIBPATH ${OPENEXR}/lib) + set(OPENEXR_LIBRARIES + optimized ${OPENEXR_LIBPATH}/Iex-2_2.lib + optimized ${OPENEXR_LIBPATH}/Half.lib + optimized ${OPENEXR_LIBPATH}/IlmImf-2_2.lib + optimized ${OPENEXR_LIBPATH}/Imath-2_2.lib + optimized ${OPENEXR_LIBPATH}/IlmThread-2_2.lib + debug ${OPENEXR_LIBPATH}/Iex-2_2_d.lib + debug ${OPENEXR_LIBPATH}/Half_d.lib + debug ${OPENEXR_LIBPATH}/IlmImf-2_2_d.lib + debug ${OPENEXR_LIBPATH}/Imath-2_2_d.lib + debug ${OPENEXR_LIBPATH}/IlmThread-2_2_d.lib + ) + endif() +endif() + +if(WITH_IMAGE_TIFF) + # Try to find tiff first then complain and set static and maybe wrong paths + windows_find_package(TIFF) + if(NOT TIFF_FOUND) + warn_hardcoded_paths(libtiff) + set(TIFF_LIBRARY ${LIBDIR}/tiff/lib/libtiff.lib) + set(TIFF_INCLUDE_DIR ${LIBDIR}/tiff/include) + endif() +endif() + +if(WITH_JACK) + set(JACK_INCLUDE_DIRS + ${LIBDIR}/jack/include/jack + ${LIBDIR}/jack/include + ) + set(JACK_LIBRARIES optimized ${LIBDIR}/jack/lib/libjack.lib debug ${LIBDIR}/jack/lib/libjack_d.lib) +endif() + +if(WITH_PYTHON) + set(PYTHON_VERSION 3.5) # CACHE STRING) + + string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) + # Use shared libs for vc2008 and vc2010 until we actually have vc2010 libs + set(PYTHON_LIBRARY ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) + unset(_PYTHON_VERSION_NO_DOTS) + + # Shared includes for both vc2008 and vc2010 + set(PYTHON_INCLUDE_DIR ${LIBDIR}/python/include/python${PYTHON_VERSION}) + + # uncached vars + set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") + set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") +endif() + +if(WITH_BOOST) + if(WITH_CYCLES_OSL) + set(boost_extra_libs wave) + endif() + if(WITH_INTERNATIONAL) + list(APPEND boost_extra_libs locale) + endif() + if(WITH_OPENVDB) + list(APPEND boost_extra_libs iostreams) + endif() + set(Boost_USE_STATIC_RUNTIME ON) # prefix lib + set(Boost_USE_MULTITHREADED ON) # suffix -mt + set(Boost_USE_STATIC_LIBS ON) # suffix -s + if (WITH_WINDOWS_FIND_MODULES) + find_package(Boost COMPONENTS date_time filesystem thread regex system ${boost_extra_libs}) + endif (WITH_WINDOWS_FIND_MODULES) + if(NOT Boost_FOUND) + warn_hardcoded_paths(BOOST) + set(BOOST ${LIBDIR}/boost) + set(BOOST_INCLUDE_DIR ${BOOST}/include) + if(MSVC12) + set(BOOST_LIBPATH ${BOOST}/lib) + set(BOOST_POSTFIX "vc120-mt-s-1_60.lib") + set(BOOST_DEBUG_POSTFIX "vc120-mt-sgd-1_60.lib") + else() + set(BOOST_LIBPATH ${BOOST}/lib) + set(BOOST_POSTFIX "vc140-mt-s-1_60.lib") + set(BOOST_DEBUG_POSTFIX "vc140-mt-sgd-1_60.lib") + endif() + set(BOOST_LIBRARIES + optimized libboost_date_time-${BOOST_POSTFIX} + optimized libboost_filesystem-${BOOST_POSTFIX} + optimized libboost_regex-${BOOST_POSTFIX} + optimized libboost_system-${BOOST_POSTFIX} + optimized libboost_thread-${BOOST_POSTFIX} + debug libboost_date_time-${BOOST_DEBUG_POSTFIX} + debug libboost_filesystem-${BOOST_DEBUG_POSTFIX} + debug libboost_regex-${BOOST_DEBUG_POSTFIX} + debug libboost_system-${BOOST_DEBUG_POSTFIX} + debug libboost_thread-${BOOST_DEBUG_POSTFIX} + ) + if(WITH_CYCLES_OSL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized libboost_wave-${BOOST_POSTFIX} + debug libboost_wave-${BOOST_DEBUG_POSTFIX}) + endif() + if(WITH_INTERNATIONAL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized libboost_locale-${BOOST_POSTFIX} + debug libboost_locale-${BOOST_DEBUG_POSTFIX}) + endif() + else() # we found boost using find_package + set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS}) + set(BOOST_LIBRARIES ${Boost_LIBRARIES}) + set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS}) + endif() + set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB") +endif() + +if(WITH_OPENIMAGEIO) + windows_find_package(OpenImageIO) + set(OPENIMAGEIO ${LIBDIR}/openimageio) + set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) + set(OIIO_OPTIMIZED optimized OpenImageIO optimized OpenImageIO_Util) + set(OIIO_DEBUG debug OpenImageIO_d debug OpenImageIO_Util_d) + set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG}) + set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib) + set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0") + set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD") + set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe") + add_definitions(-DOIIO_STATIC_BUILD) +endif() + +if(WITH_LLVM) + set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + file(GLOB LLVM_LIBRARY_OPTIMIZED ${LLVM_ROOT_DIR}/lib/*.lib) + + if(EXISTS ${LLVM_ROOT_DIR}/debug/lib) + foreach(LLVM_OPTIMIZED_LIB ${LLVM_LIBRARY_OPTIMIZED}) + get_filename_component(LIBNAME ${LLVM_OPTIMIZED_LIB} ABSOLUTE) + list(APPEND LLVM_LIBS optimized ${LIBNAME}) + endforeach(LLVM_OPTIMIZED_LIB) + + file(GLOB LLVM_LIBRARY_DEBUG ${LLVM_ROOT_DIR}/debug/lib/*.lib) + + foreach(LLVM_DEBUG_LIB ${LLVM_LIBRARY_DEBUG}) + get_filename_component(LIBNAME ${LLVM_DEBUG_LIB} ABSOLUTE) + list(APPEND LLVM_LIBS debug ${LIBNAME}) + endforeach(LLVM_DEBUG_LIB) + + set(LLVM_LIBRARY ${LLVM_LIBS}) + else() + message(WARNING "LLVM debug libs not present on this system. Using release libs for debug builds.") + set(LLVM_LIBRARY ${LLVM_LIBRARY_OPTIMIZED}) + endif() + +endif() + +if(WITH_OPENCOLORIO) + set(OPENCOLORIO ${LIBDIR}/opencolorio) + set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) + set(OPENCOLORIO_LIBRARIES OpenColorIO) + set(OPENCOLORIO_LIBPATH ${LIBDIR}/opencolorio/lib) + set(OPENCOLORIO_DEFINITIONS) +endif() + +if(WITH_OPENVDB) + set(BLOSC_LIBRARIES optimized ${LIBDIR}/blosc/lib/libblosc.lib debug ${LIBDIR}/blosc/lib/libblosc_d.lib) + set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib) + set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include) + set(OPENVDB ${LIBDIR}/openvdb) + set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include ${TBB_INCLUDE_DIR}) + set(OPENVDB_LIBRARIES optimized openvdb debug openvdb_d ${TBB_LIBRARIES} ${BLOSC_LIBRARIES}) + set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib) +endif() + +if(WITH_ALEMBIC) + set(ALEMBIC ${LIBDIR}/alembic) + set(ALEMBIC_INCLUDE_DIR ${ALEMBIC}/include) + set(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR}) + set(ALEMBIC_LIBPATH ${ALEMBIC}/lib) + set(ALEMBIC_LIBRARIES optimized alembic debug alembic_d) +endif() + +if(WITH_MOD_CLOTH_ELTOPO) + set(LAPACK ${LIBDIR}/lapack) + # set(LAPACK_INCLUDE_DIR ${LAPACK}/include) + set(LAPACK_LIBPATH ${LAPACK}/lib) + set(LAPACK_LIBRARIES + ${LIBDIR}/lapack/lib/libf2c.lib + ${LIBDIR}/lapack/lib/clapack_nowrap.lib + ${LIBDIR}/lapack/lib/BLAS_nowrap.lib + ) +endif() + +if(WITH_OPENSUBDIV) + set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include) + set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib) + set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBPATH}/osdCPU.lib ${OPENSUBDIV_LIBPATH}/osdGPU.lib) + find_package(OpenSubdiv) +endif() + +if(WITH_SDL) + set(SDL ${LIBDIR}/sdl) + set(SDL_INCLUDE_DIR ${SDL}/include) + set(SDL_LIBPATH ${SDL}/lib) + # MinGW TODO: Update MinGW to SDL2 + if(NOT CMAKE_COMPILER_IS_GNUCC) + set(SDL_LIBRARY SDL2) + else() + set(SDL_LIBRARY SDL) + endif() +endif() + +# Audio IO +if(WITH_SYSTEM_AUDASPACE) + set(AUDASPACE_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace) + set(AUDASPACE_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace.lib) + set(AUDASPACE_C_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace) + set(AUDASPACE_C_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-c.lib) + set(AUDASPACE_PY_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace) + set(AUDASPACE_PY_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-py.lib) +endif() + +# used in many places so include globally, like OpenGL +blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}") + +#find signtool +SET(ProgramFilesX86_NAME "ProgramFiles(x86)") #env dislikes the ( ) +find_program(SIGNTOOL_EXE signtool +HINTS + "$ENV{${ProgramFilesX86_NAME}}/Windows Kits/10/bin/x86/" + "$ENV{ProgramFiles}/Windows Kits/10/bin/x86/" + "$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.1/bin/x86/" + "$ENV{ProgramFiles}/Windows Kits/8.1/bin/x86/" + "$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.0/bin/x86/" + "$ENV{ProgramFiles}/Windows Kits/8.0/bin/x86/" +) diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index b34d4dfe6f1..9834cda43bc 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "V2.7x" +PROJECT_NUMBER = "V2.8x" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 2a3213e4e6f..4a109a44ec0 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -1014,6 +1014,9 @@ context_type_map = { "active_bone": ("EditBone", False), "active_gpencil_frame": ("GreasePencilLayer", True), "active_gpencil_layer": ("GPencilLayer", True), + "active_gpencil_brush": ("GPencilSculptBrush", False), + "active_gpencil_palette": ("GPencilPalette", True), + "active_gpencil_palettecolor": ("GPencilPaletteColor", True), "active_node": ("Node", False), "active_object": ("Object", False), "active_operator": ("Operator", False), diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp index 2c362778210..c1da9f36cfb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp @@ -151,8 +151,8 @@ static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1 int index = 0; btScalar minDot = BT_LARGE_FLOAT; - if( count2 > 0 ) - index = (int) normal1.minDot( vertices2, count2, minDot); + if( count2 > 0 ) + index = (int) normal1.minDot( vertices2, count2, minDot); btVector3 v1 = b2Mul(xf1, vertices1[edge1]); btVector3 v2 = b2Mul(xf2, vertices2[index]); @@ -174,9 +174,9 @@ static btScalar FindMaxSeparation(int* edgeIndex, // Find edge normal on poly1 that has the largest projection onto d. int edge = 0; - btScalar maxDot; - if( count1 > 0 ) - edge = (int) dLocal1.maxDot( normals1, count1, maxDot); + btScalar maxDot; + if( count1 > 0 ) + edge = (int) dLocal1.maxDot( normals1, count1, maxDot); // Get the separation for the edge normal. btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index a80c438d12a..589a7f55f2b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -232,8 +232,8 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap m_compoundShapeRevision = compoundShape->getUpdateRevision(); } - if (m_childCollisionAlgorithms.size()==0) - return; + if (m_childCollisionAlgorithms.size()==0) + return; const btDbvt* tree = compoundShape->getDynamicAabbTree(); //use a dynamic aabb tree to cull potential child-overlaps diff --git a/extern/clew/README.blender b/extern/clew/README.blender index e500a1bef7d..8355a96db8e 100644 --- a/extern/clew/README.blender +++ b/extern/clew/README.blender @@ -1,5 +1,5 @@ Project: OpenCL Wrangler URL: https://github.com/OpenCLWrangler/clew License: Apache 2.0 -Upstream version: 277db43 +Upstream version: 309a653 Local modifications: None diff --git a/extern/clew/src/clew.c b/extern/clew/src/clew.c index e3adabd829c..3717c74f1a0 100644 --- a/extern/clew/src/clew.c +++ b/extern/clew/src/clew.c @@ -137,6 +137,17 @@ PFNCLCREATEFROMGLTEXTURE3D __clewCreateFromGLTexture3D = NULL; #endif PFNCLGETGLCONTEXTINFOKHR __clewGetGLContextInfoKHR = NULL; +static CLEW_DYNLIB_HANDLE dynamic_library_open_find(const char **paths) { + int i = 0; + while (paths[i] != NULL) { + CLEW_DYNLIB_HANDLE lib = CLEW_DYNLIB_OPEN(paths[i]); + if (lib != NULL) { + return lib; + } + ++i; + } + return NULL; +} static void clewExit(void) { @@ -151,11 +162,15 @@ static void clewExit(void) int clewInit() { #ifdef _WIN32 - const char *path = "OpenCL.dll"; + const char *paths[] = {"OpenCL.dll", NULL}; #elif defined(__APPLE__) - const char *path = "/Library/Frameworks/OpenCL.framework/OpenCL"; + const char *paths[] = {"/Library/Frameworks/OpenCL.framework/OpenCL", NULL}; #else - const char *path = "libOpenCL.so"; + const char *paths[] = {"libOpenCL.so", + "libOpenCL.so.0", + "libOpenCL.so.1", + "libOpenCL.so.2", + NULL}; #endif int error = 0; @@ -167,7 +182,7 @@ int clewInit() } // Load library - module = CLEW_DYNLIB_OPEN(path); + module = dynamic_library_open_find(paths); // Check for errors if (module == NULL) diff --git a/extern/curve_fit_nd/README.blender b/extern/curve_fit_nd/README.blender new file mode 100644 index 00000000000..db520ea524e --- /dev/null +++ b/extern/curve_fit_nd/README.blender @@ -0,0 +1,5 @@ +Project: Curve-Fit-nD +URL: https://github.com/ideasman42/curve-fit-nd +License: BSD 3-Clause +Upstream version: Unknown (Last Release) +Local modifications: None diff --git a/extern/curve_fit_nd/intern/curve_fit_cubic.c b/extern/curve_fit_nd/intern/curve_fit_cubic.c index 9c8ebcd098b..9b4f1869c02 100644 --- a/extern/curve_fit_nd/intern/curve_fit_cubic.c +++ b/extern/curve_fit_nd/intern/curve_fit_cubic.c @@ -614,7 +614,7 @@ static void cubic_from_points_offset_fallback( double dists[2] = {0, 0}; - const double *pt = points_offset; + const double *pt = &points_offset[dims]; for (uint i = 1; i < points_offset_len - 1; i++, pt += dims) { for (uint k = 0; k < 2; k++) { sub_vn_vnvn(tmp, p0, pt, dims); @@ -623,13 +623,13 @@ static void cubic_from_points_offset_fallback( } } - float alpha_l = (dists[0] / 0.75) / dot_vnvn(tan_l, a[0], dims); - float alpha_r = (dists[1] / 0.75) / -dot_vnvn(tan_r, a[1], dims); + double alpha_l = (dists[0] / 0.75) / dot_vnvn(tan_l, a[0], dims); + double alpha_r = (dists[1] / 0.75) / -dot_vnvn(tan_r, a[1], dims); - if (!(alpha_l > 0.0f)) { + if (!(alpha_l > 0.0)) { alpha_l = dir_dist / 3.0; } - if (!(alpha_r > 0.0f)) { + if (!(alpha_r > 0.0)) { alpha_r = dir_dist / 3.0; } @@ -896,7 +896,7 @@ static double points_calc_coord_length( } assert(!is_almost_zero(r_u[points_offset_len - 1])); const double w = r_u[points_offset_len - 1]; - for (uint i = 0; i < points_offset_len; i++) { + for (uint i = 1; i < points_offset_len; i++) { r_u[i] /= w; } return w; diff --git a/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c b/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c index b51535bab10..d22d042bff5 100644 --- a/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c +++ b/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c @@ -1048,7 +1048,6 @@ int curve_fit_cubic_to_points_refit_db( { const uint knots_len = points_len; struct Knot *knots = malloc(sizeof(Knot) * knots_len); - knots[0].next = NULL; #ifndef USE_CORNER_DETECT (void)r_corner_index_array; @@ -1085,7 +1084,6 @@ int curve_fit_cubic_to_points_refit_db( knots[i].heap_node = NULL; knots[i].index = i; - knots[i].index = i; knots[i].can_remove = true; knots[i].is_removed = false; knots[i].is_corner = false; @@ -1155,8 +1153,8 @@ int curve_fit_cubic_to_points_refit_db( add_vn_vnvn(k->tan[0], tan_prev, tan_next, dims); normalize_vn(k->tan[0], dims); copy_vnvn(k->tan[1], k->tan[0], dims); - k->handles[0] = len_prev / 3; - k->handles[1] = len_next / 3; + k->handles[0] = len_prev / 3; + k->handles[1] = len_next / -3; } #else if (knots_len < 2) { @@ -1185,8 +1183,8 @@ int curve_fit_cubic_to_points_refit_db( add_vn_vnvn(k->tan[0], tan_prev, tan_next, dims); normalize_vn(k->tan[0], dims); copy_vnvn(k->tan[1], k->tan[0], dims); - k->handles[0] = len_prev / 3; - k->handles[1] = len_next / 3; + k->handles[0] = len_prev / 3; + k->handles[1] = len_next / -3; copy_vnvn(tan_prev, tan_next, dims); len_prev = len_next; @@ -1201,8 +1199,8 @@ int curve_fit_cubic_to_points_refit_db( tan_prev, &points[0 * dims], &points[1 * dims], dims); copy_vnvn(knots[0].tan[0], tan_prev, dims); copy_vnvn(knots[0].tan[1], tan_prev, dims); - knots[0].handles[0] = len_prev / 3; - knots[0].handles[1] = len_prev / 3; + knots[0].handles[0] = len_prev / 3; + knots[0].handles[1] = len_prev / -3; for (uint i_curr = 1, i_next = 2; i_next < knots_len; i_curr = i_next++) { struct Knot *k = &knots[i_curr]; @@ -1215,8 +1213,8 @@ int curve_fit_cubic_to_points_refit_db( add_vn_vnvn(k->tan[0], tan_prev, tan_next, dims); normalize_vn(k->tan[0], dims); copy_vnvn(k->tan[1], k->tan[0], dims); - k->handles[0] = len_prev / 3; - k->handles[1] = len_next / 3; + k->handles[0] = len_prev / 3; + k->handles[1] = len_next / -3; copy_vnvn(tan_prev, tan_next, dims); len_prev = len_next; @@ -1224,8 +1222,8 @@ int curve_fit_cubic_to_points_refit_db( copy_vnvn(knots[knots_len - 1].tan[0], tan_next, dims); copy_vnvn(knots[knots_len - 1].tan[1], tan_next, dims); - knots[knots_len - 1].handles[0] = len_next / 3; - knots[knots_len - 1].handles[1] = len_next / 3; + knots[knots_len - 1].handles[0] = len_next / 3; + knots[knots_len - 1].handles[1] = len_next / -3; } #endif } diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 3b410b2a1e1..97854a88e84 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -146,6 +146,14 @@ if(WITH_CYCLES_OSL) ) endif() +if(WITH_CYCLES_OPENSUBDIV) + add_definitions(-DWITH_OPENSUBDIV) + include_directories( + SYSTEM + ${OPENSUBDIV_INCLUDE_DIR} + ) +endif() + set(WITH_CYCLES_DEVICE_OPENCL TRUE) set(WITH_CYCLES_DEVICE_CUDA TRUE) set(WITH_CYCLES_DEVICE_MULTI TRUE) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 73dbf16a3d3..8cd499b7ca6 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -88,6 +88,9 @@ macro(cycles_target_link_libraries target) if(WITH_CYCLES_OSL) target_link_libraries(${target} ${OSL_LIBRARIES} ${LLVM_LIBRARIES}) endif() + if(WITH_CYCLES_OPENSUBDIV) + target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES}) + endif() target_link_libraries( ${target} ${OPENIMAGEIO_LIBRARIES} diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp index 726e9a51744..e8168bc15ff 100644 --- a/intern/cycles/app/cycles_standalone.cpp +++ b/intern/cycles/app/cycles_standalone.cpp @@ -375,6 +375,8 @@ static void options_parse(int argc, const char **argv) "--threads %d", &options.session_params.threads, "CPU Rendering Threads", "--width %d", &options.width, "Window width in pixel", "--height %d", &options.height, "Window height in pixel", + "--tile-width %d", &options.session_params.tile_size.x, "Tile width in pixels", + "--tile-height %d", &options.session_params.tile_size.y, "Tile height in pixels", "--list-devices", &list, "List information about all available devices", #ifdef WITH_CYCLES_LOGGING "--debug", &debug, "Enable debug logging", diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 3d3aca33881..8a3eb98a5a0 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -57,14 +57,12 @@ struct XMLReadState : public XMLReader { Shader *shader; /* current shader */ string base; /* base path to current file*/ float dicing_rate; /* current dicing rate */ - Mesh::DisplacementMethod displacement_method; XMLReadState() : scene(NULL), smooth(false), shader(NULL), - dicing_rate(0.0f), - displacement_method(Mesh::DISPLACE_BUMP) + dicing_rate(1.0f) { tfm = transform_identity(); } @@ -199,6 +197,9 @@ static void xml_read_camera(XMLReadState& state, pugi::xml_node node) xml_read_int(&cam->width, node, "width"); xml_read_int(&cam->height, node, "height"); + cam->full_width = cam->width; + cam->full_height = cam->height; + xml_read_node(state, cam, node); cam->matrix = state.tfm; @@ -405,8 +406,6 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node) int shader = 0; bool smooth = state.smooth; - mesh->displacement_method = state.displacement_method; - /* read vertices and polygons, RIB style */ vector<float3> P; vector<float> UV; @@ -416,53 +415,14 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node) xml_read_int_array(verts, node, "verts"); xml_read_int_array(nverts, node, "nverts"); -#if 0 if(xml_equal_string(node, "subdivision", "catmull-clark")) { - /* create subd mesh */ - SubdMesh sdmesh; - - /* create subd vertices */ - for(size_t i = 0; i < P.size(); i++) - sdmesh.add_vert(P[i]); - - /* create subd faces */ - int index_offset = 0; - - for(size_t i = 0; i < nverts.size(); i++) { - if(nverts[i] == 4) { - int v0 = verts[index_offset + 0]; - int v1 = verts[index_offset + 1]; - int v2 = verts[index_offset + 2]; - int v3 = verts[index_offset + 3]; - - sdmesh.add_face(v0, v1, v2, v3); - } - else { - for(int j = 0; j < nverts[i]-2; j++) { - int v0 = verts[index_offset]; - int v1 = verts[index_offset + j + 1]; - int v2 = verts[index_offset + j + 2]; - - sdmesh.add_face(v0, v1, v2); - } - } - - index_offset += nverts[i]; - } - - /* finalize subd mesh */ - sdmesh.finish(); - - /* parameters */ - SubdParams sdparams(mesh, shader, smooth); - xml_read_float(&sdparams.dicing_rate, node, "dicing_rate"); - - DiagSplit dsplit(sdparams); - sdmesh.tessellate(&dsplit); + mesh->subdivision_type = Mesh::SUBDIVISION_CATMULL_CLARK; } - else -#endif - { + else if(xml_equal_string(node, "subdivision", "linear")) { + mesh->subdivision_type = Mesh::SUBDIVISION_LINEAR; + } + + if(mesh->subdivision_type == Mesh::SUBDIVISION_NONE) { /* create vertices */ mesh->verts = P; @@ -517,70 +477,63 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node) } } } + else { + /* create vertices */ + mesh->verts = P; - /* temporary for test compatibility */ - mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); -} - -/* Patch */ + size_t num_ngons = 0; + size_t num_corners = 0; + for(size_t i = 0; i < nverts.size(); i++) { + num_ngons += (nverts[i] == 4) ? 0 : 1; + num_corners += nverts[i]; + } + mesh->reserve_subd_faces(nverts.size(), num_ngons, num_corners); -static void xml_read_patch(const XMLReadState& state, pugi::xml_node node) -{ - /* read patch */ - Patch *patch = NULL; + /* create subd_faces */ + int index_offset = 0; - vector<float3> P; - xml_read_float3_array(P, node, "P"); + for(size_t i = 0; i < nverts.size(); i++) { + mesh->add_subd_face(&verts[index_offset], nverts[i], shader, smooth); + index_offset += nverts[i]; + } - if(xml_equal_string(node, "type", "bilinear")) { - /* bilinear patch */ - if(P.size() == 4) { - LinearQuadPatch *bpatch = new LinearQuadPatch(); + /* uv map */ + if(xml_read_float_array(UV, node, "UV")) { + ustring name = ustring("UVMap"); + Attribute *attr = mesh->subd_attributes.add(ATTR_STD_UV, name); + float3 *fdata = attr->data_float3(); - for(int i = 0; i < 4; i++) - P[i] = transform_point(&state.tfm, P[i]); - memcpy(bpatch->hull, &P[0], sizeof(bpatch->hull)); +#if 0 + if(subdivide_uvs) { + attr->flags |= ATTR_SUBDIVIDED; + } +#endif - patch = bpatch; + index_offset = 0; + for(size_t i = 0; i < nverts.size(); i++) { + for(int j = 0; j < nverts[i]; j++) { + *(fdata++) = make_float3(UV[index_offset++]); + } + } } - else - fprintf(stderr, "Invalid number of control points for bilinear patch.\n"); - } - else if(xml_equal_string(node, "type", "bicubic")) { - /* bicubic patch */ - if(P.size() == 16) { - BicubicPatch *bpatch = new BicubicPatch(); - for(int i = 0; i < 16; i++) - P[i] = transform_point(&state.tfm, P[i]); - memcpy(bpatch->hull, &P[0], sizeof(bpatch->hull)); - - patch = bpatch; + /* setup subd params */ + if(!mesh->subd_params) { + mesh->subd_params = new SubdParams(mesh); } - else - fprintf(stderr, "Invalid number of control points for bicubic patch.\n"); - } - else - fprintf(stderr, "Unknown patch type.\n"); - - if(patch) { - /* add mesh */ - Mesh *mesh = xml_add_mesh(state.scene, transform_identity()); + SubdParams& sdparams = *mesh->subd_params; - mesh->used_shaders.push_back(state.shader); - - /* split */ - SubdParams sdparams(mesh); + sdparams.dicing_rate = state.dicing_rate; xml_read_float(&sdparams.dicing_rate, node, "dicing_rate"); + sdparams.dicing_rate = std::max(0.1f, sdparams.dicing_rate); - DiagSplit dsplit(sdparams); - dsplit.split_quad(patch); - - delete patch; - - /* temporary for test compatibility */ - mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); + state.scene->camera->update(); + sdparams.camera = state.scene->camera; + sdparams.objecttoworld = state.tfm; } + + /* temporary for test compatibility */ + mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); } /* Light */ @@ -653,14 +606,6 @@ static void xml_read_state(XMLReadState& state, pugi::xml_node node) state.smooth = true; else if(xml_equal_string(node, "interpolation", "flat")) state.smooth = false; - - /* read displacement method */ - if(xml_equal_string(node, "displacement_method", "true")) - state.displacement_method = Mesh::DISPLACE_TRUE; - else if(xml_equal_string(node, "displacement_method", "bump")) - state.displacement_method = Mesh::DISPLACE_BUMP; - else if(xml_equal_string(node, "displacement_method", "both")) - state.displacement_method = Mesh::DISPLACE_BOTH; } /* Scene */ @@ -688,9 +633,6 @@ static void xml_read_scene(XMLReadState& state, pugi::xml_node scene_node) else if(string_iequals(node.name(), "mesh")) { xml_read_mesh(state, node); } - else if(string_iequals(node.name(), "patch")) { - xml_read_patch(state, node); - } else if(string_iequals(node.name(), "light")) { xml_read_light(state, node); } @@ -751,7 +693,7 @@ void xml_read_file(Scene *scene, const char *filepath) state.tfm = transform_identity(); state.shader = scene->default_surface; state.smooth = false; - state.dicing_rate = 0.1f; + state.dicing_rate = 1.0f; state.base = path_dirname(filepath); xml_read_include(state, path_filename(filepath)); diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py index f4aaaab5eab..19f2ecc9d1a 100644 --- a/intern/cycles/blender/addon/osl.py +++ b/intern/cycles/blender/addon/osl.py @@ -41,6 +41,8 @@ def update_script_node(node, report): import shutil import tempfile + oso_file_remove = False + if node.mode == 'EXTERNAL': # compile external script file script_path = bpy.path.abspath(node.filepath, library=node.id_data.library) @@ -49,7 +51,6 @@ def update_script_node(node, report): if script_ext == ".oso": # it's a .oso file, no need to compile ok, oso_path = True, script_path - oso_file_remove = False elif script_ext == ".osl": # compile .osl file ok, oso_path = osl_compile(script_path, report) @@ -65,7 +66,6 @@ def update_script_node(node, report): elif os.path.dirname(node.filepath) == "": # module in search path oso_path = node.filepath - oso_file_remove = False ok = True else: # unknown @@ -88,12 +88,10 @@ def update_script_node(node, report): osl_file.close() ok, oso_path = osl_compile(osl_file.name, report) - oso_file_remove = False os.remove(osl_file.name) else: # compile text datablock from disk directly ok, oso_path = osl_compile(osl_path, report) - oso_file_remove = False if ok: # read bytecode diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 81204eb8ae0..82a18b3f6a9 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -369,12 +369,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Size of a micropolygon in pixels", min=0.1, max=1000.0, default=1.0, + subtype="PIXEL" ) cls.preview_dicing_rate = FloatProperty( name="Preview Dicing Rate", description="Size of a micropolygon in pixels during preview render", min=0.1, max=1000.0, default=8.0, + subtype="PIXEL" ) cls.max_subdivisions = IntProperty( @@ -775,6 +777,13 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup): default='LINEAR', ) + cls.displacement_method = EnumProperty( + name="Displacement Method", + description="Method to use for the displacement", + items=enum_displacement_methods, + default='BUMP', + ) + @classmethod def unregister(cls): del bpy.types.Material.cycles @@ -952,13 +961,6 @@ class CyclesMeshSettings(bpy.types.PropertyGroup): type=cls, ) - cls.displacement_method = EnumProperty( - name="Displacement Method", - description="Method to use for the displacement", - items=enum_displacement_methods, - default='BUMP', - ) - @classmethod def unregister(cls): del bpy.types.Mesh.cycles @@ -1007,8 +1009,8 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): ) cls.dicing_rate = FloatProperty( - name="Dicing Rate", - description="Multiplier for scene dicing rate", + name="Dicing Scale", + description="Multiplier for scene dicing rate (located in the Geometry Panel)", min=0.1, max=1000.0, default=1.0, ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 42f7970769a..52872d2b83f 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -674,40 +674,6 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel): split.separator() -class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel): - bl_label = "Displacement" - bl_context = "data" - - @classmethod - def poll(cls, context): - if CyclesButtonsPanel.poll(context): - if context.mesh or context.curve or context.meta_ball: - if context.scene.cycles.feature_set == 'EXPERIMENTAL': - return True - - return False - - def draw(self, context): - layout = self.layout - - mesh = context.mesh - curve = context.curve - mball = context.meta_ball - - if mesh: - cdata = mesh.cycles - elif curve: - cdata = curve.cycles - elif mball: - cdata = mball.cycles - - split = layout.split() - - col = split.column() - sub = col.column(align=True) - sub.label(text="Displacement:") - sub.prop(cdata, "displacement_method", text="") - class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel): bl_label = "Motion Blur" bl_context = "object" @@ -1219,6 +1185,11 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel): col.prop(cmat, "sample_as_light", text="Multiple Importance") col.prop(cmat, "use_transparent_shadow") + if context.scene.cycles.feature_set == 'EXPERIMENTAL': + col.separator() + col.label(text="Displacement:") + col.prop(cmat, "displacement_method", text="") + col = split.column() col.label(text="Volume:") sub = col.column() diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 74fd4cb44a0..c33bc4c263f 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -409,7 +409,8 @@ static void attr_create_uv_map(Scene *scene, BL::Mesh& b_mesh, const vector<int>& nverts, const vector<int>& face_flags, - bool subdivision) + bool subdivision, + bool subdivide_uvs) { if(subdivision) { BL::Mesh::uv_layers_iterator l; @@ -429,6 +430,10 @@ static void attr_create_uv_map(Scene *scene, else attr = mesh->subd_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER); + if(subdivide_uvs) { + attr->flags |= ATTR_SUBDIVIDED; + } + BL::Mesh::polygons_iterator p; float3 *fdata = attr->data_float3(); @@ -592,7 +597,8 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh& b_mesh, const vector<Shader*>& used_shaders, - bool subdivision=false) + bool subdivision=false, + bool subdivide_uvs=true) { /* count vertices and faces */ int numverts = b_mesh.vertices.length(); @@ -638,6 +644,7 @@ static void create_mesh(Scene *scene, /* create generated coordinates from undeformed coordinates */ if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { Attribute *attr = attributes.add(ATTR_STD_GENERATED); + attr->flags |= ATTR_SUBDIVIDED; float3 loc, size; mesh_texture_space(b_mesh, loc, size); @@ -746,7 +753,7 @@ static void create_mesh(Scene *scene, * The calculate functions will check whether they're needed or not. */ attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision); - attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivision); + attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivision, subdivide_uvs); /* for volume objects, create a matrix to transform from object space to * mesh texture space. this does not work with deformations but that can @@ -770,9 +777,39 @@ static void create_subd_mesh(Scene *scene, float dicing_rate, int max_subdivisions) { - create_mesh(scene, mesh, b_mesh, used_shaders, true); + BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length()-1]); + bool subdivide_uvs = subsurf_mod.use_subsurf_uv(); + + create_mesh(scene, mesh, b_mesh, used_shaders, true, subdivide_uvs); + + /* export creases */ + size_t num_creases = 0; + BL::Mesh::edges_iterator e; + + for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { + if(e->crease() != 0.0f) { + num_creases++; + } + } + + mesh->subd_creases.resize(num_creases); + + Mesh::SubdEdgeCrease* crease = mesh->subd_creases.data(); + for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { + if(e->crease() != 0.0f) { + crease->v[0] = e->vertices()[0]; + crease->v[1] = e->vertices()[1]; + crease->crease = e->crease(); - SubdParams sdparams(mesh); + crease++; + } + } + + /* set subd params */ + if(!mesh->subd_params) { + mesh->subd_params = new SubdParams(mesh); + } + SubdParams& sdparams = *mesh->subd_params; PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles"); @@ -782,10 +819,6 @@ static void create_subd_mesh(Scene *scene, scene->camera->update(); sdparams.camera = scene->camera; sdparams.objecttoworld = get_transform(b_ob.matrix_world()); - - /* tesselate */ - DiagSplit dsplit(sdparams); - mesh->tessellate(&dsplit); } /* Sync */ @@ -903,8 +936,6 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, mesh_synced.insert(mesh); /* create derived mesh */ - PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles"); - array<int> oldtriangle = mesh->triangles; /* compares curve_keys rather than strands in order to handle quick hair @@ -936,7 +967,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length()-1]; bool enabled = preview ? mod.show_viewport() : mod.show_render(); - if(enabled && mod.type() == BL::Modifier::type_SUBSURF && RNA_int_get(&cobj, "use_adaptive_subdivision")) { + if(enabled && mod.type() == BL::Modifier::type_SUBSURF && RNA_boolean_get(&cobj, "use_adaptive_subdivision")) { BL::SubsurfModifier subsurf(mod); if(subsurf.subdivision_type() == BL::SubsurfModifier::subdivision_type_CATMULL_CLARK) { @@ -974,21 +1005,6 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, } mesh->geometry_flags = requested_geometry_flags; - /* displacement method */ - if(cmesh.data) { - const int method = get_enum(cmesh, - "displacement_method", - Mesh::DISPLACE_NUM_METHODS, - Mesh::DISPLACE_BUMP); - - if(method == 0 || !experimental) - mesh->displacement_method = Mesh::DISPLACE_BUMP; - else if(method == 1) - mesh->displacement_method = Mesh::DISPLACE_TRUE; - else - mesh->displacement_method = Mesh::DISPLACE_BOTH; - } - /* fluid motion */ sync_mesh_fluid_motion(b_ob, scene, mesh); diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 4886735a18f..f305e8e17cc 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -329,16 +329,18 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, /* object transformation */ if(tfm != object->tfm) { VLOG(1) << "Object " << b_ob.name() << " motion detected."; - if(motion_time == -1.0f) { - object->motion.pre = tfm; - object->use_motion = true; - } - else if(motion_time == 1.0f) { - object->motion.post = tfm; + if(motion_time == -1.0f || motion_time == 1.0f) { object->use_motion = true; } } + if(motion_time == -1.0f) { + object->motion.pre = tfm; + } + else if(motion_time == 1.0f) { + object->motion.post = tfm; + } + /* mesh deformation */ if(object->mesh) sync_mesh_motion(b_ob, object, motion_time); @@ -395,8 +397,8 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, object->name = b_ob.name().c_str(); object->pass_id = b_ob.pass_index(); object->tfm = tfm; - object->motion.pre = tfm; - object->motion.post = tfm; + object->motion.pre = transform_empty(); + object->motion.post = transform_empty(); object->use_motion = false; /* motion blur */ diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index b9876cd604f..dd2900a8d5b 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -36,6 +36,8 @@ bool BlenderSync::sync_dupli_particle(BL::Object& b_ob, if(!b_psys) return false; + object->hide_on_missing_motion = true; + /* test if we need particle data */ if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE)) return false; diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 64559804ccb..534bc6cc897 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -64,6 +64,14 @@ static VolumeInterpolation get_volume_interpolation(PointerRNA& ptr) VOLUME_INTERPOLATION_LINEAR); } +static DisplacementMethod get_displacement_method(PointerRNA& ptr) +{ + return (DisplacementMethod)get_enum(ptr, + "displacement_method", + DISPLACE_NUM_METHODS, + DISPLACE_BUMP); +} + static int validate_enum_value(int value, int num_values, int default_value) { if(value >= num_values) { @@ -837,8 +845,10 @@ static ShaderNode *add_node(Scene *scene, } } - if(node) + if(node) { + node->name = b_node.name(); graph->add(node); + } return node; } @@ -1180,6 +1190,7 @@ void BlenderSync::sync_materials(bool update_all) shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume"); shader->volume_sampling_method = get_volume_sampling(cmat); shader->volume_interpolation_method = get_volume_interpolation(cmat); + shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP; shader->set_graph(graph); shader->tag_update(scene); diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index d5dbaba094b..e79f2bbb27d 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -698,7 +698,7 @@ protected: /* Object Key */ -enum { OBJECT_PERSISTENT_ID_SIZE = 8 }; +enum { OBJECT_PERSISTENT_ID_SIZE = 16 }; struct ObjectKey { void *parent; diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 67ffb6853d6..f2a735d12e3 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -713,14 +713,14 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range, * can not control. */ typedef StackAllocator<256, int> LeafStackAllocator; + typedef StackAllocator<256, BVHReference> LeafReferenceStackAllocator; vector<int, LeafStackAllocator> p_type[PRIMITIVE_NUM_TOTAL]; vector<int, LeafStackAllocator> p_index[PRIMITIVE_NUM_TOTAL]; vector<int, LeafStackAllocator> p_object[PRIMITIVE_NUM_TOTAL]; - vector<BVHReference, LeafStackAllocator> p_ref[PRIMITIVE_NUM_TOTAL]; + vector<BVHReference, LeafReferenceStackAllocator> p_ref[PRIMITIVE_NUM_TOTAL]; /* TODO(sergey): In theory we should be able to store references. */ - typedef StackAllocator<256, BVHReference> LeafReferenceStackAllocator; vector<BVHReference, LeafReferenceStackAllocator> object_references; uint visibility[PRIMITIVE_NUM_TOTAL] = {0}; diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index df01215c91a..85e736ad635 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -56,8 +56,14 @@ std::ostream& operator <<(std::ostream &os, << string_from_bool(requested_features.use_camera_motion) << std::endl; os << "Use Baking: " << string_from_bool(requested_features.use_baking) << std::endl; + os << "Use Subsurface: " + << string_from_bool(requested_features.use_subsurface) << std::endl; os << "Use Volume: " << string_from_bool(requested_features.use_volume) << std::endl; + os << "Use Branched Integrator: " + << string_from_bool(requested_features.use_integrator_branched) << std::endl; + os << "Use Patch Evaluation: " + << string_from_bool(requested_features.use_patch_evaluation) << std::endl; return os; } diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index e11bb7f76af..77dc1fa9713 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -109,6 +109,9 @@ public: /* Use branched integrator. */ bool use_integrator_branched; + /* Use OpenSubdiv patch evaluation */ + bool use_patch_evaluation; + DeviceRequestedFeatures() { /* TODO(sergey): Find more meaningful defaults. */ @@ -123,6 +126,7 @@ public: use_subsurface = false; use_volume = false; use_integrator_branched = false; + use_patch_evaluation = false; } bool modified(const DeviceRequestedFeatures& requested_features) @@ -137,7 +141,8 @@ public: use_baking == requested_features.use_baking && use_subsurface == requested_features.use_subsurface && use_volume == requested_features.use_volume && - use_integrator_branched == requested_features.use_integrator_branched); + use_integrator_branched == requested_features.use_integrator_branched && + use_patch_evaluation == requested_features.use_patch_evaluation); } /* Convert the requested features structure to a build options, @@ -175,6 +180,9 @@ public: if(!use_integrator_branched) { build_options += " -D__NO_BRANCHED_PATH__"; } + if(!use_patch_evaluation) { + build_options += " -D__NO_PATCH_EVAL__"; + } return build_options; } }; diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 6a511ea7316..76e52498b42 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -297,7 +297,7 @@ public: cuda_error_message("CUDA nvcc compiler version could not be parsed."); return false; } - if(cuda_version < 60) { + if(cuda_version < 75) { printf("Unsupported CUDA version %d.%d detected, " "you need CUDA 7.5 or newer.\n", major, minor); @@ -576,6 +576,7 @@ public: case TYPE_UINT: format = CU_AD_FORMAT_UNSIGNED_INT32; break; case TYPE_INT: format = CU_AD_FORMAT_SIGNED_INT32; break; case TYPE_FLOAT: format = CU_AD_FORMAT_FLOAT; break; + case TYPE_HALF: format = CU_AD_FORMAT_HALF; break; default: assert(0); return; } @@ -747,8 +748,12 @@ public: } /* Resize once */ - if(flat_slot >= bindless_mapping.size()) - bindless_mapping.resize(4096); /*TODO(dingto): Make this a variable */ + if(flat_slot >= bindless_mapping.size()) { + /* Allocate some slots in advance, to reduce amount + * of re-allocations. + */ + bindless_mapping.resize(flat_slot + 128); + } /* Set Mapping and tag that we need to (re-)upload to device */ bindless_mapping.get_data()[flat_slot] = (uint)tex; diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 50490f3a20e..5c05aeb5569 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -875,6 +875,7 @@ public: if(ciErr != CL_SUCCESS) { opencl_error("OpenCL build failed: errors in console"); + fprintf(stderr, "Build error: %s\n", clewErrorString(ciErr)); return false; } diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 42298a0811d..3c37bc0b045 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -113,6 +113,7 @@ set(SRC_SVM_HEADERS svm/svm.h svm/svm_attribute.h svm/svm_blackbody.h + svm/svm_bump.h svm/svm_camera.h svm/svm_closure.h svm/svm_convert.h @@ -162,6 +163,7 @@ set(SRC_GEOM_HEADERS geom/geom_motion_curve.h geom/geom_motion_triangle.h geom/geom_object.h + geom/geom_patch.h geom/geom_primitive.h geom/geom_subd_triangle.h geom/geom_triangle.h @@ -175,6 +177,7 @@ set(SRC_UTIL_HEADERS ../util/util_half.h ../util/util_math.h ../util/util_math_fast.h + ../util/util_static_assert.h ../util/util_transform.h ../util/util_texture.h ../util/util_types.h diff --git a/intern/cycles/kernel/bvh/qbvh_volume.h b/intern/cycles/kernel/bvh/qbvh_volume.h index b4f334eb842..847a11d8ad4 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume.h +++ b/intern/cycles/kernel/bvh/qbvh_volume.h @@ -236,6 +236,14 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* If node is leaf, fetch triangle list. */ if(node_addr < 0) { float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1)); + + if((__float_as_uint(leaf.z) & visibility) == 0) { + /* Pop. */ + node_addr = traversal_stack[stack_ptr].addr; + --stack_ptr; + continue; + } + int prim_addr = __float_as_int(leaf.x); #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h index 4d3028b37bf..ab4b70085e8 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume_all.h +++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h @@ -240,6 +240,14 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* If node is leaf, fetch triangle list. */ if(node_addr < 0) { float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1)); + + if((__float_as_uint(leaf.z) & visibility) == 0) { + /* Pop. */ + node_addr = traversal_stack[stack_ptr].addr; + --stack_ptr; + continue; + } + int prim_addr = __float_as_int(leaf.x); #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 86e1a7f317f..1e7fbdb5450 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -144,7 +144,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg, return label; } -#ifndef __KERNEL_CUDS__ +#ifndef __KERNEL_CUDA__ ccl_device #else ccl_device_inline diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h index 493afdc4f62..3605394f182 100644 --- a/intern/cycles/kernel/geom/geom.h +++ b/intern/cycles/kernel/geom/geom.h @@ -17,6 +17,9 @@ #include "geom_attribute.h" #include "geom_object.h" +#ifdef __PATCH_EVAL__ +# include "geom_patch.h" +#endif #include "geom_triangle.h" #include "geom_subd_triangle.h" #include "geom_triangle_intersect.h" diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h index 5d78cf8f9fc..08ccee56335 100644 --- a/intern/cycles/kernel/geom/geom_attribute.h +++ b/intern/cycles/kernel/geom/geom_attribute.h @@ -43,12 +43,19 @@ ccl_device_inline uint attribute_primitive_type(KernelGlobals *kg, const ShaderD } } +ccl_device_inline AttributeDescriptor attribute_not_found() +{ + const AttributeDescriptor desc = {ATTR_ELEMENT_NONE, (NodeAttributeType)0, 0, ATTR_STD_NOT_FOUND}; + return desc; +} + /* Find attribute based on ID */ -ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem) +ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id) { - if(ccl_fetch(sd, object) == PRIM_NONE) - return (int)ATTR_STD_NOT_FOUND; + if(ccl_fetch(sd, object) == PRIM_NONE) { + return attribute_not_found(); + } /* for SVM, find attribute by unique id */ uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride; @@ -57,31 +64,41 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, ui while(attr_map.x != id) { if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) { - return ATTR_STD_NOT_FOUND; + return attribute_not_found(); } attr_offset += ATTR_PRIM_TYPES; attr_map = kernel_tex_fetch(__attributes_map, attr_offset); } - *elem = (AttributeElement)attr_map.y; + AttributeDescriptor desc; + desc.element = (AttributeElement)attr_map.y; - if(ccl_fetch(sd, prim) == PRIM_NONE && (AttributeElement)attr_map.y != ATTR_ELEMENT_MESH) - return ATTR_STD_NOT_FOUND; + if(ccl_fetch(sd, prim) == PRIM_NONE && + desc.element != ATTR_ELEMENT_MESH && + desc.element != ATTR_ELEMENT_VOXEL && + desc.element != ATTR_ELEMENT_OBJECT) + { + return attribute_not_found(); + } /* return result */ - return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z; + desc.offset = (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z; + desc.type = (NodeAttributeType)(attr_map.w & 0xff); + desc.flags = (AttributeFlag)(attr_map.w >> 8); + + return desc; } /* Transform matrix attribute on meshes */ -ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderData *sd, int offset) +ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc) { Transform tfm; - tfm.x = kernel_tex_fetch(__attributes_float3, offset + 0); - tfm.y = kernel_tex_fetch(__attributes_float3, offset + 1); - tfm.z = kernel_tex_fetch(__attributes_float3, offset + 2); - tfm.w = kernel_tex_fetch(__attributes_float3, offset + 3); + tfm.x = kernel_tex_fetch(__attributes_float3, desc.offset + 0); + tfm.y = kernel_tex_fetch(__attributes_float3, desc.offset + 1); + tfm.z = kernel_tex_fetch(__attributes_float3, desc.offset + 2); + tfm.w = kernel_tex_fetch(__attributes_float3, desc.offset + 3); return tfm; } diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h index 292e1bfca0e..aa9cd295452 100644 --- a/intern/cycles/kernel/geom/geom_curve.h +++ b/intern/cycles/kernel/geom/geom_curve.h @@ -24,23 +24,23 @@ CCL_NAMESPACE_BEGIN /* Reading attributes on various curve elements */ -ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy) +ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy) { - if(elem == ATTR_ELEMENT_CURVE) { + if(desc.element == ATTR_ELEMENT_CURVE) { #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = 0.0f; if(dy) *dy = 0.0f; #endif - return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim)); + return kernel_tex_fetch(__attributes_float, desc.offset + ccl_fetch(sd, prim)); } - else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) { + else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) { float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim)); int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type)); int k1 = k0 + 1; - float f0 = kernel_tex_fetch(__attributes_float, offset + k0); - float f1 = kernel_tex_fetch(__attributes_float, offset + k1); + float f0 = kernel_tex_fetch(__attributes_float, desc.offset + k0); + float f1 = kernel_tex_fetch(__attributes_float, desc.offset + k1); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0); @@ -59,9 +59,9 @@ ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, } } -ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy) +ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy) { - if(elem == ATTR_ELEMENT_CURVE) { + if(desc.element == ATTR_ELEMENT_CURVE) { /* idea: we can't derive any useful differentials here, but for tiled * mipmap image caching it would be useful to avoid reading the highest * detail level always. maybe a derivative based on the hair density @@ -71,15 +71,15 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); #endif - return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim))); + return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + ccl_fetch(sd, prim))); } - else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) { + else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) { float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim)); int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type)); int k1 = k0 + 1; - float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0)); - float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k1)); + float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k0)); + float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k1)); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0); diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index c0d15a95954..883c5dc100d 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -292,6 +292,18 @@ ccl_device_inline void object_motion_info(KernelGlobals *kg, int object, int *nu *numverts = __float_as_int(f.w); } +/* Offset to an objects patch map */ + +ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object) +{ + if(object == OBJECT_NONE) + return 0; + + int offset = object*OBJECT_SIZE + 11; + float4 f = kernel_tex_fetch(__objects, offset); + return __float_as_uint(f.x); +} + /* Pass ID for shader */ ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd) diff --git a/intern/cycles/kernel/geom/geom_patch.h b/intern/cycles/kernel/geom/geom_patch.h new file mode 100644 index 00000000000..6a0ff5a4a04 --- /dev/null +++ b/intern/cycles/kernel/geom/geom_patch.h @@ -0,0 +1,343 @@ +/* + * Based on code from OpenSubdiv released under this license: + * + * Copyright 2013 Pixar + * + * Licensed under the Apache License, Version 2.0 (the "Apache License") + * with the following modification; you may not use this file except in + * compliance with the Apache License and the following modification to it: + * Section 6. Trademarks. is deleted and replaced with: + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor + * and its affiliates, except as required to comply with Section 4(c) of + * the License and to reproduce the content of the NOTICE file. + * + * You may obtain a copy of the Apache License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Apache License with the above modification is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the Apache License for the specific + * language governing permissions and limitations under the Apache License. + * + */ + +CCL_NAMESPACE_BEGIN + +typedef struct PatchHandle { + int array_index, patch_index, vert_index; +} PatchHandle; + +ccl_device_inline int patch_map_resolve_quadrant(float median, float *u, float *v) +{ + int quadrant = -1; + + if(*u < median) { + if(*v < median) { + quadrant = 0; + } + else { + quadrant = 1; + *v -= median; + } + } + else { + if(*v < median) { + quadrant = 3; + } + else { + quadrant = 2; + *v -= median; + } + *u -= median; + } + + return quadrant; +} + +/* retrieve PatchHandle from patch coords */ + +ccl_device_inline PatchHandle patch_map_find_patch(KernelGlobals *kg, int object, int patch, float u, float v) +{ + PatchHandle handle; + + kernel_assert((u >= 0.0f) && (u <= 1.0f) && (v >= 0.0f) && (v <= 1.0f)); + + int node = (object_patch_map_offset(kg, object) + patch)/2; + float median = 0.5f; + + for(int depth = 0; depth < 0xff; depth++) { + float delta = median * 0.5f; + + int quadrant = patch_map_resolve_quadrant(median, &u, &v); + kernel_assert(quadrant >= 0); + + uint child = kernel_tex_fetch(__patches, node + quadrant); + + /* is the quadrant a hole? */ + if(!(child & PATCH_MAP_NODE_IS_SET)) { + handle.array_index = -1; + return handle; + } + + uint index = child & PATCH_MAP_NODE_INDEX_MASK; + + if(child & PATCH_MAP_NODE_IS_LEAF) { + handle.array_index = kernel_tex_fetch(__patches, index + 0); + handle.patch_index = kernel_tex_fetch(__patches, index + 1); + handle.vert_index = kernel_tex_fetch(__patches, index + 2); + + return handle; + } else { + node = index; + } + + median = delta; + } + + /* no leaf found */ + kernel_assert(0); + + handle.array_index = -1; + return handle; +} + +ccl_device_inline void patch_eval_bspline_weights(float t, float *point, float *deriv) +{ + /* The four uniform cubic B-Spline basis functions evaluated at t */ + float inv_6 = 1.0f / 6.0f; + + float t2 = t * t; + float t3 = t * t2; + + point[0] = inv_6 * (1.0f - 3.0f*(t - t2) - t3); + point[1] = inv_6 * (4.0f - 6.0f*t2 + 3.0f*t3); + point[2] = inv_6 * (1.0f + 3.0f*(t + t2 - t3)); + point[3] = inv_6 * t3; + + /* Derivatives of the above four basis functions at t */ + deriv[0] = -0.5f*t2 + t - 0.5f; + deriv[1] = 1.5f*t2 - 2.0f*t; + deriv[2] = -1.5f*t2 + t + 0.5f; + deriv[3] = 0.5f*t2; +} + +ccl_device_inline void patch_eval_adjust_boundary_weights(uint bits, float *s, float *t) +{ + int boundary = ((bits >> 8) & 0xf); + + if(boundary & 1) { + t[2] -= t[0]; + t[1] += 2*t[0]; + t[0] = 0; + } + + if(boundary & 2) { + s[1] -= s[3]; + s[2] += 2*s[3]; + s[3] = 0; + } + + if(boundary & 4) { + t[1] -= t[3]; + t[2] += 2*t[3]; + t[3] = 0; + } + + if(boundary & 8) { + s[2] -= s[0]; + s[1] += 2*s[0]; + s[0] = 0; + } +} + +ccl_device_inline int patch_eval_depth(uint patch_bits) +{ + return (patch_bits & 0xf); +} + +ccl_device_inline float patch_eval_param_fraction(uint patch_bits) +{ + bool non_quad_root = (patch_bits >> 4) & 0x1; + int depth = patch_eval_depth(patch_bits); + + if(non_quad_root) { + return 1.0f / (float)(1 << (depth-1)); + } + else { + return 1.0f / (float)(1 << depth); + } +} + +ccl_device_inline void patch_eval_normalize_coords(uint patch_bits, float *u, float *v) +{ + float frac = patch_eval_param_fraction(patch_bits); + + int iu = (patch_bits >> 22) & 0x3ff; + int iv = (patch_bits >> 12) & 0x3ff; + + /* top left corner */ + float pu = (float)iu*frac; + float pv = (float)iv*frac; + + /* normalize uv coordinates */ + *u = (*u - pu) / frac; + *v = (*v - pv) / frac; +} + +/* retrieve patch control indices */ + +ccl_device_inline int patch_eval_indices(KernelGlobals *kg, const PatchHandle *handle, int channel, + int indices[PATCH_MAX_CONTROL_VERTS]) +{ + int index_base = kernel_tex_fetch(__patches, handle->array_index + 2) + handle->vert_index; + + /* XXX: regular patches only */ + for(int i = 0; i < 16; i++) { + indices[i] = kernel_tex_fetch(__patches, index_base + i); + } + + return 16; +} + +/* evaluate patch basis functions */ + +ccl_device_inline void patch_eval_basis(KernelGlobals *kg, const PatchHandle *handle, float u, float v, + float weights[PATCH_MAX_CONTROL_VERTS], + float weights_du[PATCH_MAX_CONTROL_VERTS], + float weights_dv[PATCH_MAX_CONTROL_VERTS]) +{ + uint patch_bits = kernel_tex_fetch(__patches, handle->patch_index + 1); /* read patch param */ + float d_scale = 1 << patch_eval_depth(patch_bits); + + bool non_quad_root = (patch_bits >> 4) & 0x1; + if(non_quad_root) { + d_scale *= 0.5f; + } + + patch_eval_normalize_coords(patch_bits, &u, &v); + + /* XXX: regular patches only for now. */ + + float s[4], t[4], ds[4], dt[4]; + + patch_eval_bspline_weights(u, s, ds); + patch_eval_bspline_weights(v, t, dt); + + patch_eval_adjust_boundary_weights(patch_bits, s, t); + patch_eval_adjust_boundary_weights(patch_bits, ds, dt); + + for(int k = 0; k < 4; k++) { + for(int l = 0; l < 4; l++) { + weights[4*k+l] = s[l] * t[k]; + weights_du[4*k+l] = ds[l] * t[k] * d_scale; + weights_dv[4*k+l] = s[l] * dt[k] * d_scale; + } + } +} + +/* generic function for evaluating indices and weights from patch coords */ + +ccl_device_inline int patch_eval_control_verts(KernelGlobals *kg, int object, int patch, float u, float v, int channel, + int indices[PATCH_MAX_CONTROL_VERTS], + float weights[PATCH_MAX_CONTROL_VERTS], + float weights_du[PATCH_MAX_CONTROL_VERTS], + float weights_dv[PATCH_MAX_CONTROL_VERTS]) +{ + PatchHandle handle = patch_map_find_patch(kg, object, patch, u, v); + kernel_assert(handle.array_index >= 0); + + int num_control = patch_eval_indices(kg, &handle, channel, indices); + patch_eval_basis(kg, &handle, u, v, weights, weights_du, weights_dv); + + return num_control; +} + +/* functions for evaluating attributes on patches */ + +ccl_device float patch_eval_float(KernelGlobals *kg, const ShaderData *sd, int offset, + int patch, float u, float v, int channel, + float *du, float* dv) +{ + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts(kg, ccl_fetch(sd, object), patch, u, v, channel, + indices, weights, weights_du, weights_dv); + + float val = 0.0f; + if(du) *du = 0.0f; + if(dv) *dv = 0.0f; + + for(int i = 0; i < num_control; i++) { + float v = kernel_tex_fetch(__attributes_float, offset + indices[i]); + + val += v * weights[i]; + if(du) *du += v * weights_du[i]; + if(dv) *dv += v * weights_dv[i]; + } + + return val; +} + +ccl_device float3 patch_eval_float3(KernelGlobals *kg, const ShaderData *sd, int offset, + int patch, float u, float v, int channel, + float3 *du, float3 *dv) +{ + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts(kg, ccl_fetch(sd, object), patch, u, v, channel, + indices, weights, weights_du, weights_dv); + + float3 val = make_float3(0.0f, 0.0f, 0.0f); + if(du) *du = make_float3(0.0f, 0.0f, 0.0f); + if(dv) *dv = make_float3(0.0f, 0.0f, 0.0f); + + for(int i = 0; i < num_control; i++) { + float3 v = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + indices[i])); + + val += v * weights[i]; + if(du) *du += v * weights_du[i]; + if(dv) *dv += v * weights_dv[i]; + } + + return val; +} + +ccl_device float3 patch_eval_uchar4(KernelGlobals *kg, const ShaderData *sd, int offset, + int patch, float u, float v, int channel, + float3 *du, float3 *dv) +{ + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts(kg, ccl_fetch(sd, object), patch, u, v, channel, + indices, weights, weights_du, weights_dv); + + float3 val = make_float3(0.0f, 0.0f, 0.0f); + if(du) *du = make_float3(0.0f, 0.0f, 0.0f); + if(dv) *dv = make_float3(0.0f, 0.0f, 0.0f); + + for(int i = 0; i < num_control; i++) { + float3 v = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, offset + indices[i])); + + val += v * weights[i]; + if(du) *du += v * weights_du[i]; + if(dv) *dv += v * weights_dv[i]; + } + + return val; +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h index b16f0c9a99b..4384c2093e9 100644 --- a/intern/cycles/kernel/geom/geom_primitive.h +++ b/intern/cycles/kernel/geom/geom_primitive.h @@ -25,24 +25,23 @@ CCL_NAMESPACE_BEGIN ccl_device_inline float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, - AttributeElement elem, - int offset, + const AttributeDescriptor desc, float *dx, float *dy) { if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) { if(subd_triangle_patch(kg, sd) == ~0) - return triangle_attribute_float(kg, sd, elem, offset, dx, dy); + return triangle_attribute_float(kg, sd, desc, dx, dy); else - return subd_triangle_attribute_float(kg, sd, elem, offset, dx, dy); + return subd_triangle_attribute_float(kg, sd, desc, dx, dy); } #ifdef __HAIR__ else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { - return curve_attribute_float(kg, sd, elem, offset, dx, dy); + return curve_attribute_float(kg, sd, desc, dx, dy); } #endif #ifdef __VOLUME__ - else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) { - return volume_attribute_float(kg, sd, elem, offset, dx, dy); + else if(ccl_fetch(sd, object) != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) { + return volume_attribute_float(kg, sd, desc, dx, dy); } #endif else { @@ -54,25 +53,23 @@ ccl_device_inline float primitive_attribute_float(KernelGlobals *kg, ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, - AttributeElement elem, - int offset, - float3 *dx, - float3 *dy) + const AttributeDescriptor desc, + float3 *dx, float3 *dy) { if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) { if(subd_triangle_patch(kg, sd) == ~0) - return triangle_attribute_float3(kg, sd, elem, offset, dx, dy); + return triangle_attribute_float3(kg, sd, desc, dx, dy); else - return subd_triangle_attribute_float3(kg, sd, elem, offset, dx, dy); + return subd_triangle_attribute_float3(kg, sd, desc, dx, dy); } #ifdef __HAIR__ else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { - return curve_attribute_float3(kg, sd, elem, offset, dx, dy); + return curve_attribute_float3(kg, sd, desc, dx, dy); } #endif #ifdef __VOLUME__ - else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) { - return volume_attribute_float3(kg, sd, elem, offset, dx, dy); + else if(ccl_fetch(sd, object) != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) { + return volume_attribute_float3(kg, sd, desc, dx, dy); } #endif else { @@ -86,13 +83,12 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg, ccl_device_inline float3 primitive_uv(KernelGlobals *kg, ShaderData *sd) { - AttributeElement elem_uv; - int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv); + const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_UV); - if(offset_uv == ATTR_STD_NOT_FOUND) + if(desc.offset == ATTR_STD_NOT_FOUND) return make_float3(0.0f, 0.0f, 0.0f); - float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL); + float3 uv = primitive_attribute_float3(kg, sd, desc, NULL, NULL); uv.z = 1.0f; return uv; } @@ -102,15 +98,14 @@ ccl_device_inline float3 primitive_uv(KernelGlobals *kg, ShaderData *sd) ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, int *face_id) { /* storing ptex data as attributes is not memory efficient but simple for tests */ - AttributeElement elem_face_id, elem_uv; - int offset_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID, &elem_face_id); - int offset_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV, &elem_uv); + const AttributeDescriptor desc_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID); + const AttributeDescriptor desc_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV); - if(offset_face_id == ATTR_STD_NOT_FOUND || offset_uv == ATTR_STD_NOT_FOUND) + if(desc_face_id.offset == ATTR_STD_NOT_FOUND || desc_uv.offset == ATTR_STD_NOT_FOUND) return false; - float3 uv3 = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL); - float face_id_f = primitive_attribute_float(kg, sd, elem_face_id, offset_face_id, NULL, NULL); + float3 uv3 = primitive_attribute_float3(kg, sd, desc_uv, NULL, NULL); + float face_id_f = primitive_attribute_float(kg, sd, desc_face_id, NULL, NULL); *uv = make_float2(uv3.x, uv3.y); *face_id = (int)face_id_f; @@ -132,11 +127,10 @@ ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd) #endif /* try to create spherical tangent from generated coordinates */ - AttributeElement attr_elem; - int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem); + const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED); - if(attr_offset != ATTR_STD_NOT_FOUND) { - float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); + if(desc.offset != ATTR_STD_NOT_FOUND) { + float3 data = primitive_attribute_float3(kg, sd, desc, NULL, NULL); data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); object_normal_transform(kg, sd, &data); return cross(ccl_fetch(sd, N), normalize(cross(data, ccl_fetch(sd, N)))); @@ -173,19 +167,18 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData * float3 motion_pre = center, motion_post = center; /* deformation motion */ - AttributeElement elem; - int offset = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION, &elem); + AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION); - if(offset != ATTR_STD_NOT_FOUND) { + if(desc.offset != ATTR_STD_NOT_FOUND) { /* get motion info */ int numverts, numkeys; object_motion_info(kg, ccl_fetch(sd, object), NULL, &numverts, &numkeys); /* lookup attributes */ - int offset_next = (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys; + motion_pre = primitive_attribute_float3(kg, sd, desc, NULL, NULL); - motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL); - motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL); + desc.offset += (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)? numverts: numkeys; + motion_post = primitive_attribute_float3(kg, sd, desc, NULL, NULL); #ifdef __HAIR__ if(is_curve_primitive && (ccl_fetch(sd, flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) { diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h index bf9be182345..647840dc696 100644 --- a/intern/cycles/kernel/geom/geom_subd_triangle.h +++ b/intern/cycles/kernel/geom/geom_subd_triangle.h @@ -97,36 +97,81 @@ ccl_device_inline void subd_triangle_patch_corners(KernelGlobals *kg, int patch, /* Reading attributes on various subdivision triangle elements */ -ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy) +ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy) { int patch = subd_triangle_patch(kg, sd); - if(elem == ATTR_ELEMENT_FACE) { +#ifdef __PATCH_EVAL__ + if(desc.flags & ATTR_SUBDIVIDED) { + float2 uv[3]; + subd_triangle_patch_uv(kg, sd, uv); + + float2 dpdu = uv[0] - uv[2]; + float2 dpdv = uv[1] - uv[2]; + + /* p is [s, t] */ + float2 p = dpdu * ccl_fetch(sd, u) + dpdv * ccl_fetch(sd, v) + uv[2]; + + float a, dads, dadt; + a = patch_eval_float(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + +#ifdef __RAY_DIFFERENTIALS__ + if(dx || dy) { + float dsdu = dpdu.x; + float dtdu = dpdu.y; + float dsdv = dpdv.x; + float dtdv = dpdv.y; + + if(dx) { + float dudx = ccl_fetch(sd, du).dx; + float dvdx = ccl_fetch(sd, dv).dx; + + float dsdx = dsdu*dudx + dsdv*dvdx; + float dtdx = dtdu*dudx + dtdv*dvdx; + + *dx = dads*dsdx + dadt*dtdx; + } + if(dy) { + float dudy = ccl_fetch(sd, du).dy; + float dvdy = ccl_fetch(sd, dv).dy; + + float dsdy = dsdu*dudy + dsdv*dvdy; + float dtdy = dtdu*dudy + dtdv*dvdy; + + *dy = dads*dsdy + dadt*dtdy; + } + } +#endif + + return a; + } + else +#endif /* __PATCH_EVAL__ */ + if(desc.element == ATTR_ELEMENT_FACE) { if(dx) *dx = 0.0f; if(dy) *dy = 0.0f; - return kernel_tex_fetch(__attributes_float, offset + subd_triangle_patch_face(kg, patch)); + return kernel_tex_fetch(__attributes_float, desc.offset + subd_triangle_patch_face(kg, patch)); } - else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) { + else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { float2 uv[3]; subd_triangle_patch_uv(kg, sd, uv); - uint4 v = subd_triangle_patch_indices(kg, patch); - float a, b, c; + uint4 v = subd_triangle_patch_indices(kg, patch); - float f0 = kernel_tex_fetch(__attributes_float, offset + v.x); - float f1 = kernel_tex_fetch(__attributes_float, offset + v.y); - float f2 = kernel_tex_fetch(__attributes_float, offset + v.z); - float f3 = kernel_tex_fetch(__attributes_float, offset + v.w); + float f0 = kernel_tex_fetch(__attributes_float, desc.offset + v.x); + float f1 = kernel_tex_fetch(__attributes_float, desc.offset + v.y); + float f2 = kernel_tex_fetch(__attributes_float, desc.offset + v.z); + float f3 = kernel_tex_fetch(__attributes_float, desc.offset + v.w); if(subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1+f0)*0.5f; f3 = (f3+f0)*0.5f; } - a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); - b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); - c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); + float a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); + float b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); + float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c; @@ -135,28 +180,26 @@ ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderDa return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c; } - else if(elem == ATTR_ELEMENT_CORNER) { - int corners[4]; - subd_triangle_patch_corners(kg, patch, corners); - + else if(desc.element == ATTR_ELEMENT_CORNER) { float2 uv[3]; subd_triangle_patch_uv(kg, sd, uv); - float a, b, c; + int corners[4]; + subd_triangle_patch_corners(kg, patch, corners); - float f0 = kernel_tex_fetch(__attributes_float, corners[0] + offset); - float f1 = kernel_tex_fetch(__attributes_float, corners[1] + offset); - float f2 = kernel_tex_fetch(__attributes_float, corners[2] + offset); - float f3 = kernel_tex_fetch(__attributes_float, corners[3] + offset); + float f0 = kernel_tex_fetch(__attributes_float, corners[0] + desc.offset); + float f1 = kernel_tex_fetch(__attributes_float, corners[1] + desc.offset); + float f2 = kernel_tex_fetch(__attributes_float, corners[2] + desc.offset); + float f3 = kernel_tex_fetch(__attributes_float, corners[3] + desc.offset); if(subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1+f0)*0.5f; f3 = (f3+f0)*0.5f; } - a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); - b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); - c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); + float a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); + float b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); + float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c; @@ -173,36 +216,87 @@ ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderDa } } -ccl_device float3 subd_triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy) +ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy) { int patch = subd_triangle_patch(kg, sd); - if(elem == ATTR_ELEMENT_FACE) { +#ifdef __PATCH_EVAL__ + if(desc.flags & ATTR_SUBDIVIDED) { + float2 uv[3]; + subd_triangle_patch_uv(kg, sd, uv); + + float2 dpdu = uv[0] - uv[2]; + float2 dpdv = uv[1] - uv[2]; + + /* p is [s, t] */ + float2 p = dpdu * ccl_fetch(sd, u) + dpdv * ccl_fetch(sd, v) + uv[2]; + + float3 a, dads, dadt; + + if(desc.element == ATTR_ELEMENT_CORNER_BYTE) { + a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + } + else { + a = patch_eval_float3(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + } + +#ifdef __RAY_DIFFERENTIALS__ + if(dx || dy) { + float dsdu = dpdu.x; + float dtdu = dpdu.y; + float dsdv = dpdv.x; + float dtdv = dpdv.y; + + if(dx) { + float dudx = ccl_fetch(sd, du).dx; + float dvdx = ccl_fetch(sd, dv).dx; + + float dsdx = dsdu*dudx + dsdv*dvdx; + float dtdx = dtdu*dudx + dtdv*dvdx; + + *dx = dads*dsdx + dadt*dtdx; + } + if(dy) { + float dudy = ccl_fetch(sd, du).dy; + float dvdy = ccl_fetch(sd, dv).dy; + + float dsdy = dsdu*dudy + dsdv*dvdy; + float dtdy = dtdu*dudy + dtdv*dvdy; + + *dy = dads*dsdy + dadt*dtdy; + } + } +#endif + + return a; + } + else +#endif /* __PATCH_EVAL__ */ + if(desc.element == ATTR_ELEMENT_FACE) { if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); - return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + subd_triangle_patch_face(kg, patch))); + return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + subd_triangle_patch_face(kg, patch))); } - else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) { + else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { float2 uv[3]; subd_triangle_patch_uv(kg, sd, uv); - uint4 v = subd_triangle_patch_indices(kg, patch); - float3 a, b, c; + uint4 v = subd_triangle_patch_indices(kg, patch); - float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.x)); - float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.y)); - float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.z)); - float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.w)); + float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.x)); + float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.y)); + float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.z)); + float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.w)); if(subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1+f0)*0.5f; f3 = (f3+f0)*0.5f; } - a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); - b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); - c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); + float3 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); + float3 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); + float3 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c; @@ -211,27 +305,26 @@ ccl_device float3 subd_triangle_attribute_float3(KernelGlobals *kg, const Shader return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c; } - else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) { - int corners[4]; - subd_triangle_patch_corners(kg, patch, corners); - + else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) { float2 uv[3]; subd_triangle_patch_uv(kg, sd, uv); - float3 a, b, c; + int corners[4]; + subd_triangle_patch_corners(kg, patch, corners); + float3 f0, f1, f2, f3; - if(elem == ATTR_ELEMENT_CORNER) { - f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + offset)); - f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + offset)); - f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + offset)); - f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + offset)); + if(desc.element == ATTR_ELEMENT_CORNER) { + f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset)); + f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset)); + f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset)); + f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset)); } else { - f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + offset)); - f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + offset)); - f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + offset)); - f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + offset)); + f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset)); + f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset)); + f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset)); + f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset)); } if(subd_triangle_patch_num_corners(kg, patch) != 4) { @@ -239,9 +332,9 @@ ccl_device float3 subd_triangle_attribute_float3(KernelGlobals *kg, const Shader f3 = (f3+f0)*0.5f; } - a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); - b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); - c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); + float3 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); + float3 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); + float3 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c; diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index 0c2351e1d1b..d3289d6572c 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -105,20 +105,20 @@ ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, ccl_addr_spa /* Reading attributes on various triangle elements */ -ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy) +ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy) { - if(elem == ATTR_ELEMENT_FACE) { + if(desc.element == ATTR_ELEMENT_FACE) { if(dx) *dx = 0.0f; if(dy) *dy = 0.0f; - return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim)); + return kernel_tex_fetch(__attributes_float, desc.offset + ccl_fetch(sd, prim)); } - else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) { + else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim)); - float f0 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.x); - float f1 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.y); - float f2 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.z); + float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x); + float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y); + float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2; @@ -127,8 +127,8 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2; } - else if(elem == ATTR_ELEMENT_CORNER) { - int tri = offset + ccl_fetch(sd, prim)*3; + else if(desc.element == ATTR_ELEMENT_CORNER) { + int tri = desc.offset + ccl_fetch(sd, prim)*3; float f0 = kernel_tex_fetch(__attributes_float, tri + 0); float f1 = kernel_tex_fetch(__attributes_float, tri + 1); float f2 = kernel_tex_fetch(__attributes_float, tri + 2); @@ -148,20 +148,20 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s } } -ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy) +ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy) { - if(elem == ATTR_ELEMENT_FACE) { + if(desc.element == ATTR_ELEMENT_FACE) { if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); - return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim))); + return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + ccl_fetch(sd, prim))); } - else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) { + else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim)); - float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x)); - float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y)); - float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z)); + float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x)); + float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y)); + float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z)); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2; @@ -170,11 +170,11 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2; } - else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) { - int tri = offset + ccl_fetch(sd, prim)*3; + else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) { + int tri = desc.offset + ccl_fetch(sd, prim)*3; float3 f0, f1, f2; - if(elem == ATTR_ELEMENT_CORNER) { + if(desc.element == ATTR_ELEMENT_CORNER) { f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h index 7c8182bc430..fd97a63efb5 100644 --- a/intern/cycles/kernel/geom/geom_volume.h +++ b/intern/cycles/kernel/geom/geom_volume.h @@ -50,36 +50,35 @@ ccl_device_inline float3 volume_normalized_position(KernelGlobals *kg, { /* todo: optimize this so it's just a single matrix multiplication when * possible (not motion blur), or perhaps even just translation + scale */ - AttributeElement attr_elem; - int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem); + const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM); object_inverse_position_transform(kg, sd, &P); - if(attr_offset != ATTR_STD_NOT_FOUND) { - Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset); + if(desc.offset != ATTR_STD_NOT_FOUND) { + Transform tfm = primitive_attribute_matrix(kg, sd, desc); P = transform_point(&tfm, P); } return P; } -ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int id, float *dx, float *dy) +ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy) { float3 P = volume_normalized_position(kg, sd, sd->P); #ifdef __KERNEL_GPU__ # if __CUDA_ARCH__ >= 300 - CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id); + CUtexObject tex = kernel_tex_fetch(__bindless_mapping, desc.offset); float f = kernel_tex_image_interp_3d_float(tex, P.x, P.y, P.z); - float4 r = make_float4(f, f, f, 1.0); + float4 r = make_float4(f, f, f, 1.0f); # else - float4 r = volume_image_texture_3d(id, P.x, P.y, P.z); + float4 r = volume_image_texture_3d(desc.offset, P.x, P.y, P.z); # endif #else float4 r; if(sd->flag & SD_VOLUME_CUBIC) - r = kernel_tex_image_interp_3d_ex(id, P.x, P.y, P.z, INTERPOLATION_CUBIC); + r = kernel_tex_image_interp_3d_ex(desc.offset, P.x, P.y, P.z, INTERPOLATION_CUBIC); else - r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z); + r = kernel_tex_image_interp_3d(desc.offset, P.x, P.y, P.z); #endif if(dx) *dx = 0.0f; @@ -88,22 +87,22 @@ ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, return average(float4_to_float3(r)); } -ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int id, float3 *dx, float3 *dy) +ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy) { float3 P = volume_normalized_position(kg, sd, sd->P); #ifdef __KERNEL_GPU__ # if __CUDA_ARCH__ >= 300 - CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id); + CUtexObject tex = kernel_tex_fetch(__bindless_mapping, desc.offset); float4 r = kernel_tex_image_interp_3d_float4(tex, P.x, P.y, P.z); # else - float4 r = volume_image_texture_3d(id, P.x, P.y, P.z); + float4 r = volume_image_texture_3d(desc.offset, P.x, P.y, P.z); # endif #else float4 r; if(sd->flag & SD_VOLUME_CUBIC) - r = kernel_tex_image_interp_3d_ex(id, P.x, P.y, P.z, INTERPOLATION_CUBIC); + r = kernel_tex_image_interp_3d_ex(desc.offset, P.x, P.y, P.z, INTERPOLATION_CUBIC); else - r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z); + r = kernel_tex_image_interp_3d(desc.offset, P.x, P.y, P.z); #endif if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index c882b477c35..7b30df04550 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -112,7 +112,7 @@ template<typename T> struct texture_image { ccl_always_inline float4 read(uchar r) { float f = r*(1.0f/255.0f); - return make_float4(f, f, f, 1.0); + return make_float4(f, f, f, 1.0f); } ccl_always_inline float4 read(float r) @@ -495,6 +495,7 @@ typedef texture<uint> texture_uint; typedef texture<int> texture_int; typedef texture<uint4> texture_uint4; typedef texture<uchar4> texture_uchar4; +typedef texture<uchar> texture_uchar; typedef texture_image<float> texture_image_float; typedef texture_image<uchar> texture_image_uchar; typedef texture_image<half> texture_image_half; diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h index a039b414006..9a96cb9f438 100644 --- a/intern/cycles/kernel/kernel_compat_cuda.h +++ b/intern/cycles/kernel/kernel_compat_cuda.h @@ -31,6 +31,7 @@ #endif #include <cuda.h> +#include <cuda_fp16.h> #include <float.h> /* Qualifier wrappers for different names on different devices */ @@ -47,6 +48,7 @@ #define ccl_may_alias #define ccl_addr_space #define ccl_restrict __restrict__ +#define ccl_align(n) __align__(n) /* No assert supported for CUDA */ @@ -65,6 +67,7 @@ typedef texture<float, 1> texture_float; typedef texture<uint, 1> texture_uint; typedef texture<int, 1> texture_int; typedef texture<uint4, 1> texture_uint4; +typedef texture<uchar, 1> texture_uchar; typedef texture<uchar4, 1> texture_uchar4; typedef texture<float4, 2> texture_image_float4; typedef texture<float4, 3> texture_image3d_float4; diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h index 8505cb85576..2ae89dde7c4 100644 --- a/intern/cycles/kernel/kernel_compat_opencl.h +++ b/intern/cycles/kernel/kernel_compat_opencl.h @@ -40,6 +40,7 @@ #define ccl_local __local #define ccl_private __private #define ccl_restrict restrict +#define ccl_align(n) __attribute__((aligned(n))) #ifdef __SPLIT_KERNEL__ # define ccl_addr_space __global diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index 64f1468eacf..e38c1a01f6b 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -112,7 +112,7 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba } kernel_path_indirect(kg, - indirect_sd, + indirect_sd, emission_sd, rng, &bsdf_ray, @@ -224,7 +224,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, kg, rng, &bssrdf_sd, - indirect_sd, + indirect_sd, emission_sd, throughput, num_samples_inv, diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index e0e35d792ab..661dc52fb31 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -45,9 +45,9 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, state->volume_bounce = 0; if(kernel_data.integrator.use_volumes) { - /* initialize volume stack with volume we are inside of */ - kernel_volume_stack_init(kg, stack_sd, ray, state->volume_stack); - /* seed RNG for cases where we can't use stratified samples */ + /* Initialize volume stack with volume we are inside of. */ + kernel_volume_stack_init(kg, stack_sd, state, ray, state->volume_stack); + /* Seed RNG for cases where we can't use stratified samples .*/ state->rng_congruential = lcg_init(*rng + sample*0x51633e2d); } else { diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 731dc0407c5..b534d9950c5 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -132,7 +132,13 @@ ccl_device_inline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, #endif } -ccl_device_inline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy) +/* Temporary workaround for Pascal cards, otherwise AA does not work properly. */ +#if defined(__KERNEL_GPU__) && __CUDA_ARCH__ >= 600 +__device__ __forceinline__ +#else +ccl_device_inline +#endif +void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy) { #ifdef __CMJ__ if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) { diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 98d321c9c16..079bea30bdd 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -149,7 +149,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg, /* ShaderData setup from BSSRDF scatter */ #ifdef __SUBSURFACE__ -# ifndef __KERNEL_CUDS__ +# ifndef __KERNEL_CUDA__ ccl_device # else ccl_device_inline @@ -539,7 +539,7 @@ ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg, #endif -#ifndef __KERNEL_CUDS__ +#ifndef __KERNEL_CUDA__ ccl_device #else ccl_device_inline diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index 4477a9f567a..ba45eea6388 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -86,7 +86,7 @@ ccl_device ShaderClosure *subsurface_scatter_pick_closure(KernelGlobals *kg, Sha } #ifndef __KERNEL_GPU__ -ccl_device +ccl_device_noinline #else ccl_device_inline #endif diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 7d6fec02331..8d5bb75a428 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -188,6 +188,8 @@ KERNEL_TEX(uint, texture_uint, __bindless_mapping) /* packed image (opencl) */ KERNEL_TEX(uchar4, texture_uchar4, __tex_image_byte4_packed) KERNEL_TEX(float4, texture_float4, __tex_image_float4_packed) +KERNEL_TEX(uchar, texture_uchar, __tex_image_byte_packed) +KERNEL_TEX(float, texture_float, __tex_image_float_packed) KERNEL_TEX(uint4, texture_uint4, __tex_image_packed_info) #undef KERNEL_TEX diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 18b5c35c768..0646148f6a0 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -19,6 +19,7 @@ #include "kernel_math.h" #include "svm/svm_types.h" +#include "util_static_assert.h" #ifndef __KERNEL_GPU__ # define __KERNEL_CPU__ @@ -34,7 +35,7 @@ CCL_NAMESPACE_BEGIN /* constants */ -#define OBJECT_SIZE 11 +#define OBJECT_SIZE 12 #define OBJECT_VECTOR_SIZE 6 #define LIGHT_SIZE 5 #define FILTER_TABLE_SIZE 1024 @@ -112,16 +113,7 @@ CCL_NAMESPACE_BEGIN # ifdef __KERNEL_OPENCL_AMD__ # define __CL_USE_NATIVE__ # define __KERNEL_SHADING__ -# define __MULTI_CLOSURE__ -# define __PASSES__ -# define __BACKGROUND_MIS__ -# define __LAMP_MIS__ -# define __AO__ -# define __CAMERA_MOTION__ -# define __OBJECT_MOTION__ -# define __HAIR__ -# define __BAKING__ -# define __TRANSPARENT_SHADOWS__ +# define __KERNEL_ADV_SHADING__ # endif /* __KERNEL_OPENCL_AMD__ */ # ifdef __KERNEL_OPENCL_INTEL_CPU__ @@ -147,6 +139,7 @@ CCL_NAMESPACE_BEGIN #define __CAMERA_CLIPPING__ #define __INTERSECTION_REFINE__ #define __CLAMP_SAMPLE__ +#define __PATCH_EVAL__ #ifdef __KERNEL_SHADING__ # define __SVM__ @@ -196,6 +189,9 @@ CCL_NAMESPACE_BEGIN #ifdef __NO_BRANCHED_PATH__ # undef __BRANCHED_PATH__ #endif +#ifdef __NO_PATCH_EVAL__ +# undef __PATCH_EVAL__ +#endif /* Random Numbers */ @@ -624,6 +620,18 @@ typedef enum AttributeStandard { ATTR_STD_NOT_FOUND = ~0 } AttributeStandard; +typedef enum AttributeFlag { + ATTR_FINAL_SIZE = (1 << 0), + ATTR_SUBDIVIDED = (1 << 1), +} AttributeFlag; + +typedef struct AttributeDescriptor { + AttributeElement element; + NodeAttributeType type; + uint flags; /* see enum AttributeFlag */ + int offset; +} AttributeDescriptor; + /* Closure data */ #ifdef __MULTI_CLOSURE__ @@ -644,23 +652,18 @@ typedef enum AttributeStandard { * ShaderClosure has a fixed size, and any extra space must be allocated * with closure_alloc_extra(). * - * float3 is 12 bytes on CUDA and 16 bytes on CPU/OpenCL, we set the data - * size to ensure ShaderClosure is 80 bytes total everywhere. */ + * We pad the struct to 80 bytes and ensure it is aligned to 16 bytes, which + * we assume to be the maximum required alignment for any struct. */ #define SHADER_CLOSURE_BASE \ float3 weight; \ ClosureType type; \ float sample_weight \ -typedef ccl_addr_space struct ShaderClosure { +typedef ccl_addr_space struct ccl_align(16) ShaderClosure { SHADER_CLOSURE_BASE; - /* pad to 80 bytes, data types are aligned to own size */ -#ifdef __KERNEL_CUDA__ - float data[15]; -#else - float data[14]; -#endif + float data[14]; /* pad to 80 bytes */ } ShaderClosure; /* Shader Context @@ -711,20 +714,21 @@ enum ShaderDataFlag { SD_VOLUME_MIS = (1 << 19), /* use multiple importance sampling */ SD_VOLUME_CUBIC = (1 << 20), /* use cubic interpolation for voxels */ SD_HAS_BUMP = (1 << 21), /* has data connected to the displacement input */ + SD_HAS_DISPLACEMENT = (1 << 22), /* has true displacement */ SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME| SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME| SD_HAS_BSSRDF_BUMP|SD_VOLUME_EQUIANGULAR|SD_VOLUME_MIS| - SD_VOLUME_CUBIC|SD_HAS_BUMP), + SD_VOLUME_CUBIC|SD_HAS_BUMP|SD_HAS_DISPLACEMENT), /* object flags */ - SD_HOLDOUT_MASK = (1 << 22), /* holdout for camera rays */ - SD_OBJECT_MOTION = (1 << 23), /* has object motion blur */ - SD_TRANSFORM_APPLIED = (1 << 24), /* vertices have transform applied */ - SD_NEGATIVE_SCALE_APPLIED = (1 << 25), /* vertices have negative scale applied */ - SD_OBJECT_HAS_VOLUME = (1 << 26), /* object has a volume shader */ - SD_OBJECT_INTERSECTS_VOLUME = (1 << 27), /* object intersects AABB of an object with volume shader */ - SD_OBJECT_HAS_VERTEX_MOTION = (1 << 28), /* has position for motion vertices */ + SD_HOLDOUT_MASK = (1 << 23), /* holdout for camera rays */ + SD_OBJECT_MOTION = (1 << 24), /* has object motion blur */ + SD_TRANSFORM_APPLIED = (1 << 25), /* vertices have transform applied */ + SD_NEGATIVE_SCALE_APPLIED = (1 << 26), /* vertices have negative scale applied */ + SD_OBJECT_HAS_VOLUME = (1 << 27), /* object has a volume shader */ + SD_OBJECT_INTERSECTS_VOLUME = (1 << 28), /* object intersects AABB of an object with volume shader */ + SD_OBJECT_HAS_VERTEX_MOTION = (1 << 29), /* has position for motion vertices */ SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED| SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME| @@ -733,9 +737,9 @@ enum ShaderDataFlag { #ifdef __SPLIT_KERNEL__ # define SD_THREAD (get_global_id(1) * get_global_size(0) + get_global_id(0)) -# if defined(__SPLIT_KERNEL_AOS__) +# if !defined(__SPLIT_KERNEL_SOA__) /* ShaderData is stored as an Array-of-Structures */ -# define ccl_soa_member(type, name) type soa_##name; +# define ccl_soa_member(type, name) type soa_##name # define ccl_fetch(s, t) (s[SD_THREAD].soa_##t) # define ccl_fetch_array(s, t, index) (&s[SD_THREAD].soa_##t[index]) # else @@ -743,7 +747,7 @@ enum ShaderDataFlag { # define SD_GLOBAL_SIZE (get_global_size(0) * get_global_size(1)) # define SD_FIELD_SIZE(t) sizeof(((struct ShaderData*)0)->t) # define SD_OFFSETOF(t) ((char*)(&((struct ShaderData*)0)->t) - (char*)0) -# define ccl_soa_member(type, name) type soa_##name; +# define ccl_soa_member(type, name) type soa_##name # define ccl_fetch(s, t) (((ShaderData*)((ccl_addr_space char*)s + SD_GLOBAL_SIZE * SD_OFFSETOF(soa_##t) + SD_FIELD_SIZE(soa_##t) * SD_THREAD - SD_OFFSETOF(soa_##t)))->soa_##t) # define ccl_fetch_array(s, t, index) (&ccl_fetch(s, t)[index]) # endif @@ -979,6 +983,7 @@ typedef struct KernelCamera { int pad; } KernelCamera; +static_assert_align(KernelCamera, 16); typedef struct KernelFilm { float exposure; @@ -1033,6 +1038,7 @@ typedef struct KernelFilm { int pass_pad3; #endif } KernelFilm; +static_assert_align(KernelFilm, 16); typedef struct KernelBackground { /* only shader index */ @@ -1046,6 +1052,7 @@ typedef struct KernelBackground { float ao_distance; float ao_pad1, ao_pad2; } KernelBackground; +static_assert_align(KernelBackground, 16); typedef struct KernelIntegrator { /* emission */ @@ -1113,8 +1120,10 @@ typedef struct KernelIntegrator { float volume_step_size; int volume_samples; - int pad; + int pad1; + int pad2; } KernelIntegrator; +static_assert_align(KernelIntegrator, 16); typedef struct KernelBVH { /* root node */ @@ -1126,6 +1135,7 @@ typedef struct KernelBVH { int use_qbvh; int pad1, pad2; } KernelBVH; +static_assert_align(KernelBVH, 16); typedef enum CurveFlag { /* runtime flags */ @@ -1145,11 +1155,13 @@ typedef struct KernelCurves { float minimum_width; float maximum_width; } KernelCurves; +static_assert_align(KernelCurves, 16); typedef struct KernelTables { int beckmann_offset; int pad1, pad2, pad3; } KernelTables; +static_assert_align(KernelTables, 16); typedef struct KernelData { KernelCamera cam; @@ -1160,8 +1172,12 @@ typedef struct KernelData { KernelCurves curve; KernelTables tables; } KernelData; +static_assert_align(KernelData, 16); #ifdef __KERNEL_DEBUG__ +/* NOTE: This is a runtime-only struct, alignment is not + * really important here. + */ typedef ccl_addr_space struct DebugData { // Total number of BVH node traversal steps and primitives intersections // for the camera rays. @@ -1239,6 +1255,16 @@ enum RayState { #define REMOVE_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] & (~flag))) #define IS_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] & flag) +/* Patches */ + +#define PATCH_MAX_CONTROL_VERTS 16 + +/* Patch map node flags */ + +#define PATCH_MAP_NODE_IS_SET (1 << 30) +#define PATCH_MAP_NODE_IS_LEAF (1u << 31) +#define PATCH_MAP_NODE_INDEX_MASK (~(PATCH_MAP_NODE_IS_SET | PATCH_MAP_NODE_IS_LEAF)) + CCL_NAMESPACE_END #endif /* __KERNEL_TYPES_H__ */ diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 9dafed9afd1..4ab51b81f13 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -1010,7 +1010,8 @@ ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneou ccl_device void kernel_volume_stack_init(KernelGlobals *kg, ShaderData *stack_sd, - Ray *ray, + const PathState *state, + const Ray *ray, VolumeStack *stack) { /* NULL ray happens in the baker, does it need proper initialization of @@ -1031,9 +1032,12 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg, return; } + kernel_assert(state->flag & PATH_RAY_CAMERA); + Ray volume_ray = *ray; volume_ray.t = FLT_MAX; + const uint visibility = (state->flag & PATH_RAY_ALL_VISIBILITY); int stack_index = 0, enclosed_index = 0; #ifdef __VOLUME_RECORD_ALL__ @@ -1042,7 +1046,7 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg, &volume_ray, hits, 2*VOLUME_STACK_SIZE, - PATH_RAY_ALL_VISIBILITY); + visibility); if(num_hits > 0) { int enclosed_volumes[VOLUME_STACK_SIZE]; Intersection *isect = hits; @@ -1091,7 +1095,7 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg, step < 2 * VOLUME_STACK_SIZE) { Intersection isect; - if(!scene_intersect_volume(kg, &volume_ray, &isect, PATH_RAY_ALL_VISIBILITY)) { + if(!scene_intersect_volume(kg, &volume_ray, &isect, visibility)) { break; } diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h index 47383140170..af68907a5c2 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h @@ -25,12 +25,12 @@ ccl_device float4 kernel_tex_image_interp_impl(KernelGlobals *kg, int tex, float { if(tex >= TEX_START_HALF_CPU) return kg->texture_half_images[tex - TEX_START_HALF_CPU].interp(x, y); - else if(tex >= TEX_START_HALF4_CPU) - return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp(x, y); else if(tex >= TEX_START_BYTE_CPU) return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp(x, y); else if(tex >= TEX_START_FLOAT_CPU) return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp(x, y); + else if(tex >= TEX_START_HALF4_CPU) + return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp(x, y); else if(tex >= TEX_START_BYTE4_CPU) return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp(x, y); else @@ -41,12 +41,12 @@ ccl_device float4 kernel_tex_image_interp_3d_impl(KernelGlobals *kg, int tex, fl { if(tex >= TEX_START_HALF_CPU) return kg->texture_half_images[tex - TEX_START_HALF_CPU].interp_3d(x, y, z); - else if(tex >= TEX_START_HALF4_CPU) - return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp_3d(x, y, z); else if(tex >= TEX_START_BYTE_CPU) return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp_3d(x, y, z); else if(tex >= TEX_START_FLOAT_CPU) return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp_3d(x, y, z); + else if(tex >= TEX_START_HALF4_CPU) + return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp_3d(x, y, z); else if(tex >= TEX_START_BYTE4_CPU) return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp_3d(x, y, z); else @@ -57,13 +57,13 @@ ccl_device float4 kernel_tex_image_interp_3d_impl(KernelGlobals *kg, int tex, fl ccl_device float4 kernel_tex_image_interp_3d_ex_impl(KernelGlobals *kg, int tex, float x, float y, float z, int interpolation) { if(tex >= TEX_START_HALF_CPU) - return kg->texture_half4_images[tex - TEX_START_HALF_CPU].interp_3d_ex(x, y, z, interpolation); - else if(tex >= TEX_START_HALF4_CPU) - return kg->texture_half_images[tex - TEX_START_HALF4_CPU].interp_3d_ex(x, y, z, interpolation); + return kg->texture_half_images[tex - TEX_START_HALF_CPU].interp_3d_ex(x, y, z, interpolation); else if(tex >= TEX_START_BYTE_CPU) return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp_3d_ex(x, y, z, interpolation); else if(tex >= TEX_START_FLOAT_CPU) return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp_3d_ex(x, y, z, interpolation); + else if(tex >= TEX_START_HALF4_CPU) + return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp_3d_ex(x, y, z, interpolation); else if(tex >= TEX_START_BYTE4_CPU) return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp_3d_ex(x, y, z, interpolation); else diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 916542ec628..65cb7ecc6b4 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -54,13 +54,13 @@ struct OSLGlobals { vector<OSL::ShaderGroupRef> surface_state; vector<OSL::ShaderGroupRef> volume_state; vector<OSL::ShaderGroupRef> displacement_state; + vector<OSL::ShaderGroupRef> bump_state; OSL::ShaderGroupRef background_state; /* attributes */ struct Attribute { TypeDesc type; - AttributeElement elem; - int offset; + AttributeDescriptor desc; ParamValue value; }; diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index caae24405f1..f61a9ec0fb1 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -93,6 +93,7 @@ ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices"); ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices"); ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices"); ustring OSLRenderServices::u_geom_name("geom:name"); +ustring OSLRenderServices::u_geom_undisplaced("geom:undisplaced"); ustring OSLRenderServices::u_is_smooth("geom:is_smooth"); #ifdef __HAIR__ ustring OSLRenderServices::u_is_curve("geom:is_curve"); @@ -127,8 +128,10 @@ OSLRenderServices::OSLRenderServices() OSLRenderServices::~OSLRenderServices() { - VLOG(2) << "OSL texture system stats:\n" - << osl_ts->getstats(); + if(osl_ts) { + VLOG(2) << "OSL texture system stats:\n" + << osl_ts->getstats(); + } #ifdef WITH_PTEX ptex_cache->release(); #endif @@ -554,13 +557,13 @@ static bool get_mesh_element_attribute(KernelGlobals *kg, const ShaderData *sd, attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { float3 fval[3]; - fval[0] = primitive_attribute_float3(kg, sd, attr.elem, attr.offset, + fval[0] = primitive_attribute_float3(kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); return set_attribute_float3(fval, type, derivatives, val); } else if(attr.type == TypeDesc::TypeFloat) { float fval[3]; - fval[0] = primitive_attribute_float(kg, sd, attr.elem, attr.offset, + fval[0] = primitive_attribute_float(kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); return set_attribute_float(fval, type, derivatives, val); } @@ -573,7 +576,7 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS const TypeDesc& type, bool derivatives, void *val) { if(attr.type == TypeDesc::TypeMatrix) { - Transform tfm = primitive_attribute_matrix(kg, sd, attr.offset); + Transform tfm = primitive_attribute_matrix(kg, sd, attr.desc); return set_attribute_matrix(tfm, type, val); } else { @@ -815,7 +818,7 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring if(it != attribute_map.end()) { const OSLGlobals::Attribute& attr = it->second; - if(attr.elem != ATTR_ELEMENT_OBJECT) { + if(attr.desc.element != ATTR_ELEMENT_OBJECT) { /* triangle and vertex attributes */ if(get_mesh_element_attribute(kg, sd, attr, type, derivatives, val)) return true; diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 2701abb483c..0f2e02c62b0 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -158,6 +158,7 @@ public: static ustring u_geom_trianglevertices; static ustring u_geom_polyvertices; static ustring u_geom_name; + static ustring u_geom_undisplaced; static ustring u_is_smooth; static ustring u_is_curve; static ustring u_curve_thickness; diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index de02ec8f691..0d762bbdb38 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -184,6 +184,48 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state OSL::ShadingContext *octx = tdata->context[(int)ctx]; int shader = sd->shader & SHADER_MASK; + /* automatic bump shader */ + if(kg->osl->bump_state[shader]) { + /* save state */ + float3 P = sd->P; + float3 dPdx = sd->dP.dx; + float3 dPdy = sd->dP.dy; + + /* set state as if undisplaced */ + if(sd->flag & SD_HAS_DISPLACEMENT) { + float data[9]; + bool found = kg->osl->services->get_attribute(sd, true, OSLRenderServices::u_empty, TypeDesc::TypeVector, + OSLRenderServices::u_geom_undisplaced, data); + (void)found; + assert(found); + + memcpy(&sd->P, data, sizeof(float)*3); + memcpy(&sd->dP.dx, data+3, sizeof(float)*3); + memcpy(&sd->dP.dy, data+6, sizeof(float)*3); + + object_position_transform(kg, sd, &sd->P); + object_dir_transform(kg, sd, &sd->dP.dx); + object_dir_transform(kg, sd, &sd->dP.dy); + + globals->P = TO_VEC3(sd->P); + globals->dPdx = TO_VEC3(sd->dP.dx); + globals->dPdy = TO_VEC3(sd->dP.dy); + } + + /* execute bump shader */ + ss->execute(octx, *(kg->osl->bump_state[shader]), *globals); + + /* reset state */ + sd->P = P; + sd->dP.dx = dPdx; + sd->dP.dy = dPdy; + + globals->P = TO_VEC3(P); + globals->dPdx = TO_VEC3(dPdx); + globals->dPdy = TO_VEC3(dPdy); + } + + /* surface shader */ if(kg->osl->surface_state[shader]) { ss->execute(octx, *(kg->osl->surface_state[shader]), *globals); } @@ -334,7 +376,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderConte /* Attributes */ -int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem) +int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeDescriptor *desc) { /* for OSL, a hash map is used to lookup the attribute by name. */ int object = sd->object*ATTR_PRIM_TYPES; @@ -348,16 +390,23 @@ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, if(it != attr_map.end()) { const OSLGlobals::Attribute &osl_attr = it->second; - *elem = osl_attr.elem; + *desc = osl_attr.desc; - if(sd->prim == PRIM_NONE && (AttributeElement)osl_attr.elem != ATTR_ELEMENT_MESH) + if(sd->prim == PRIM_NONE && (AttributeElement)osl_attr.desc.element != ATTR_ELEMENT_MESH) { + desc->offset = ATTR_STD_NOT_FOUND; return ATTR_STD_NOT_FOUND; + } /* return result */ - return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset; + if(osl_attr.desc.element == ATTR_ELEMENT_NONE) { + desc->offset = ATTR_STD_NOT_FOUND; + } + return desc->offset; } - else + else { + desc->offset = ATTR_STD_NOT_FOUND; return (int)ATTR_STD_NOT_FOUND; + } } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index a185b8b8c05..ad06dd6929d 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -59,7 +59,7 @@ public: static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx); /* attributes */ - static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem); + static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeDescriptor *desc); }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl index f95e9fcfe3c..41bcac4fb10 100644 --- a/intern/cycles/kernel/shaders/node_normal_map.osl +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -26,6 +26,7 @@ shader node_normal_map( output normal Normal = NormalIn) { color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5); + int is_backfacing = backfacing(); if (space == "tangent") { vector tangent; @@ -34,9 +35,15 @@ shader node_normal_map( float is_smooth; getattribute("geom:is_smooth", is_smooth); - if (!is_smooth) + if (!is_smooth) { ninterp = normalize(transform("world", "object", Ng)); + /* the normal is already inverted, which is too soon for the math here */ + if (is_backfacing) { + ninterp = -ninterp; + } + } + // get _unnormalized_ interpolated normal and tangent if (getattribute(attr_name, tangent) && getattribute(attr_sign_name, tangent_sign) && @@ -73,7 +80,12 @@ shader node_normal_map( Normal = normalize(vector(mcolor)); } - + + /* invert normal for backfacing polygons */ + if (is_backfacing) { + Normal = -Normal; + } + if (Strength != 1.0) Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0)); } diff --git a/intern/cycles/kernel/shaders/node_rgb_curves.osl b/intern/cycles/kernel/shaders/node_rgb_curves.osl index c8e7e4f175b..984b7d47e8f 100644 --- a/intern/cycles/kernel/shaders/node_rgb_curves.osl +++ b/intern/cycles/kernel/shaders/node_rgb_curves.osl @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "stdosl.h" #include "node_ramp_util.h" shader node_rgb_curves( diff --git a/intern/cycles/kernel/shaders/node_rgb_ramp.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl index 24b8728b999..4e7d8fdcf65 100644 --- a/intern/cycles/kernel/shaders/node_rgb_ramp.osl +++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "stdosl.h" #include "node_ramp_util.h" shader node_rgb_ramp( diff --git a/intern/cycles/kernel/shaders/node_vector_curves.osl b/intern/cycles/kernel/shaders/node_vector_curves.osl index d92fa11d439..ff284c48e0a 100644 --- a/intern/cycles/kernel/shaders/node_vector_curves.osl +++ b/intern/cycles/kernel/shaders/node_vector_curves.osl @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "stdosl.h" #include "node_ramp_util.h" shader node_vector_curves( diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 502994e71f1..998a32e3181 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -181,6 +181,7 @@ CCL_NAMESPACE_END #include "svm_brick.h" #include "svm_vector_transform.h" #include "svm_voxel.h" +#include "svm_bump.h" CCL_NAMESPACE_BEGIN @@ -294,6 +295,12 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a case NODE_CLOSURE_SET_NORMAL: svm_node_set_normal(kg, sd, stack, node.y, node.z); break; + case NODE_ENTER_BUMP_EVAL: + svm_node_enter_bump_eval(kg, sd, stack, node.y); + break; + case NODE_LEAVE_BUMP_EVAL: + svm_node_leave_bump_eval(kg, sd, stack, node.y); + break; # endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */ case NODE_HSV: svm_node_hsv(kg, sd, stack, node, &offset); diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h index bd6013e9205..0e55c99ae97 100644 --- a/intern/cycles/kernel/svm/svm_attribute.h +++ b/intern/cycles/kernel/svm/svm_attribute.h @@ -18,117 +18,101 @@ CCL_NAMESPACE_BEGIN /* Attribute Node */ -ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd, +ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeType *type, - NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset) + uint *out_offset) { *out_offset = node.z; *type = (NodeAttributeType)node.w; + + AttributeDescriptor desc; + if(ccl_fetch(sd, object) != OBJECT_NONE) { - /* find attribute by unique id */ - uint id = node.y; - uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride; - attr_offset += attribute_primitive_type(kg, sd); - uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); - - while(attr_map.x != id) { - if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) { - *elem = ATTR_ELEMENT_NONE; - *offset = 0; - *mesh_type = (NodeAttributeType)node.w; - return; - } - attr_offset += ATTR_PRIM_TYPES; - attr_map = kernel_tex_fetch(__attributes_map, attr_offset); + desc = find_attribute(kg, sd, node.y); + if(desc.offset == ATTR_STD_NOT_FOUND) { + desc = attribute_not_found(); + desc.offset = 0; + desc.type = (NodeAttributeType)node.w; } - - /* return result */ - *elem = (AttributeElement)attr_map.y; - *offset = as_int(attr_map.z); - *mesh_type = (NodeAttributeType)attr_map.w; } else { /* background */ - *elem = ATTR_ELEMENT_NONE; - *offset = 0; - *mesh_type = (NodeAttributeType)node.w; + desc = attribute_not_found(); + desc.offset = 0; + desc.type = (NodeAttributeType)node.w; } + + return desc; } ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { - NodeAttributeType type, mesh_type; - AttributeElement elem; + NodeAttributeType type; uint out_offset; - int offset; - - svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset); + AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset); /* fetch and store attribute */ if(type == NODE_ATTR_FLOAT) { - if(mesh_type == NODE_ATTR_FLOAT) { - float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL); + if(desc.type == NODE_ATTR_FLOAT) { + float f = primitive_attribute_float(kg, sd, desc, NULL, NULL); stack_store_float(stack, out_offset, f); } else { - float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL); + float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL); stack_store_float(stack, out_offset, average(f)); } } else { - if(mesh_type == NODE_ATTR_FLOAT3) { - float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL); + if(desc.type == NODE_ATTR_FLOAT3) { + float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL); stack_store_float3(stack, out_offset, f); } else { - float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL); + float f = primitive_attribute_float(kg, sd, desc, NULL, NULL); stack_store_float3(stack, out_offset, make_float3(f, f, f)); } } } -#ifndef __KERNEL_CUDS__ +#ifndef __KERNEL_CUDA__ ccl_device #else ccl_device_noinline #endif void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { - NodeAttributeType type, mesh_type; - AttributeElement elem; + NodeAttributeType type; uint out_offset; - int offset; - - svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset); + AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset); /* fetch and store attribute */ if(type == NODE_ATTR_FLOAT) { - if(mesh_type == NODE_ATTR_FLOAT) { + if(desc.type == NODE_ATTR_FLOAT) { float dx; - float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL); + float f = primitive_attribute_float(kg, sd, desc, &dx, NULL); stack_store_float(stack, out_offset, f+dx); } else { float3 dx; - float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL); + float3 f = primitive_attribute_float3(kg, sd, desc, &dx, NULL); stack_store_float(stack, out_offset, average(f+dx)); } } else { - if(mesh_type == NODE_ATTR_FLOAT3) { + if(desc.type == NODE_ATTR_FLOAT3) { float3 dx; - float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL); + float3 f = primitive_attribute_float3(kg, sd, desc, &dx, NULL); stack_store_float3(stack, out_offset, f+dx); } else { float dx; - float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL); + float f = primitive_attribute_float(kg, sd, desc, &dx, NULL); stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx)); } } } -#ifndef __KERNEL_CUDS__ +#ifndef __KERNEL_CUDA__ ccl_device #else ccl_device_noinline @@ -138,35 +122,32 @@ void svm_node_attr_bump_dy(KernelGlobals *kg, float *stack, uint4 node) { - NodeAttributeType type, mesh_type; - AttributeElement elem; + NodeAttributeType type; uint out_offset; - int offset; - - svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset); + AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset); /* fetch and store attribute */ if(type == NODE_ATTR_FLOAT) { - if(mesh_type == NODE_ATTR_FLOAT) { + if(desc.type == NODE_ATTR_FLOAT) { float dy; - float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy); + float f = primitive_attribute_float(kg, sd, desc, NULL, &dy); stack_store_float(stack, out_offset, f+dy); } else { float3 dy; - float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy); + float3 f = primitive_attribute_float3(kg, sd, desc, NULL, &dy); stack_store_float(stack, out_offset, average(f+dy)); } } else { - if(mesh_type == NODE_ATTR_FLOAT3) { + if(desc.type == NODE_ATTR_FLOAT3) { float3 dy; - float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy); + float3 f = primitive_attribute_float3(kg, sd, desc, NULL, &dy); stack_store_float3(stack, out_offset, f+dy); } else { float dy; - float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy); + float f = primitive_attribute_float(kg, sd, desc, NULL, &dy); stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy)); } } diff --git a/intern/cycles/kernel/svm/svm_bump.h b/intern/cycles/kernel/svm/svm_bump.h new file mode 100644 index 00000000000..04a8c7b64e5 --- /dev/null +++ b/intern/cycles/kernel/svm/svm_bump.h @@ -0,0 +1,54 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + +/* Bump Eval Nodes */ + +ccl_device void svm_node_enter_bump_eval(KernelGlobals *kg, ShaderData *sd, float *stack, uint offset) +{ + /* save state */ + stack_store_float3(stack, offset+0, ccl_fetch(sd, P)); + stack_store_float3(stack, offset+3, ccl_fetch(sd, dP).dx); + stack_store_float3(stack, offset+6, ccl_fetch(sd, dP).dy); + + /* set state as if undisplaced */ + const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED); + + if(desc.offset != ATTR_STD_NOT_FOUND) { + float3 P, dPdx, dPdy; + P = primitive_attribute_float3(kg, sd, desc, &dPdx, &dPdy); + + object_position_transform(kg, sd, &P); + object_dir_transform(kg, sd, &dPdx); + object_dir_transform(kg, sd, &dPdy); + + ccl_fetch(sd, P) = P; + ccl_fetch(sd, dP).dx = dPdx; + ccl_fetch(sd, dP).dy = dPdy; + } +} + +ccl_device void svm_node_leave_bump_eval(KernelGlobals *kg, ShaderData *sd, float *stack, uint offset) +{ + /* restore state */ + ccl_fetch(sd, P) = stack_load_float3(stack, offset+0); + ccl_fetch(sd, dP).dx = stack_load_float3(stack, offset+3); + ccl_fetch(sd, dP).dy = stack_load_float3(stack, offset+6); +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index b6b90dfff81..378ce650129 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -18,7 +18,7 @@ CCL_NAMESPACE_BEGIN /* Float4 textures on various devices. */ #if defined(__KERNEL_CPU__) -# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CPU +# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CPU #elif defined(__KERNEL_CUDA__) # if __CUDA_ARCH__ < 300 # define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CUDA @@ -36,13 +36,26 @@ CCL_NAMESPACE_BEGIN ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg, int id, int offset) { - if(id >= TEX_NUM_FLOAT4_IMAGES) { + /* Float4 */ + if(id < TEX_START_BYTE4_OPENCL) { + return kernel_tex_fetch(__tex_image_float4_packed, offset); + } + /* Byte4 */ + else if(id < TEX_START_FLOAT_OPENCL) { uchar4 r = kernel_tex_fetch(__tex_image_byte4_packed, offset); float f = 1.0f/255.0f; return make_float4(r.x*f, r.y*f, r.z*f, r.w*f); } + /* Float */ + else if(id < TEX_START_BYTE_OPENCL) { + float f = kernel_tex_fetch(__tex_image_float_packed, offset); + return make_float4(f, f, f, 1.0f); + } + /* Byte */ else { - return kernel_tex_fetch(__tex_image_float4_packed, offset); + uchar r = kernel_tex_fetch(__tex_image_byte_packed, offset); + float f = r * (1.0f/255.0f); + return make_float4(f, f, f, 1.0f); } } @@ -277,11 +290,13 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, } # else CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id); - if(id < 2048) /* TODO(dingto): Make this a variable */ + /* float4, byte4 and half4 */ + if(id < TEX_START_FLOAT_CUDA_KEPLER) r = kernel_tex_image_interp_float4(tex, x, y); + /* float, byte and half */ else { float f = kernel_tex_image_interp_float(tex, x, y); - r = make_float4(f, f, f, 1.0); + r = make_float4(f, f, f, 1.0f); } # endif #endif diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index 3f7d18a02fe..6d13a0d8e02 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -32,21 +32,17 @@ ccl_device void svm_vector_math(float *Fac, float3 *Vector, NodeVectorMath type, *Fac = average_fac(*Vector); } else if(type == NODE_VECTOR_MATH_AVERAGE) { - *Fac = len(Vector1 + Vector2); - *Vector = normalize(Vector1 + Vector2); + *Vector = safe_normalize_len(Vector1 + Vector2, Fac); } else if(type == NODE_VECTOR_MATH_DOT_PRODUCT) { *Fac = dot(Vector1, Vector2); *Vector = make_float3(0.0f, 0.0f, 0.0f); } else if(type == NODE_VECTOR_MATH_CROSS_PRODUCT) { - float3 c = cross(Vector1, Vector2); - *Fac = len(c); - *Vector = normalize(c); + *Vector = safe_normalize_len(cross(Vector1, Vector2), Fac); } else if(type == NODE_VECTOR_MATH_NORMALIZE) { - *Fac = len(Vector1); - *Vector = normalize(Vector1); + *Vector = safe_normalize_len(Vector1, Fac); } else { *Fac = 0.0f; diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index b39d6a3e009..6ea2539c543 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -277,6 +277,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st float3 color = stack_load_float3(stack, color_offset); color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f); + bool is_backfacing = (ccl_fetch(sd, flag) & SD_BACKFACING) != 0; float3 N; if(space == NODE_NORMAL_MAP_TANGENT) { @@ -287,26 +288,31 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st } /* first try to get tangent attribute */ - AttributeElement attr_elem, attr_sign_elem, attr_normal_elem; - int attr_offset = find_attribute(kg, sd, node.z, &attr_elem); - int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem); - int attr_normal_offset = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL, &attr_normal_elem); + const AttributeDescriptor attr = find_attribute(kg, sd, node.z); + const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w); + const AttributeDescriptor attr_normal = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL); - if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND || attr_normal_offset == ATTR_STD_NOT_FOUND) { + if(attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND || attr_normal.offset == ATTR_STD_NOT_FOUND) { stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); return; } /* get _unnormalized_ interpolated normal and tangent */ - float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); - float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL); + float3 tangent = primitive_attribute_float3(kg, sd, attr, NULL, NULL); + float sign = primitive_attribute_float(kg, sd, attr_sign, NULL, NULL); float3 normal; if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) { - normal = primitive_attribute_float3(kg, sd, attr_normal_elem, attr_normal_offset, NULL, NULL); + normal = primitive_attribute_float3(kg, sd, attr_normal, NULL, NULL); } else { normal = ccl_fetch(sd, Ng); + + /* the normal is already inverted, which is too soon for the math here */ + if(is_backfacing) { + normal = -normal; + } + object_inverse_normal_transform(kg, sd, &normal); } @@ -333,6 +339,11 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st N = safe_normalize(N); } + /* invert normal for backfacing polygons */ + if(is_backfacing) { + N = -N; + } + float strength = stack_load_float(stack, strength_offset); if(strength != 1.0f) { @@ -356,24 +367,22 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack if(direction_type == NODE_TANGENT_UVMAP) { /* UV map */ - AttributeElement attr_elem; - int attr_offset = find_attribute(kg, sd, node.z, &attr_elem); + const AttributeDescriptor desc = find_attribute(kg, sd, node.z); - if(attr_offset == ATTR_STD_NOT_FOUND) + if(desc.offset == ATTR_STD_NOT_FOUND) tangent = make_float3(0.0f, 0.0f, 0.0f); else - tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); + tangent = primitive_attribute_float3(kg, sd, desc, NULL, NULL); } else { /* radial */ - AttributeElement attr_elem; - int attr_offset = find_attribute(kg, sd, node.z, &attr_elem); + const AttributeDescriptor desc = find_attribute(kg, sd, node.z); float3 generated; - if(attr_offset == ATTR_STD_NOT_FOUND) + if(desc.offset == ATTR_STD_NOT_FOUND) generated = ccl_fetch(sd, P); else - generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); + generated = primitive_attribute_float3(kg, sd, desc, NULL, NULL); if(axis == NODE_TANGENT_AXIS_X) tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f)); diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 51083c31708..9cfa8395b85 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -26,6 +26,8 @@ CCL_NAMESPACE_BEGIN /* SVM stack offsets with this value indicate that it's not on the stack */ #define SVM_STACK_INVALID 255 +#define SVM_BUMP_EVAL_STATE_SIZE 9 + /* Nodes */ /* Known frequencies of used nodes, used for selective nodes compilation @@ -127,6 +129,8 @@ typedef enum ShaderNodeType { NODE_HAIR_INFO, NODE_UVMAP, NODE_TEX_VOXEL, + NODE_ENTER_BUMP_EVAL, + NODE_LEAVE_BUMP_EVAL, } ShaderNodeType; typedef enum NodeAttributeType { @@ -374,7 +378,8 @@ typedef enum NodeTexVoxelSpace { typedef enum ShaderType { SHADER_TYPE_SURFACE, SHADER_TYPE_VOLUME, - SHADER_TYPE_DISPLACEMENT + SHADER_TYPE_DISPLACEMENT, + SHADER_TYPE_BUMP, } ShaderType; /* Closure */ diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h index d2cc2c3730e..f54f4e8e888 100644 --- a/intern/cycles/kernel/svm/svm_voxel.h +++ b/intern/cycles/kernel/svm/svm_voxel.h @@ -50,7 +50,7 @@ ccl_device void svm_node_tex_voxel(KernelGlobals *kg, r = kernel_tex_image_interp_3d_float4(tex, co.x, co.y, co.z); else { float f = kernel_tex_image_interp_3d_float(tex, co.x, co.y, co.z); - r = make_float4(f, f, f, 1.0); + r = make_float4(f, f, f, 1.0f); } # else /* __CUDA_ARCH__ >= 300 */ r = volume_image_texture_3d(id, co.x, co.y, co.z); diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index e8ff81fe08e..c0d429a583c 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -44,6 +44,7 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_) type = type_; element = element_; std = ATTR_STD_NONE; + flags = 0; /* string and matrix not supported! */ assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor || @@ -61,6 +62,11 @@ void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only) } } +void Attribute::resize(size_t num_elements) +{ + buffer.resize(num_elements * data_sizeof(), 0); +} + void Attribute::add(const float& f) { char *data = (char*)&f; @@ -130,6 +136,10 @@ size_t Attribute::data_sizeof() const size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const { + if(flags & ATTR_FINAL_SIZE) { + return buffer.size() / data_sizeof(); + } + size_t size; switch(element) { @@ -517,16 +527,19 @@ AttributeRequest::AttributeRequest(ustring name_) std = ATTR_STD_NONE; triangle_type = TypeDesc::TypeFloat; - triangle_element = ATTR_ELEMENT_NONE; - triangle_offset = 0; + triangle_desc.element = ATTR_ELEMENT_NONE; + triangle_desc.offset = 0; + triangle_desc.type = NODE_ATTR_FLOAT; curve_type = TypeDesc::TypeFloat; - curve_element = ATTR_ELEMENT_NONE; - curve_offset = 0; + curve_desc.element = ATTR_ELEMENT_NONE; + curve_desc.offset = 0; + curve_desc.type = NODE_ATTR_FLOAT; subd_type = TypeDesc::TypeFloat; - subd_element = ATTR_ELEMENT_NONE; - subd_offset = 0; + subd_desc.element = ATTR_ELEMENT_NONE; + subd_desc.offset = 0; + subd_desc.type = NODE_ATTR_FLOAT; } AttributeRequest::AttributeRequest(AttributeStandard std_) @@ -535,16 +548,19 @@ AttributeRequest::AttributeRequest(AttributeStandard std_) std = std_; triangle_type = TypeDesc::TypeFloat; - triangle_element = ATTR_ELEMENT_NONE; - triangle_offset = 0; + triangle_desc.element = ATTR_ELEMENT_NONE; + triangle_desc.offset = 0; + triangle_desc.type = NODE_ATTR_FLOAT; curve_type = TypeDesc::TypeFloat; - curve_element = ATTR_ELEMENT_NONE; - curve_offset = 0; + curve_desc.element = ATTR_ELEMENT_NONE; + curve_desc.offset = 0; + curve_desc.type = NODE_ATTR_FLOAT; subd_type = TypeDesc::TypeFloat; - subd_element = ATTR_ELEMENT_NONE; - subd_offset = 0; + subd_desc.element = ATTR_ELEMENT_NONE; + subd_desc.offset = 0; + subd_desc.type = NODE_ATTR_FLOAT; } /* AttributeRequestSet */ diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index e51bdf28d66..f4538c76369 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -54,11 +54,13 @@ public: TypeDesc type; vector<char> buffer; AttributeElement element; + uint flags; /* enum AttributeFlag */ Attribute() {} ~Attribute(); void set(ustring name, TypeDesc type, AttributeElement element); void resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only); + void resize(size_t num_elements); size_t data_sizeof() const; size_t element_size(Mesh *mesh, AttributePrimitive prim) const; @@ -135,8 +137,7 @@ public: /* temporary variables used by MeshManager */ TypeDesc triangle_type, curve_type, subd_type; - AttributeElement triangle_element, curve_element, subd_element; - int triangle_offset, curve_offset, subd_offset; + AttributeDescriptor triangle_desc, curve_desc, subd_desc; explicit AttributeRequest(ustring name_); explicit AttributeRequest(AttributeStandard std); diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 6e795ef896a..57256ceecd3 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -856,27 +856,8 @@ void ShaderGraph::bump_from_displacement() /* connect the bump out to the set normal in: */ connect(bump->output("Normal"), set_normal->input("Direction")); - /* connect bump output to normal input nodes that aren't set yet. actually - * this will only set the normal input to the geometry node that we created - * and connected to all other normal inputs already. */ - foreach(ShaderNode *node, nodes) { - /* Don't connect normal to the bump node we're coming from, - * otherwise it'll be a cycle in graph. - */ - if(node == bump) { - continue; - } - foreach(ShaderInput *input, node->inputs) { - if(!input->link && (input->flags() & SocketType::LINK_NORMAL)) - connect(set_normal->output("Normal"), input); - } - } - - /* for displacement bump, clear the normal input in case the above loop - * connected the setnormal out to the bump normalin */ - ShaderInput *bump_normal_in = bump->input("Normal"); - if(bump_normal_in) - bump_normal_in->link = NULL; + /* connect to output node */ + connect(set_normal->output("Normal"), output()->input("Normal")); /* finally, add the copied nodes to the graph. we can't do this earlier * because we would create dependency cycles in the above loop */ diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 614620c14af..24543601ef9 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -52,15 +52,15 @@ ImageManager::ImageManager(const DeviceInfo& info) { \ tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_ ## ARCH; \ tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_ ## ARCH; \ + tex_num_images[IMAGE_DATA_TYPE_HALF4] = TEX_NUM_HALF4_ ## ARCH; \ tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_ ## ARCH; \ tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_ ## ARCH; \ - tex_num_images[IMAGE_DATA_TYPE_HALF4] = TEX_NUM_HALF4_ ## ARCH; \ tex_num_images[IMAGE_DATA_TYPE_HALF] = TEX_NUM_HALF_ ## ARCH; \ tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_START_FLOAT4_ ## ARCH; \ tex_start_images[IMAGE_DATA_TYPE_BYTE4] = TEX_START_BYTE4_ ## ARCH; \ + tex_start_images[IMAGE_DATA_TYPE_HALF4] = TEX_START_HALF4_ ## ARCH; \ tex_start_images[IMAGE_DATA_TYPE_FLOAT] = TEX_START_FLOAT_ ## ARCH; \ tex_start_images[IMAGE_DATA_TYPE_BYTE] = TEX_START_BYTE_ ## ARCH; \ - tex_start_images[IMAGE_DATA_TYPE_HALF4] = TEX_START_HALF4_ ## ARCH; \ tex_start_images[IMAGE_DATA_TYPE_HALF] = TEX_START_HALF_ ## ARCH; \ } @@ -82,15 +82,15 @@ ImageManager::ImageManager(const DeviceInfo& info) /* Should not happen. */ tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = 0; tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0; + tex_num_images[IMAGE_DATA_TYPE_HALF4] = 0; tex_num_images[IMAGE_DATA_TYPE_FLOAT] = 0; tex_num_images[IMAGE_DATA_TYPE_BYTE] = 0; - tex_num_images[IMAGE_DATA_TYPE_HALF4] = 0; tex_num_images[IMAGE_DATA_TYPE_HALF] = 0; tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = 0; tex_start_images[IMAGE_DATA_TYPE_BYTE4] = 0; + tex_start_images[IMAGE_DATA_TYPE_HALF4] = 0; tex_start_images[IMAGE_DATA_TYPE_FLOAT] = 0; tex_start_images[IMAGE_DATA_TYPE_BYTE] = 0; - tex_start_images[IMAGE_DATA_TYPE_HALF4] = 0; tex_start_images[IMAGE_DATA_TYPE_HALF] = 0; assert(0); } @@ -216,7 +216,7 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen } /* We use a consecutive slot counting scheme on the devices, in order - * float4, byte4, float, byte. + * float4, byte4, half4, float, byte, half. * These functions convert the slot ids from ImageManager "images" ones * to device ones and vice versa. */ int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type) @@ -284,7 +284,7 @@ int ImageManager::add_image(const string& filename, if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4) is_float = true; - /* No single channel and half textures on CUDA (Fermi) and OpenCL, use available slots */ + /* No single channel and half textures on CUDA (Fermi) and no half on OpenCL, use available slots */ if((type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_HALF4 || type == IMAGE_DATA_TYPE_HALF) && @@ -1105,10 +1105,11 @@ void ImageManager::device_pack_images(Device *device, size_t size = 0, offset = 0; ImageDataType type; - int info_size = tex_num_images[IMAGE_DATA_TYPE_FLOAT4] + tex_num_images[IMAGE_DATA_TYPE_BYTE4]; + int info_size = tex_num_images[IMAGE_DATA_TYPE_FLOAT4] + tex_num_images[IMAGE_DATA_TYPE_BYTE4] + + tex_num_images[IMAGE_DATA_TYPE_FLOAT] + tex_num_images[IMAGE_DATA_TYPE_BYTE]; uint4 *info = dscene->tex_image_packed_info.resize(info_size); - /* Byte Textures*/ + /* Byte4 Textures*/ type = IMAGE_DATA_TYPE_BYTE4; for(size_t slot = 0; slot < images[type].size(); slot++) { @@ -1119,7 +1120,7 @@ void ImageManager::device_pack_images(Device *device, size += tex_img.size(); } - uchar4 *pixels_byte = dscene->tex_image_byte4_packed.resize(size); + uchar4 *pixels_byte4 = dscene->tex_image_byte4_packed.resize(size); for(size_t slot = 0; slot < images[type].size(); slot++) { if(!images[type][slot]) @@ -1131,11 +1132,11 @@ void ImageManager::device_pack_images(Device *device, info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); - memcpy(pixels_byte+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); + memcpy(pixels_byte4+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); offset += tex_img.size(); } - /* Float Textures*/ + /* Float4 Textures*/ type = IMAGE_DATA_TYPE_FLOAT4; size = 0, offset = 0; @@ -1147,7 +1148,7 @@ void ImageManager::device_pack_images(Device *device, size += tex_img.size(); } - float4 *pixels_float = dscene->tex_image_float4_packed.resize(size); + float4 *pixels_float4 = dscene->tex_image_float4_packed.resize(size); for(size_t slot = 0; slot < images[type].size(); slot++) { if(!images[type][slot]) @@ -1160,6 +1161,63 @@ void ImageManager::device_pack_images(Device *device, uint8_t options = pack_image_options(type, slot); info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); + memcpy(pixels_float4+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); + offset += tex_img.size(); + } + + /* Byte Textures*/ + type = IMAGE_DATA_TYPE_BYTE; + size = 0, offset = 0; + + for(size_t slot = 0; slot < images[type].size(); slot++) { + if(!images[type][slot]) + continue; + + device_vector<uchar>& tex_img = dscene->tex_byte_image[slot]; + size += tex_img.size(); + } + + uchar *pixels_byte = dscene->tex_image_byte_packed.resize(size); + + for(size_t slot = 0; slot < images[type].size(); slot++) { + if(!images[type][slot]) + continue; + + device_vector<uchar>& tex_img = dscene->tex_byte_image[slot]; + + uint8_t options = pack_image_options(type, slot); + + info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); + + memcpy(pixels_byte+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); + offset += tex_img.size(); + } + + /* Float Textures*/ + type = IMAGE_DATA_TYPE_FLOAT; + size = 0, offset = 0; + + for(size_t slot = 0; slot < images[type].size(); slot++) { + if(!images[type][slot]) + continue; + + device_vector<float>& tex_img = dscene->tex_float_image[slot]; + size += tex_img.size(); + } + + float *pixels_float = dscene->tex_image_float_packed.resize(size); + + for(size_t slot = 0; slot < images[type].size(); slot++) { + if(!images[type][slot]) + continue; + + device_vector<float>& tex_img = dscene->tex_float_image[slot]; + + /* todo: support 3D textures, only CPU for now */ + + uint8_t options = pack_image_options(type, slot); + info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); + memcpy(pixels_float+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); offset += tex_img.size(); } @@ -1178,6 +1236,20 @@ void ImageManager::device_pack_images(Device *device, } device->tex_alloc("__tex_image_float4_packed", dscene->tex_image_float4_packed); } + if(dscene->tex_image_byte_packed.size()) { + if(dscene->tex_image_byte_packed.device_pointer) { + thread_scoped_lock device_lock(device_mutex); + device->tex_free(dscene->tex_image_byte_packed); + } + device->tex_alloc("__tex_image_byte_packed", dscene->tex_image_byte_packed); + } + if(dscene->tex_image_float_packed.size()) { + if(dscene->tex_image_float_packed.device_pointer) { + thread_scoped_lock device_lock(device_mutex); + device->tex_free(dscene->tex_image_float_packed); + } + device->tex_alloc("__tex_image_float_packed", dscene->tex_image_float_packed); + } if(dscene->tex_image_packed_info.size()) { if(dscene->tex_image_packed_info.device_pointer) { thread_scoped_lock device_lock(device_mutex); @@ -1208,10 +1280,14 @@ void ImageManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->tex_image_byte4_packed); device->tex_free(dscene->tex_image_float4_packed); + device->tex_free(dscene->tex_image_byte_packed); + device->tex_free(dscene->tex_image_float_packed); device->tex_free(dscene->tex_image_packed_info); dscene->tex_image_byte4_packed.clear(); dscene->tex_image_float4_packed.clear(); + dscene->tex_image_byte_packed.clear(); + dscene->tex_image_float_packed.clear(); dscene->tex_image_packed_info.clear(); } diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 07998684b23..cca71a6bb93 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -39,9 +39,9 @@ public: enum ImageDataType { IMAGE_DATA_TYPE_FLOAT4 = 0, IMAGE_DATA_TYPE_BYTE4 = 1, - IMAGE_DATA_TYPE_FLOAT = 2, - IMAGE_DATA_TYPE_BYTE = 3, - IMAGE_DATA_TYPE_HALF4 = 4, + IMAGE_DATA_TYPE_HALF4 = 2, + IMAGE_DATA_TYPE_FLOAT = 3, + IMAGE_DATA_TYPE_BYTE = 4, IMAGE_DATA_TYPE_HALF = 5, IMAGE_DATA_NUM_TYPES diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 4cd77f8c6e1..787e5cf07b2 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -177,6 +177,16 @@ LightManager::~LightManager() { } +bool LightManager::has_background_light(Scene *scene) +{ + foreach(Light *light, scene->lights) { + if(light->type == LIGHT_BACKGROUND) { + return true; + } + } + return false; +} + void LightManager::disable_ineffective_light(Device *device, Scene *scene) { /* Make all lights enabled by default, and perform some preliminary checks diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 745caa96159..040a672937d 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -91,6 +91,9 @@ public: void tag_update(Scene *scene); + /* Check whether there is a background light. */ + bool has_background_light(Scene *scene); + protected: /* Optimization: disable light which is either unsupported or * which doesn't contribute to the scene or which is only used for MIS diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 4cf0a785897..5445fd3c29c 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -30,6 +30,9 @@ #include "osl_globals.h" +#include "subd_split.h" +#include "subd_patch_table.h" + #include "util_foreach.h" #include "util_logging.h" #include "util_progress.h" @@ -112,19 +115,12 @@ float3 Mesh::SubdFace::normal(const Mesh *mesh) const return safe_normalize(cross(v1 - v0, v2 - v0)); } - /* Mesh */ NODE_DEFINE(Mesh) { NodeType* type = NodeType::add("mesh", create); - static NodeEnum displacement_method_enum; - displacement_method_enum.insert("bump", DISPLACE_BUMP); - displacement_method_enum.insert("true", DISPLACE_TRUE); - displacement_method_enum.insert("both", DISPLACE_BOTH); - SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP); - SOCKET_UINT(motion_steps, "Motion Steps", 3); SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false); @@ -177,11 +173,16 @@ Mesh::Mesh() num_ngons = 0; subdivision_type = SUBDIVISION_NONE; + subd_params = NULL; + + patch_table = NULL; } Mesh::~Mesh() { delete bvh; + delete patch_table; + delete subd_params; } void Mesh::resize_mesh(int numverts, int numtris) @@ -274,6 +275,8 @@ void Mesh::clear() num_subd_verts = 0; + subd_creases.clear(); + attributes.clear(); curve_attributes.clear(); subd_attributes.clear(); @@ -283,6 +286,9 @@ void Mesh::clear() transform_negative_scaled = false; transform_normal = transform_identity(); geometry_flags = GEOMETRY_NONE; + + delete patch_table; + patch_table = NULL; } int Mesh::split_vertex(int vertex) @@ -292,17 +298,17 @@ int Mesh::split_vertex(int vertex) foreach(Attribute& attr, attributes.attributes) { if(attr.element == ATTR_ELEMENT_VERTEX) { - vector<char> tmp(attr.data_sizeof()); - memcpy(&tmp[0], attr.data() + tmp.size()*vertex, tmp.size()); - attr.add(&tmp[0]); + array<char> tmp(attr.data_sizeof()); + memcpy(tmp.data(), attr.data() + tmp.size()*vertex, tmp.size()); + attr.add(tmp.data()); } } foreach(Attribute& attr, subd_attributes.attributes) { if(attr.element == ATTR_ELEMENT_VERTEX) { - vector<char> tmp(attr.data_sizeof()); - memcpy(&tmp[0], attr.data() + tmp.size()*vertex, tmp.size()); - attr.add(&tmp[0]); + array<char> tmp(attr.data_sizeof()); + memcpy(tmp.data(), attr.data() + tmp.size()*vertex, tmp.size()); + attr.add(tmp.data()); } } @@ -468,7 +474,7 @@ void Mesh::add_face_normals() bool flip = transform_negative_scaled; if(triangles_size) { - float3 *verts_ptr = &verts[0]; + float3 *verts_ptr = verts.data(); for(size_t i = 0; i < triangles_size; i++) { fN[i] = compute_face_normal(get_triangle(i), verts_ptr); @@ -494,7 +500,7 @@ void Mesh::add_vertex_normals() size_t triangles_size = num_triangles(); /* static vertex normals */ - if(!attributes.find(ATTR_STD_VERTEX_NORMAL)) { + if(!attributes.find(ATTR_STD_VERTEX_NORMAL) && triangles_size) { /* get attributes */ Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL); Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL); @@ -505,17 +511,17 @@ void Mesh::add_vertex_normals() /* compute vertex normals */ memset(vN, 0, verts.size()*sizeof(float3)); - if(triangles_size) { - - for(size_t i = 0; i < triangles_size; i++) - for(size_t j = 0; j < 3; j++) - vN[get_triangle(i).v[j]] += fN[i]; + for(size_t i = 0; i < triangles_size; i++) { + for(size_t j = 0; j < 3; j++) { + vN[get_triangle(i).v[j]] += fN[i]; + } } for(size_t i = 0; i < verts_size; i++) { vN[i] = normalize(vN[i]); - if(flip) + if(flip) { vN[i] = -vN[i]; + } } } @@ -523,7 +529,7 @@ void Mesh::add_vertex_normals() Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); Attribute *attr_mN = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); - if(has_motion_blur() && attr_mP && !attr_mN) { + if(has_motion_blur() && attr_mP && !attr_mN && triangles_size) { /* create attribute */ attr_mN = attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL); @@ -534,27 +540,79 @@ void Mesh::add_vertex_normals() /* compute */ memset(mN, 0, verts.size()*sizeof(float3)); - if(triangles_size) { - for(size_t i = 0; i < triangles_size; i++) { - for(size_t j = 0; j < 3; j++) { - float3 fN = compute_face_normal(get_triangle(i), mP); - mN[get_triangle(i).v[j]] += fN; - } + for(size_t i = 0; i < triangles_size; i++) { + for(size_t j = 0; j < 3; j++) { + float3 fN = compute_face_normal(get_triangle(i), mP); + mN[get_triangle(i).v[j]] += fN; } } for(size_t i = 0; i < verts_size; i++) { mN[i] = normalize(mN[i]); - if(flip) + if(flip) { mN[i] = -mN[i]; + } } } } + + /* subd vertex normals */ + if(!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && subd_faces.size()) { + /* get attributes */ + Attribute *attr_vN = subd_attributes.add(ATTR_STD_VERTEX_NORMAL); + float3 *vN = attr_vN->data_float3(); + + /* compute vertex normals */ + memset(vN, 0, verts.size()*sizeof(float3)); + + for(size_t i = 0; i < subd_faces.size(); i++) { + SubdFace& face = subd_faces[i]; + float3 fN = face.normal(this); + + for(size_t j = 0; j < face.num_corners; j++) { + size_t corner = subd_face_corners[face.start_corner+j]; + vN[corner] += fN; + } + } + + for(size_t i = 0; i < verts_size; i++) { + vN[i] = normalize(vN[i]); + if(flip) { + vN[i] = -vN[i]; + } + } + } +} + +void Mesh::add_undisplaced() +{ + AttributeSet& attrs = (subdivision_type == SUBDIVISION_NONE) ? attributes : subd_attributes; + + /* don't compute if already there */ + if(attrs.find(ATTR_STD_POSITION_UNDISPLACED)) { + return; + } + + /* get attribute */ + Attribute *attr = attrs.add(ATTR_STD_POSITION_UNDISPLACED); + attr->flags |= ATTR_SUBDIVIDED; + + float3 *data = attr->data_float3(); + + /* copy verts */ + size_t size = attr->buffer_size(this, (subdivision_type == SUBDIVISION_NONE) ? ATTR_PRIM_TRIANGLE : ATTR_PRIM_SUBD); + if(size) { + memcpy(data, verts.data(), size); + } } void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal) { Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); + if(attr_vN == NULL) { + /* Happens on objects with just hair. */ + return; + } float3 *vN = attr_vN->data_float3(); uint shader_id = 0; @@ -562,7 +620,7 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal) bool last_smooth = false; size_t triangles_size = num_triangles(); - int *shader_ptr = (shader.size())? &shader[0]: NULL; + int *shader_ptr = shader.data(); bool do_transform = transform_applied; Transform ntfm = transform_normal; @@ -574,7 +632,7 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal) last_smooth = smooth[i]; Shader *shader = (last_shader < used_shaders.size()) ? used_shaders[last_shader] : scene->default_surface; - shader_id = scene->shader_manager->get_shader_id(shader, this, last_smooth); + shader_id = scene->shader_manager->get_shader_id(shader, last_smooth); } tri_shader[i] = shader_id; @@ -602,7 +660,7 @@ void Mesh::pack_verts(const vector<uint>& tri_prim_index, size_t verts_size = verts.size(); if(verts_size && subd_faces.size()) { - float2 *vert_patch_uv_ptr = &vert_patch_uv[0]; + float2 *vert_patch_uv_ptr = vert_patch_uv.data(); for(size_t i = 0; i < verts_size; i++) { tri_patch_uv[i] = vert_patch_uv_ptr[i]; @@ -611,16 +669,14 @@ void Mesh::pack_verts(const vector<uint>& tri_prim_index, size_t triangles_size = num_triangles(); - if(triangles_size) { - for(size_t i = 0; i < triangles_size; i++) { - Triangle t = get_triangle(i); - tri_vindex[i] = make_uint4(t.v[0] + vert_offset, - t.v[1] + vert_offset, - t.v[2] + vert_offset, - tri_prim_index[i + tri_offset]); + for(size_t i = 0; i < triangles_size; i++) { + Triangle t = get_triangle(i); + tri_vindex[i] = make_uint4(t.v[0] + vert_offset, + t.v[1] + vert_offset, + t.v[2] + vert_offset, + tri_prim_index[i + tri_offset]); - tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i]*8 + patch_offset); - } + tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i]*8 + patch_offset); } } @@ -630,8 +686,8 @@ void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, s /* pack curve keys */ if(curve_keys_size) { - float3 *keys_ptr = &curve_keys[0]; - float *radius_ptr = &curve_radius[0]; + float3 *keys_ptr = curve_keys.data(); + float *radius_ptr = curve_radius.data(); for(size_t i = 0; i < curve_keys_size; i++) curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]); @@ -640,20 +696,18 @@ void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, s /* pack curve segments */ size_t curve_num = num_curves(); - if(curve_num) { - for(size_t i = 0; i < curve_num; i++) { - Curve curve = get_curve(i); - int shader_id = curve_shader[i]; - Shader *shader = (shader_id < used_shaders.size()) ? - used_shaders[shader_id] : scene->default_surface; - shader_id = scene->shader_manager->get_shader_id(shader, this, false); - - curve_data[i] = make_float4( - __int_as_float(curve.first_key + curvekey_offset), - __int_as_float(curve.num_keys), - __int_as_float(shader_id), - 0.0f); - } + for(size_t i = 0; i < curve_num; i++) { + Curve curve = get_curve(i); + int shader_id = curve_shader[i]; + Shader *shader = (shader_id < used_shaders.size()) ? + used_shaders[shader_id] : scene->default_surface; + shader_id = scene->shader_manager->get_shader_id(shader, false); + + curve_data[i] = make_float4( + __int_as_float(curve.first_key + curvekey_offset), + __int_as_float(curve.num_keys), + __int_as_float(shader_id), + 0.0f); } } @@ -662,13 +716,30 @@ void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, ui size_t num_faces = subd_faces.size(); int ngons = 0; - if(num_faces) { - for(size_t f = 0; f < num_faces; f++) { - SubdFace face = subd_faces[f]; + for(size_t f = 0; f < num_faces; f++) { + SubdFace face = subd_faces[f]; - if(face.is_quad()) { + if(face.is_quad()) { + int c[4]; + memcpy(c, &subd_face_corners[face.start_corner], sizeof(int)*4); + + *(patch_data++) = c[0] + vert_offset; + *(patch_data++) = c[1] + vert_offset; + *(patch_data++) = c[2] + vert_offset; + *(patch_data++) = c[3] + vert_offset; + + *(patch_data++) = f+face_offset; + *(patch_data++) = face.num_corners; + *(patch_data++) = face.start_corner + corner_offset; + *(patch_data++) = 0; + } + else { + for(int i = 0; i < face.num_corners; i++) { int c[4]; - memcpy(c, &subd_face_corners[face.start_corner], sizeof(int)*4); + c[0] = subd_face_corners[face.start_corner + mod(i + 0, face.num_corners)]; + c[1] = subd_face_corners[face.start_corner + mod(i + 1, face.num_corners)]; + c[2] = verts.size() - num_subd_verts + ngons; + c[3] = subd_face_corners[face.start_corner + mod(i - 1, face.num_corners)]; *(patch_data++) = c[0] + vert_offset; *(patch_data++) = c[1] + vert_offset; @@ -676,36 +747,16 @@ void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, ui *(patch_data++) = c[3] + vert_offset; *(patch_data++) = f+face_offset; - *(patch_data++) = face.num_corners; + *(patch_data++) = face.num_corners | (i << 16); *(patch_data++) = face.start_corner + corner_offset; - *(patch_data++) = 0; + *(patch_data++) = subd_face_corners.size() + ngons + corner_offset; } - else { - for(int i = 0; i < face.num_corners; i++) { - int c[4]; - c[0] = subd_face_corners[face.start_corner + mod(i + 0, face.num_corners)]; - c[1] = subd_face_corners[face.start_corner + mod(i + 1, face.num_corners)]; - c[2] = verts.size() - num_subd_verts + ngons; - c[3] = subd_face_corners[face.start_corner + mod(i - 1, face.num_corners)]; - - *(patch_data++) = c[0] + vert_offset; - *(patch_data++) = c[1] + vert_offset; - *(patch_data++) = c[2] + vert_offset; - *(patch_data++) = c[3] + vert_offset; - - *(patch_data++) = f+face_offset; - *(patch_data++) = face.num_corners | (i << 16); - *(patch_data++) = face.start_corner + corner_offset; - *(patch_data++) = subd_face_corners.size() + ngons + corner_offset; - } - ngons++; - } + ngons++; } } } - void Mesh::compute_bvh(DeviceScene *dscene, SceneParams *params, Progress *progress, @@ -779,6 +830,17 @@ bool Mesh::has_motion_blur() const curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))); } +bool Mesh::has_true_displacement() const +{ + foreach(Shader *shader, used_shaders) { + if(shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) { + return true; + } + } + + return false; +} + bool Mesh::need_build_bvh() const { return !transform_applied || has_surface_bssrdf; @@ -831,9 +893,10 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att OSLGlobals::Attribute osl_attr; osl_attr.type = attr.type(); - osl_attr.elem = ATTR_ELEMENT_OBJECT; + osl_attr.desc.element = ATTR_ELEMENT_OBJECT; osl_attr.value = attr; - osl_attr.offset = 0; + osl_attr.desc.offset = 0; + osl_attr.desc.flags = 0; og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][attr.name()] = osl_attr; og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr; @@ -853,9 +916,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att foreach(AttributeRequest& req, attributes.requests) { OSLGlobals::Attribute osl_attr; - if(req.triangle_element != ATTR_ELEMENT_NONE) { - osl_attr.elem = req.triangle_element; - osl_attr.offset = req.triangle_offset; + if(req.triangle_desc.element != ATTR_ELEMENT_NONE) { + osl_attr.desc = req.triangle_desc; if(req.triangle_type == TypeDesc::TypeFloat) osl_attr.type = TypeDesc::TypeFloat; @@ -875,9 +937,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att } } - if(req.curve_element != ATTR_ELEMENT_NONE) { - osl_attr.elem = req.curve_element; - osl_attr.offset = req.curve_offset; + if(req.curve_desc.element != ATTR_ELEMENT_NONE) { + osl_attr.desc = req.curve_desc; if(req.curve_type == TypeDesc::TypeFloat) osl_attr.type = TypeDesc::TypeFloat; @@ -897,9 +958,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att } } - if(req.subd_element != ATTR_ELEMENT_NONE) { - osl_attr.elem = req.subd_element; - osl_attr.offset = req.subd_offset; + if(req.subd_desc.element != ATTR_ELEMENT_NONE) { + osl_attr.desc = req.subd_desc; if(req.subd_type == TypeDesc::TypeFloat) osl_attr.type = TypeDesc::TypeFloat; @@ -971,8 +1031,8 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce if(mesh->num_triangles()) { attr_map[index].x = id; - attr_map[index].y = req.triangle_element; - attr_map[index].z = as_uint(req.triangle_offset); + attr_map[index].y = req.triangle_desc.element; + attr_map[index].z = as_uint(req.triangle_desc.offset); if(req.triangle_type == TypeDesc::TypeFloat) attr_map[index].w = NODE_ATTR_FLOAT; @@ -980,14 +1040,16 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce attr_map[index].w = NODE_ATTR_MATRIX; else attr_map[index].w = NODE_ATTR_FLOAT3; + + attr_map[index].w |= req.triangle_desc.flags << 8; } index++; if(mesh->num_curves()) { attr_map[index].x = id; - attr_map[index].y = req.curve_element; - attr_map[index].z = as_uint(req.curve_offset); + attr_map[index].y = req.curve_desc.element; + attr_map[index].z = as_uint(req.curve_desc.offset); if(req.curve_type == TypeDesc::TypeFloat) attr_map[index].w = NODE_ATTR_FLOAT; @@ -995,14 +1057,16 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce attr_map[index].w = NODE_ATTR_MATRIX; else attr_map[index].w = NODE_ATTR_FLOAT3; + + attr_map[index].w |= req.curve_desc.flags << 8; } index++; if(mesh->subd_faces.size()) { attr_map[index].x = id; - attr_map[index].y = req.subd_element; - attr_map[index].z = as_uint(req.subd_offset); + attr_map[index].y = req.subd_desc.element; + attr_map[index].z = as_uint(req.subd_desc.offset); if(req.subd_type == TypeDesc::TypeFloat) attr_map[index].w = NODE_ATTR_FLOAT; @@ -1010,6 +1074,8 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce attr_map[index].w = NODE_ATTR_MATRIX; else attr_map[index].w = NODE_ATTR_FLOAT3; + + attr_map[index].w |= req.subd_desc.flags << 8; } index++; @@ -1069,17 +1135,20 @@ static void update_attribute_element_offset(Mesh *mesh, Attribute *mattr, AttributePrimitive prim, TypeDesc& type, - int& offset, - AttributeElement& element) + AttributeDescriptor& desc) { if(mattr) { /* store element and type */ - element = mattr->element; + desc.element = mattr->element; + desc.flags = mattr->flags; type = mattr->type; /* store attribute data in arrays */ size_t size = mattr->element_size(mesh, prim); + AttributeElement& element = desc.element; + int& offset = desc.offset; + if(mattr->element == ATTR_ELEMENT_VOXEL) { /* store slot in offset value */ VoxelAttribute *voxel_data = mattr->data_voxel(); @@ -1128,7 +1197,11 @@ static void update_attribute_element_offset(Mesh *mesh, /* mesh vertex/curve index is global, not per object, so we sneak * a correction for that in here */ - if(element == ATTR_ELEMENT_VERTEX) + if(mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK && desc.flags & ATTR_SUBDIVIDED) { + /* indices for subdivided attributes are retrieved + * from patch table so no need for correction here*/ + } + else if(element == ATTR_ELEMENT_VERTEX) offset -= mesh->vert_offset; else if(element == ATTR_ELEMENT_VERTEX_MOTION) offset -= mesh->vert_offset; @@ -1153,8 +1226,8 @@ static void update_attribute_element_offset(Mesh *mesh, } else { /* attribute not found */ - element = ATTR_ELEMENT_NONE; - offset = 0; + desc.element = ATTR_ELEMENT_NONE; + desc.offset = 0; } } @@ -1243,8 +1316,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, triangle_mattr, ATTR_PRIM_TRIANGLE, req.triangle_type, - req.triangle_offset, - req.triangle_element); + req.triangle_desc); update_attribute_element_offset(mesh, attr_float, attr_float_offset, @@ -1253,8 +1325,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, curve_mattr, ATTR_PRIM_CURVE, req.curve_type, - req.curve_offset, - req.curve_element); + req.curve_desc); update_attribute_element_offset(mesh, attr_float, attr_float_offset, @@ -1263,8 +1334,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, subd_mattr, ATTR_PRIM_SUBD, req.subd_type, - req.subd_offset, - req.subd_element); + req.subd_desc); if(progress.get_cancel()) return; } @@ -1327,6 +1397,12 @@ void MeshManager::mesh_calc_offset(Scene *scene) if(mesh->subd_faces.size()) { Mesh::SubdFace& last = mesh->subd_faces[mesh->subd_faces.size()-1]; patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; + + /* patch tables are stored in same array so include them in patch_size */ + if(mesh->patch_table) { + mesh->patch_table_offset = patch_size; + patch_size += mesh->patch_table->total_size(); + } } face_size += mesh->subd_faces.size(); corner_size += mesh->subd_face_corners.size(); @@ -1358,6 +1434,12 @@ void MeshManager::device_update_mesh(Device *device, if(mesh->subd_faces.size()) { Mesh::SubdFace& last = mesh->subd_faces[mesh->subd_faces.size()-1]; patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; + + /* patch tables are stored in same array so include them in patch_size */ + if(mesh->patch_table) { + mesh->patch_table_offset = patch_size; + patch_size += mesh->patch_table->total_size(); + } } } @@ -1440,6 +1522,11 @@ void MeshManager::device_update_mesh(Device *device, foreach(Mesh *mesh, scene->meshes) { mesh->pack_patches(&patch_data[mesh->patch_offset], mesh->vert_offset, mesh->face_offset, mesh->corner_offset); + + if(mesh->patch_table) { + mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], mesh->patch_table_offset); + } + if(progress.get_cancel()) return; } @@ -1617,6 +1704,46 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen mesh->add_face_normals(); mesh->add_vertex_normals(); + if(mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) { + mesh->add_undisplaced(); + } + + if(progress.get_cancel()) return; + } + } + + /* Tessellate meshes that are using subdivision */ + size_t total_tess_needed = 0; + foreach(Mesh *mesh, scene->meshes) { + if(mesh->need_update && + mesh->subdivision_type != Mesh::SUBDIVISION_NONE && + mesh->num_subd_verts == 0 && + mesh->subd_params) + { + total_tess_needed++; + } + } + + size_t i = 0; + foreach(Mesh *mesh, scene->meshes) { + if(mesh->need_update && + mesh->subdivision_type != Mesh::SUBDIVISION_NONE && + mesh->num_subd_verts == 0 && + mesh->subd_params) + { + string msg = "Tessellating "; + if(mesh->name == "") + msg += string_printf("%u/%u", (uint)(i+1), (uint)total_tess_needed); + else + msg += string_printf("%s %u/%u", mesh->name.c_str(), (uint)(i+1), (uint)total_tess_needed); + + progress.set_status("Updating Mesh", msg); + + DiagSplit dsplit(*mesh->subd_params); + mesh->tessellate(&dsplit); + + i++; + if(progress.get_cancel()) return; } } @@ -1626,7 +1753,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen bool old_need_object_flags_update = false; foreach(Mesh *mesh, scene->meshes) { if(mesh->need_update && - mesh->displacement_method != Mesh::DISPLACE_BUMP) + mesh->has_true_displacement()) { true_displacement_used = true; break; @@ -1652,6 +1779,10 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen } if(progress.get_cancel()) return; + /* after mesh data has been copied to device memory we need to update + * offsets for patch tables as this can't be known before hand */ + scene->object_manager->device_update_patch_map_offsets(device, dscene, scene); + device_update_attributes(device, dscene, scene, progress); if(progress.get_cancel()) return; @@ -1677,7 +1808,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen } /* Update bvh. */ - size_t i = 0, num_bvh = 0; + size_t num_bvh = 0; foreach(Mesh *mesh, scene->meshes) { if(mesh->need_update && mesh->need_build_bvh()) { num_bvh++; @@ -1686,6 +1817,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen TaskPool pool; + i = 0; foreach(Mesh *mesh, scene->meshes) { if(mesh->need_update) { pool.push(function_bind(&Mesh::compute_bvh, diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index c9ae9aab888..c0310f45840 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -39,7 +39,9 @@ class Progress; class Scene; class SceneParams; class AttributeRequest; +struct SubdParams; class DiagSplit; +struct PackedPatchTable; /* Mesh */ @@ -110,13 +112,9 @@ public: int num_ptex_faces() const { return num_corners == 4 ? 1 : num_corners; } }; - /* Displacement */ - enum DisplacementMethod { - DISPLACE_BUMP = 0, - DISPLACE_TRUE = 1, - DISPLACE_BOTH = 2, - - DISPLACE_NUM_METHODS, + struct SubdEdgeCrease { + int v[2]; + float crease; }; enum SubdivisionType { @@ -157,6 +155,10 @@ public: array<int> subd_face_corners; int num_ngons; + array<SubdEdgeCrease> subd_creases; + + SubdParams *subd_params; + vector<Shader*> used_shaders; AttributeSet attributes; AttributeSet curve_attributes; @@ -166,7 +168,8 @@ public: bool transform_applied; bool transform_negative_scaled; Transform transform_normal; - DisplacementMethod displacement_method; + + PackedPatchTable *patch_table; uint motion_steps; bool use_motion_blur; @@ -184,6 +187,7 @@ public: size_t curvekey_offset; size_t patch_offset; + size_t patch_table_offset; size_t face_offset; size_t corner_offset; @@ -211,6 +215,7 @@ public: void compute_bounds(); void add_face_normals(); void add_vertex_normals(); + void add_undisplaced(); void pack_normals(Scene *scene, uint *shader, float4 *vnormal); void pack_verts(const vector<uint>& tri_prim_index, @@ -234,6 +239,7 @@ public: void tag_update(Scene *scene, bool rebuild); bool has_motion_blur() const; + bool has_true_displacement() const; /* Check whether the mesh should have own BVH built separately. Briefly, * own BVH is needed for mesh, if: diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp index 95f46ff02a2..ef9cfedd412 100644 --- a/intern/cycles/render/mesh_displace.cpp +++ b/intern/cycles/render/mesh_displace.cpp @@ -26,19 +26,27 @@ CCL_NAMESPACE_BEGIN +static float3 compute_face_normal(const Mesh::Triangle& t, float3 *verts) +{ + float3 v0 = verts[t.v[0]]; + float3 v1 = verts[t.v[1]]; + float3 v2 = verts[t.v[2]]; + + float3 norm = cross(v1 - v0, v2 - v0); + float normlen = len(norm); + + if(normlen == 0.0f) + return make_float3(1.0f, 0.0f, 0.0f); + + return norm / normlen; +} + bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress& progress) { /* verify if we have a displacement shader */ - bool has_displacement = false; - - if(mesh->displacement_method != Mesh::DISPLACE_BUMP) { - foreach(Shader *shader, mesh->used_shaders) - if(shader->has_displacement) - has_displacement = true; - } - - if(!has_displacement) + if(!mesh->has_true_displacement()) { return false; + } string msg = string_printf("Computing Displacement %s", mesh->name.c_str()); progress.set_status("Updating Mesh", msg); @@ -67,8 +75,9 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me Shader *shader = (shader_index < mesh->used_shaders.size()) ? mesh->used_shaders[shader_index] : scene->default_surface; - if(!shader->has_displacement) + if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) { continue; + } for(int j = 0; j < 3; j++) { if(done[t.v[j]]) @@ -153,8 +162,9 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me Shader *shader = (shader_index < mesh->used_shaders.size()) ? mesh->used_shaders[shader_index] : scene->default_surface; - if(!shader->has_displacement) + if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) { continue; + } for(int j = 0; j < 3; j++) { if(!done[t.v[j]]) { @@ -178,9 +188,131 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me mesh->attributes.remove(ATTR_STD_FACE_NORMAL); mesh->add_face_normals(); - if(mesh->displacement_method == Mesh::DISPLACE_TRUE) { - mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); - mesh->add_vertex_normals(); + bool need_recompute_vertex_normals = false; + + foreach(Shader *shader, mesh->used_shaders) { + if(shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) { + need_recompute_vertex_normals = true; + break; + } + } + + if(need_recompute_vertex_normals) { + bool flip = mesh->transform_negative_scaled; + vector<bool> tri_has_true_disp(num_triangles, false); + + for(size_t i = 0; i < num_triangles; i++) { + int shader_index = mesh->shader[i]; + Shader *shader = (shader_index < mesh->used_shaders.size()) ? + mesh->used_shaders[shader_index] : scene->default_surface; + + tri_has_true_disp[i] = shader->has_displacement && shader->displacement_method == DISPLACE_TRUE; + } + + /* static vertex normals */ + + /* get attributes */ + Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL); + Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); + + float3 *fN = attr_fN->data_float3(); + float3 *vN = attr_vN->data_float3(); + + /* compute vertex normals */ + + /* zero vertex normals on triangles with true displacement */ + for(size_t i = 0; i < num_triangles; i++) { + if(tri_has_true_disp[i]) { + for(size_t j = 0; j < 3; j++) { + vN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f); + } + } + } + + /* add face normals to vertex normals */ + for(size_t i = 0; i < num_triangles; i++) { + if(tri_has_true_disp[i]) { + for(size_t j = 0; j < 3; j++) { + vN[mesh->get_triangle(i).v[j]] += fN[i]; + } + } + } + + /* normalize vertex normals */ + done.clear(); + done.resize(num_verts, false); + + for(size_t i = 0; i < num_triangles; i++) { + if(tri_has_true_disp[i]) { + for(size_t j = 0; j < 3; j++) { + int vert = mesh->get_triangle(i).v[j]; + + if(done[vert]) { + continue; + } + + vN[vert] = normalize(vN[vert]); + if(flip) + vN[vert] = -vN[vert]; + + done[vert] = true; + } + } + } + + /* motion vertex normals */ + Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); + + if(mesh->has_motion_blur() && attr_mP && attr_mN) { + for(int step = 0; step < mesh->motion_steps - 1; step++) { + float3 *mP = attr_mP->data_float3() + step*mesh->verts.size(); + float3 *mN = attr_mN->data_float3() + step*mesh->verts.size(); + + /* compute */ + + /* zero vertex normals on triangles with true displacement */ + for(size_t i = 0; i < num_triangles; i++) { + if(tri_has_true_disp[i]) { + for(size_t j = 0; j < 3; j++) { + mN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f); + } + } + } + + /* add face normals to vertex normals */ + for(size_t i = 0; i < num_triangles; i++) { + if(tri_has_true_disp[i]) { + for(size_t j = 0; j < 3; j++) { + float3 fN = compute_face_normal(mesh->get_triangle(i), mP); + mN[mesh->get_triangle(i).v[j]] += fN; + } + } + } + + /* normalize vertex normals */ + done.clear(); + done.resize(num_verts, false); + + for(size_t i = 0; i < num_triangles; i++) { + if(tri_has_true_disp[i]) { + for(size_t j = 0; j < 3; j++) { + int vert = mesh->get_triangle(i).v[j]; + + if(done[vert]) { + continue; + } + + mN[vert] = normalize(mN[vert]); + if(flip) + mN[vert] = -mN[vert]; + + done[vert] = true; + } + } + } + } + } } return true; diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp index fe8e41e8d35..c8cc3abf7d9 100644 --- a/intern/cycles/render/mesh_subdivision.cpp +++ b/intern/cycles/render/mesh_subdivision.cpp @@ -19,13 +19,304 @@ #include "subd_split.h" #include "subd_patch.h" +#include "subd_patch_table.h" #include "util_foreach.h" CCL_NAMESPACE_BEGIN +#ifdef WITH_OPENSUBDIV + +CCL_NAMESPACE_END + +#include <opensubdiv/far/topologyRefinerFactory.h> +#include <opensubdiv/far/primvarRefiner.h> +#include <opensubdiv/far/patchTableFactory.h> +#include <opensubdiv/far/patchMap.h> + +/* specializations of TopologyRefinerFactory for ccl::Mesh */ + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { +namespace Far { + template<> + bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner& refiner, ccl::Mesh const& mesh) + { + setNumBaseVertices(refiner, mesh.verts.size()); + setNumBaseFaces(refiner, mesh.subd_faces.size()); + + const ccl::Mesh::SubdFace* face = mesh.subd_faces.data(); + + for(int i = 0; i < mesh.subd_faces.size(); i++, face++) { + setNumBaseFaceVertices(refiner, i, face->num_corners); + } + + return true; + } + + template<> + bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner& refiner, ccl::Mesh const& mesh) + { + const ccl::Mesh::SubdFace* face = mesh.subd_faces.data(); + + for(int i = 0; i < mesh.subd_faces.size(); i++, face++) { + IndexArray face_verts = getBaseFaceVertices(refiner, i); + + int* corner = &mesh.subd_face_corners[face->start_corner]; + + for(int j = 0; j < face->num_corners; j++, corner++) { + face_verts[j] = *corner; + } + } + + return true; + } + + template<> + bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner& refiner, ccl::Mesh const& mesh) + { + const ccl::Mesh::SubdEdgeCrease* crease = mesh.subd_creases.data(); + + for(int i = 0; i < mesh.subd_creases.size(); i++, crease++) { + Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]); + + if(edge != INDEX_INVALID) { + setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f); + } + } + + for(int i = 0; i < mesh.verts.size(); i++) { + ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i); + + if(vert_edges.size() == 2) { + float sharpness = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]); + sharpness = std::min(sharpness, refiner.getLevel(0).getEdgeSharpness(vert_edges[1])); + + setBaseVertexSharpness(refiner, i, sharpness); + } + } + + return true; + } + + template<> + bool TopologyRefinerFactory<ccl::Mesh>::assignFaceVaryingTopology(TopologyRefiner& /*refiner*/, ccl::Mesh const& /*mesh*/) + { + return true; + } + + template<> + void TopologyRefinerFactory<ccl::Mesh>::reportInvalidTopology(TopologyError /*err_code*/, + char const */*msg*/, ccl::Mesh const& /*mesh*/) + { + } +} /* namespace Far */ +} /* namespace OPENSUBDIV_VERSION */ +} /* namespace OpenSubdiv */ + +CCL_NAMESPACE_BEGIN + +using namespace OpenSubdiv; + +/* struct that implements OpenSubdiv's vertex interface */ + +template<typename T> +struct OsdValue { + T value; + + OsdValue() {} + + void Clear(void* = 0) { + memset(&value, 0, sizeof(T)); + } + + void AddWithWeight(OsdValue<T> const& src, float weight) { + value += src.value * weight; + } +}; + +template<> +void OsdValue<uchar4>::AddWithWeight(OsdValue<uchar4> const& src, float weight) +{ + for(int i = 0; i < 4; i++) { + value[i] += (uchar)(src.value[i] * weight); + } +} + +/* class for holding OpenSubdiv data used during tessellation */ + +class OsdData { + Mesh* mesh; + vector<OsdValue<float3> > verts; + Far::TopologyRefiner* refiner; + Far::PatchTable* patch_table; + Far::PatchMap* patch_map; + +public: + OsdData() : mesh(NULL), refiner(NULL), patch_table(NULL), patch_map(NULL) {} + + ~OsdData() + { + delete refiner; + delete patch_table; + delete patch_map; + } + + void build_from_mesh(Mesh* mesh_) + { + mesh = mesh_; + + /* type and options */ + Sdc::SchemeType type = Sdc::SCHEME_CATMARK; + + Sdc::Options options; + options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY); + + /* create refiner */ + refiner = Far::TopologyRefinerFactory<Mesh>::Create(*mesh, + Far::TopologyRefinerFactory<Mesh>::Options(type, options)); + + /* adaptive refinement */ + int max_isolation = 10; + refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation)); + + /* create patch table */ + Far::PatchTableFactory::Options patch_options; + patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS; + + patch_table = Far::PatchTableFactory::Create(*refiner, patch_options); + + /* interpolate verts */ + int num_refiner_verts = refiner->GetNumVerticesTotal(); + int num_local_points = patch_table->GetNumLocalPoints(); + + verts.resize(num_refiner_verts + num_local_points); + for(int i = 0; i < mesh->verts.size(); i++) { + verts[i].value = mesh->verts[i]; + } + + OsdValue<float3>* src = verts.data(); + for(int i = 0; i < refiner->GetMaxLevel(); i++) { + OsdValue<float3>* dest = src + refiner->GetLevel(i).GetNumVertices(); + Far::PrimvarRefiner(*refiner).Interpolate(i+1, src, dest); + src = dest; + } + + patch_table->ComputeLocalPointValues(&verts[0], &verts[num_refiner_verts]); + + /* create patch map */ + patch_map = new Far::PatchMap(*patch_table); + } + + void subdivide_attribute(Attribute& attr) + { + Far::PrimvarRefiner primvar_refiner(*refiner); + + if(attr.element == ATTR_ELEMENT_VERTEX) { + int num_refiner_verts = refiner->GetNumVerticesTotal(); + int num_local_points = patch_table->GetNumLocalPoints(); + + attr.resize(num_refiner_verts + num_local_points); + attr.flags |= ATTR_FINAL_SIZE; + + char* src = attr.buffer.data(); + + for(int i = 0; i < refiner->GetMaxLevel(); i++) { + char* dest = src + refiner->GetLevel(i).GetNumVertices() * attr.data_sizeof(); + + if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) { + primvar_refiner.Interpolate(i+1, (OsdValue<float>*)src, (OsdValue<float>*&)dest); + } + else { + primvar_refiner.Interpolate(i+1, (OsdValue<float4>*)src, (OsdValue<float4>*&)dest); + } + + src = dest; + } + + if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) { + patch_table->ComputeLocalPointValues((OsdValue<float>*)&attr.buffer[0], + (OsdValue<float>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]); + } + else { + patch_table->ComputeLocalPointValues((OsdValue<float4>*)&attr.buffer[0], + (OsdValue<float4>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]); + } + } + else if(attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) { + // TODO(mai): fvar interpolation + } + } + + friend struct OsdPatch; + friend class Mesh; +}; + +/* ccl::Patch implementation that uses OpenSubdiv for eval */ + +struct OsdPatch : Patch { + OsdData* osd_data; + + OsdPatch(OsdData* data) : osd_data(data) {} + + void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) + { + const Far::PatchTable::PatchHandle* handle = osd_data->patch_map->FindPatch(patch_index, u, v); + assert(handle); + + float p_weights[20], du_weights[20], dv_weights[20]; + osd_data->patch_table->EvaluateBasis(*handle, u, v, p_weights, du_weights, dv_weights); + + Far::ConstIndexArray cv = osd_data->patch_table->GetPatchVertices(*handle); + + float3 du, dv; + if(P) *P = make_float3(0.0f, 0.0f, 0.0f); + du = make_float3(0.0f, 0.0f, 0.0f); + dv = make_float3(0.0f, 0.0f, 0.0f); + + for(int i = 0; i < cv.size(); i++) { + float3 p = osd_data->verts[cv[i]].value; + + if(P) *P += p * p_weights[i]; + du += p * du_weights[i]; + dv += p * dv_weights[i]; + } + + if(dPdu) *dPdu = du; + if(dPdv) *dPdv = dv; + if(N) *N = normalize(cross(du, dv)); + } + + BoundBox bound() { return BoundBox::empty; } +}; + +#endif + void Mesh::tessellate(DiagSplit *split) { +#ifdef WITH_OPENSUBDIV + OsdData osd_data; + bool need_packed_patch_table = false; + + if(subdivision_type == SUBDIVISION_CATMULL_CLARK) { + if(subd_faces.size()) { + osd_data.build_from_mesh(this); + } + } + else +#endif + { + /* force linear subdivision if OpenSubdiv is unavailable to avoid + * falling into catmull-clark code paths by accident + */ + subdivision_type = SUBDIVISION_LINEAR; + + /* force disable attribute subdivision for same reason as above */ + foreach(Attribute& attr, subd_attributes.attributes) { + attr.flags &= ~ATTR_SUBDIVIDED; + } + } + int num_faces = subd_faces.size(); Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL); @@ -36,113 +327,158 @@ void Mesh::tessellate(DiagSplit *split) if(face.is_quad()) { /* quad */ - LinearQuadPatch patch; - float3 *hull = patch.hull; - float3 *normals = patch.normals; + QuadDice::SubPatch subpatch; + + LinearQuadPatch quad_patch; +#ifdef WITH_OPENSUBDIV + OsdPatch osd_patch(&osd_data); - patch.patch_index = face.ptex_offset; - patch.shader = face.shader; + if(subdivision_type == SUBDIVISION_CATMULL_CLARK) { + osd_patch.patch_index = face.ptex_offset; - for(int i = 0; i < 4; i++) { - hull[i] = verts[subd_face_corners[face.start_corner+i]]; + subpatch.patch = &osd_patch; } + else +#endif + { + float3 *hull = quad_patch.hull; + float3 *normals = quad_patch.normals; + + quad_patch.patch_index = face.ptex_offset; - if(face.smooth) { for(int i = 0; i < 4; i++) { - normals[i] = vN[subd_face_corners[face.start_corner+i]]; + hull[i] = verts[subd_face_corners[face.start_corner+i]]; } - } - else { - float3 N = face.normal(this); - for(int i = 0; i < 4; i++) { - normals[i] = N; + + if(face.smooth) { + for(int i = 0; i < 4; i++) { + normals[i] = vN[subd_face_corners[face.start_corner+i]]; + } + } + else { + float3 N = face.normal(this); + for(int i = 0; i < 4; i++) { + normals[i] = N; + } } + + swap(hull[2], hull[3]); + swap(normals[2], normals[3]); + + subpatch.patch = &quad_patch; } - swap(hull[2], hull[3]); - swap(normals[2], normals[3]); + subpatch.patch->shader = face.shader; /* Quad faces need to be split at least once to line up with split ngons, we do this * here in this manner because if we do it later edge factors may end up slightly off. */ - QuadDice::SubPatch subpatch; - subpatch.patch = &patch; - subpatch.P00 = make_float2(0.0f, 0.0f); subpatch.P10 = make_float2(0.5f, 0.0f); subpatch.P01 = make_float2(0.0f, 0.5f); subpatch.P11 = make_float2(0.5f, 0.5f); - split->split_quad(&patch, &subpatch); + split->split_quad(subpatch.patch, &subpatch); subpatch.P00 = make_float2(0.5f, 0.0f); subpatch.P10 = make_float2(1.0f, 0.0f); subpatch.P01 = make_float2(0.5f, 0.5f); subpatch.P11 = make_float2(1.0f, 0.5f); - split->split_quad(&patch, &subpatch); + split->split_quad(subpatch.patch, &subpatch); subpatch.P00 = make_float2(0.0f, 0.5f); subpatch.P10 = make_float2(0.5f, 0.5f); subpatch.P01 = make_float2(0.0f, 1.0f); subpatch.P11 = make_float2(0.5f, 1.0f); - split->split_quad(&patch, &subpatch); + split->split_quad(subpatch.patch, &subpatch); subpatch.P00 = make_float2(0.5f, 0.5f); subpatch.P10 = make_float2(1.0f, 0.5f); subpatch.P01 = make_float2(0.5f, 1.0f); subpatch.P11 = make_float2(1.0f, 1.0f); - split->split_quad(&patch, &subpatch); + split->split_quad(subpatch.patch, &subpatch); } else { /* ngon */ - float3 center_vert = make_float3(0.0f, 0.0f, 0.0f); - float3 center_normal = make_float3(0.0f, 0.0f, 0.0f); +#ifdef WITH_OPENSUBDIV + if(subdivision_type == SUBDIVISION_CATMULL_CLARK) { + OsdPatch patch(&osd_data); - float inv_num_corners = 1.0f/float(face.num_corners); - for(int corner = 0; corner < face.num_corners; corner++) { - center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners; - center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners; + patch.shader = face.shader; + + for(int corner = 0; corner < face.num_corners; corner++) { + patch.patch_index = face.ptex_offset + corner; + + split->split_quad(&patch); + } } + else +#endif + { + float3 center_vert = make_float3(0.0f, 0.0f, 0.0f); + float3 center_normal = make_float3(0.0f, 0.0f, 0.0f); + + float inv_num_corners = 1.0f/float(face.num_corners); + for(int corner = 0; corner < face.num_corners; corner++) { + center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners; + center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners; + } - for(int corner = 0; corner < face.num_corners; corner++) { - LinearQuadPatch patch; - float3 *hull = patch.hull; - float3 *normals = patch.normals; + for(int corner = 0; corner < face.num_corners; corner++) { + LinearQuadPatch patch; + float3 *hull = patch.hull; + float3 *normals = patch.normals; - patch.patch_index = face.ptex_offset + corner; + patch.patch_index = face.ptex_offset + corner; - patch.shader = face.shader; + patch.shader = face.shader; - hull[0] = verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]]; - hull[1] = verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]]; - hull[2] = verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]]; - hull[3] = center_vert; + hull[0] = verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]]; + hull[1] = verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]]; + hull[2] = verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]]; + hull[3] = center_vert; - hull[1] = (hull[1] + hull[0]) * 0.5; - hull[2] = (hull[2] + hull[0]) * 0.5; + hull[1] = (hull[1] + hull[0]) * 0.5; + hull[2] = (hull[2] + hull[0]) * 0.5; - if(face.smooth) { - normals[0] = vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]]; - normals[1] = vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]]; - normals[2] = vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]]; - normals[3] = center_normal; + if(face.smooth) { + normals[0] = vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]]; + normals[1] = vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]]; + normals[2] = vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]]; + normals[3] = center_normal; - normals[1] = (normals[1] + normals[0]) * 0.5; - normals[2] = (normals[2] + normals[0]) * 0.5; - } - else { - float3 N = face.normal(this); - for(int i = 0; i < 4; i++) { - normals[i] = N; + normals[1] = (normals[1] + normals[0]) * 0.5; + normals[2] = (normals[2] + normals[0]) * 0.5; + } + else { + float3 N = face.normal(this); + for(int i = 0; i < 4; i++) { + normals[i] = N; + } } - } - split->split_quad(&patch); + split->split_quad(&patch); + } } } } /* interpolate center points for attributes */ foreach(Attribute& attr, subd_attributes.attributes) { +#ifdef WITH_OPENSUBDIV + if(subdivision_type == SUBDIVISION_CATMULL_CLARK && attr.flags & ATTR_SUBDIVIDED) { + if(attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) { + /* keep subdivision for corner attributes disabled for now */ + attr.flags &= ~ATTR_SUBDIVIDED; + } + else if(subd_faces.size()) { + osd_data.subdivide_attribute(attr); + + need_packed_patch_table = true; + continue; + } + } +#endif + char* data = attr.data(); size_t stride = attr.data_sizeof(); int ngons = 0; @@ -218,6 +554,15 @@ void Mesh::tessellate(DiagSplit *split) default: break; } } + +#ifdef WITH_OPENSUBDIV + /* pack patch tables */ + if(need_packed_patch_table) { + delete patch_table; + patch_table = new PackedPatchTable; + patch_table->pack(osd_data.patch_table); + } +#endif } CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 4f54b86fe4a..0304d6d95d1 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -4846,12 +4846,8 @@ void CurvesNode::constant_fold(const ConstantFolder& folder, ShaderInput *value_ { ShaderInput *fac_in = input("Fac"); - /* remove no-op node */ - if(!fac_in->link && fac == 0.0f) { - folder.bypass(value_in->link); - } /* evaluate fully constant node */ - else if(folder.all_inputs_constant()) { + if(folder.all_inputs_constant()) { if (curves.size() == 0) return; @@ -4864,6 +4860,11 @@ void CurvesNode::constant_fold(const ConstantFolder& folder, ShaderInput *value_ folder.make_constant(interp(value, result, fac)); } + /* remove no-op node */ + else if(!fac_in->link && fac == 0.0f) { + /* link is not null because otherwise all inputs are constant */ + folder.bypass(value_in->link); + } } void CurvesNode::compile(SVMCompiler& compiler, int type, ShaderInput *value_in, ShaderOutput *value_out) diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 662d87e8b6b..d8f3ce58505 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -29,6 +29,8 @@ #include "util_progress.h" #include "util_vector.h" +#include "subd_patch_table.h" + CCL_NAMESPACE_BEGIN /* Object */ @@ -43,6 +45,7 @@ NODE_DEFINE(Object) SOCKET_UINT(random_id, "Random ID", 0); SOCKET_INT(pass_id, "Pass ID", 0); SOCKET_BOOLEAN(use_holdout, "Use Holdout", false); + SOCKET_BOOLEAN(hide_on_missing_motion, "Hide on Missing Motion", false); SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f)); @@ -55,9 +58,9 @@ Object::Object() particle_system = NULL; particle_index = 0; bounds = BoundBox::empty; - motion.pre = transform_identity(); - motion.mid = transform_identity(); - motion.post = transform_identity(); + motion.pre = transform_empty(); + motion.mid = transform_empty(); + motion.post = transform_empty(); use_motion = false; } @@ -70,8 +73,30 @@ void Object::compute_bounds(bool motion_blur) BoundBox mbounds = mesh->bounds; if(motion_blur && use_motion) { + MotionTransform mtfm = motion; + + if(hide_on_missing_motion) { + /* Hide objects that have no valid previous or next transform, for + * example particle that stop existing. TODO: add support for this + * case in the kernel so we don't get render artifacts. */ + if(mtfm.pre == transform_empty() || + mtfm.post == transform_empty()) { + bounds = BoundBox::empty; + return; + } + } + + /* In case of missing motion information for previous/next frame, + * assume there is no motion. */ + if(mtfm.pre == transform_empty()) { + mtfm.pre = tfm; + } + if(mtfm.post == transform_empty()) { + mtfm.post = tfm; + } + DecompMotionTransform decomp; - transform_motion_decompose(&decomp, &motion, &tfm); + transform_motion_decompose(&decomp, &mtfm, &tfm); bounds = BoundBox::empty; @@ -228,7 +253,7 @@ vector<float> Object::motion_times() bool Object::is_traceable() { /* Mesh itself can be empty,can skip all such objects. */ - if (bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) { + if (!bounds.valid() || bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) { return false; } /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */ @@ -334,19 +359,27 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s * comes with deformed position in object space, or if we transform * the shading point in world space. */ - Transform mtfm_pre = ob->motion.pre; - Transform mtfm_post = ob->motion.post; + MotionTransform mtfm = ob->motion; + + /* In case of missing motion information for previous/next frame, + * assume there is no motion. */ + if(!ob->use_motion || mtfm.pre == transform_empty()) { + mtfm.pre = ob->tfm; + } + if(!ob->use_motion || mtfm.post == transform_empty()) { + mtfm.post = ob->tfm; + } if(!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) { - mtfm_pre = mtfm_pre * itfm; - mtfm_post = mtfm_post * itfm; + mtfm.pre = mtfm.pre * itfm; + mtfm.post = mtfm.post * itfm; } else { flag |= SD_OBJECT_HAS_VERTEX_MOTION; } - memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+0], &mtfm_pre, sizeof(float4)*3); - memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+3], &mtfm_post, sizeof(float4)*3); + memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+0], &mtfm.pre, sizeof(float4)*3); + memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+3], &mtfm.post, sizeof(float4)*3); } #ifdef __OBJECT_MOTION__ else if(state->need_motion == Scene::MOTION_BLUR) { @@ -589,6 +622,40 @@ void ObjectManager::device_update_flags(Device *device, device->tex_alloc("__object_flag", dscene->object_flag); } +void ObjectManager::device_update_patch_map_offsets(Device *device, DeviceScene *dscene, Scene *scene) +{ + if (scene->objects.size() == 0) + return; + + uint4* objects = (uint4*)dscene->objects.get_data(); + + bool update = false; + + int object_index = 0; + foreach(Object *object, scene->objects) { + int offset = object_index*OBJECT_SIZE + 11; + + Mesh* mesh = object->mesh; + + if(mesh->patch_table) { + uint patch_map_offset = 2*(mesh->patch_table_offset + mesh->patch_table->total_size() - + mesh->patch_table->num_nodes * PATCH_NODE_SIZE) - mesh->patch_offset; + + if(objects[offset].x != patch_map_offset) { + objects[offset].x = patch_map_offset; + update = true; + } + } + + object_index++; + } + + if(update) { + device->tex_free(dscene->objects); + device->tex_alloc("__objects", dscene->objects); + } +} + void ObjectManager::device_free(Device *device, DeviceScene *dscene) { device->tex_free(dscene->objects); @@ -638,7 +705,7 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u * Could be solved by moving reference counter to Mesh. */ if((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) && - object->mesh->displacement_method == Mesh::DISPLACE_BUMP) + !object->mesh->has_true_displacement() && object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE) { if(!(motion_blur && object->use_motion)) { if(!object->mesh->transform_applied) { diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 7ab73f3c91a..7e306fab2a8 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -51,6 +51,7 @@ public: uint visibility; MotionTransform motion; bool use_motion; + bool hide_on_missing_motion; bool use_holdout; float3 dupli_generated; @@ -97,6 +98,8 @@ public: Scene *scene, Progress& progress, bool bounds_valid = true); + void device_update_patch_map_offsets(Device *device, DeviceScene *dscene, Scene *scene); + void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 676afad997e..f83aab47e84 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -549,7 +549,7 @@ string OSLCompiler::id(ShaderNode *node) { /* assign layer unique name based on pointer address + bump mode */ stringstream stream; - stream << "node_" << node->name << "_" << node; + stream << "node_" << node->type->name << "_" << node; return stream.str(); } @@ -609,7 +609,7 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) return true; if(input->name() == "Displacement" && current_type != SHADER_TYPE_DISPLACEMENT) return true; - if(input->name() == "Normal") + if(input->name() == "Normal" && current_type != SHADER_TYPE_BUMP) return true; } else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) { @@ -684,6 +684,8 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) ss->Shader("surface", name, id(node).c_str()); else if(current_type == SHADER_TYPE_DISPLACEMENT) ss->Shader("displacement", name, id(node).c_str()); + else if(current_type == SHADER_TYPE_BUMP) + ss->Shader("displacement", name, id(node).c_str()); else assert(0); @@ -1055,6 +1057,12 @@ OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph generate_nodes(dependencies); output->compile(*this); } + else if(type == SHADER_TYPE_BUMP) { + /* generate bump shader */ + find_dependencies(dependencies, output->input("Normal")); + generate_nodes(dependencies); + output->compile(*this); + } else if(type == SHADER_TYPE_VOLUME) { /* generate volume shader */ find_dependencies(dependencies, output->input("Volume")); @@ -1116,10 +1124,10 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader) if(shader->used && graph && output->input("Surface")->link) { shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); - if(shader->graph_bump) - shader->osl_surface_bump_ref = compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE); + if(shader->graph_bump && shader->displacement_method != DISPLACE_TRUE) + shader->osl_surface_bump_ref = compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP); else - shader->osl_surface_bump_ref = shader->osl_surface_ref; + shader->osl_surface_bump_ref = OSL::ShaderGroupRef(); shader->has_surface = true; } @@ -1147,13 +1155,9 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader) /* push state to array for lookup */ og->surface_state.push_back(shader->osl_surface_ref); - og->surface_state.push_back(shader->osl_surface_bump_ref); - - og->volume_state.push_back(shader->osl_volume_ref); og->volume_state.push_back(shader->osl_volume_ref); - - og->displacement_state.push_back(shader->osl_displacement_ref); og->displacement_state.push_back(shader->osl_displacement_ref); + og->bump_state.push_back(shader->osl_surface_bump_ref); } #else diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 9e72f197cce..8fec171b6fb 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -123,6 +123,8 @@ public: /* opencl images */ device_vector<uchar4> tex_image_byte4_packed; device_vector<float4> tex_image_float4_packed; + device_vector<uchar> tex_image_byte_packed; + device_vector<float> tex_image_float_packed; device_vector<uint4> tex_image_packed_info; KernelData data; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 1cd76ff2b39..9d8c9fed7af 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -635,6 +635,11 @@ DeviceRequestedFeatures Session::get_requested_device_features() } requested_features.use_object_motion |= object->use_motion | mesh->use_motion_blur; requested_features.use_camera_motion |= mesh->use_motion_blur; +#ifdef WITH_OPENSUBDIV + if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { + requested_features.use_patch_evaluation = true; + } +#endif } BakeManager *bake_manager = scene->bake_manager; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 4cdb878df45..10c3507e3f4 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -150,6 +150,12 @@ NODE_DEFINE(Shader) volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC); SOCKET_ENUM(volume_interpolation_method, "Volume Interpolation Method", volume_interpolation_method_enum, VOLUME_INTERPOLATION_LINEAR); + static NodeEnum displacement_method_enum; + displacement_method_enum.insert("bump", DISPLACE_BUMP); + displacement_method_enum.insert("true", DISPLACE_TRUE); + displacement_method_enum.insert("both", DISPLACE_BOTH); + SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP); + return type; } @@ -173,6 +179,8 @@ Shader::Shader() has_object_dependency = false; has_integrator_dependency = false; + displacement_method = DISPLACE_BUMP; + id = -1; used = false; @@ -213,6 +221,16 @@ void Shader::tag_update(Scene *scene) if(use_mis && has_surface_emission) scene->light_manager->need_update = true; + /* Special handle of background MIS light for now: for some reason it + * has use_mis set to false. We are quite close to release now, so + * better to be safe. + */ + if(this == scene->default_background && + scene->light_manager->has_background_light(scene)) + { + scene->light_manager->need_update = true; + } + /* quick detection of which kind of shaders we have to avoid loading * e.g. surface attributes when there is only a volume shader. this could * be more fine grained but it's better than nothing */ @@ -232,6 +250,10 @@ void Shader::tag_update(Scene *scene) attributes.clear(); foreach(ShaderNode *node, graph->nodes) node->attributes(this, &attributes); + + if(has_displacement && displacement_method == DISPLACE_BOTH) { + attributes.add(ATTR_STD_POSITION_UNDISPLACED); + } /* compare if the attributes changed, mesh manager will check * need_update_attributes, update the relevant meshes and clear it. */ @@ -304,14 +326,11 @@ uint ShaderManager::get_attribute_id(AttributeStandard std) return (uint)std; } -int ShaderManager::get_shader_id(Shader *shader, Mesh *mesh, bool smooth) +int ShaderManager::get_shader_id(Shader *shader, bool smooth) { /* get a shader id to pass to the kernel */ - int id = shader->id*2; - - /* index depends bump since this setting is not in the shader */ - if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE) - id += 1; + int id = shader->id; + /* smooth flag */ if(smooth) id |= SHADER_SMOOTH_NORMAL; @@ -360,7 +379,7 @@ void ShaderManager::device_update_common(Device *device, if(scene->shaders.size() == 0) return; - uint shader_flag_size = scene->shaders.size()*4; + uint shader_flag_size = scene->shaders.size()*2; uint *shader_flag = dscene->shader_flag.resize(shader_flag_size); uint i = 0; bool has_volumes = false; @@ -398,15 +417,14 @@ void ShaderManager::device_update_common(Device *device, flag |= SD_VOLUME_CUBIC; if(shader->graph_bump) flag |= SD_HAS_BUMP; - - /* regular shader */ - shader_flag[i++] = flag; - shader_flag[i++] = shader->pass_id; + if(shader->displacement_method != DISPLACE_BUMP) + flag |= SD_HAS_DISPLACEMENT; /* shader with bump mapping */ - if(shader->graph_bump) + if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump) flag |= SD_HAS_BSSRDF_BUMP; + /* regular shader */ shader_flag[i++] = flag; shader_flag[i++] = shader->pass_id; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index dc57ed4e4eb..696e22bc3c9 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -66,6 +66,14 @@ enum VolumeInterpolation { VOLUME_NUM_INTERPOLATION, }; +enum DisplacementMethod { + DISPLACE_BUMP = 0, + DISPLACE_TRUE = 1, + DISPLACE_BOTH = 2, + + DISPLACE_NUM_METHODS, +}; + /* Shader describing the appearance of a Mesh, Light or Background. * * While there is only a single shader graph, it has three outputs: surface, @@ -110,6 +118,9 @@ public: bool has_object_dependency; bool has_integrator_dependency; + /* displacement */ + DisplacementMethod displacement_method; + /* requested mesh attributes */ AttributeRequestSet attributes; @@ -162,7 +173,7 @@ public: uint get_attribute_id(AttributeStandard std); /* get shader id for mesh faces */ - int get_shader_id(Shader *shader, Mesh *mesh = NULL, bool smooth = false); + int get_shader_id(Shader *shader, bool smooth = false); /* add default shaders to scene, to use as default for things that don't * have any shader assigned explicitly */ diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 1a166885e2b..069c3e3043a 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -63,7 +63,6 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene for(i = 0; i < scene->shaders.size(); i++) { svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); - svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); } foreach(Shader *shader, scene->shaders) { @@ -147,9 +146,8 @@ int SVMCompiler::stack_size(SocketType::Type type) return size; } -int SVMCompiler::stack_find_offset(SocketType::Type type) +int SVMCompiler::stack_find_offset(int size) { - int size = stack_size(type); int offset = -1; /* find free space in stack & mark as used */ @@ -176,6 +174,11 @@ int SVMCompiler::stack_find_offset(SocketType::Type type) return 0; } +int SVMCompiler::stack_find_offset(SocketType::Type type) +{ + return stack_find_offset(stack_size(type)); +} + void SVMCompiler::stack_clear_offset(SocketType::Type type, int offset) { int size = stack_size(type); @@ -648,6 +651,9 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty case SHADER_TYPE_DISPLACEMENT: clin = node->input("Displacement"); break; + case SHADER_TYPE_BUMP: + clin = node->input("Normal"); + break; default: assert(0); break; @@ -664,6 +670,13 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty output->stack_offset = SVM_STACK_INVALID; } + /* for the bump shader we need add a node to store the shader state */ + int bump_state_offset = SVM_STACK_INVALID; + if(type == SHADER_TYPE_BUMP) { + bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE); + add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset); + } + if(shader->used) { if(clin->link) { bool generate = false; @@ -681,6 +694,9 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty generate = true; shader->has_displacement = true; break; + case SHADER_TYPE_BUMP: /* generate bump shader */ + generate = true; + break; default: break; } @@ -697,13 +713,21 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty node->compile(*this); } + /* add node to restore state after bump shader has finished */ + if(type == SHADER_TYPE_BUMP) { + add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset); + } + /* if compile failed, generate empty shader */ if(compile_failed) { svm_nodes.clear(); compile_failed = false; } - add_node(NODE_END, 0, 0, 0); + /* for bump shaders we fall thru to the surface shader, but if this is any other kind of shader it ends here */ + if(type != SHADER_TYPE_BUMP) { + add_node(NODE_END, 0, 0, 0); + } } void SVMCompiler::compile(Scene *scene, @@ -753,19 +777,22 @@ void SVMCompiler::compile(Scene *scene, shader->has_object_dependency = false; shader->has_integrator_dependency = false; + /* generate bump shader */ + if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump) { + scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL); + compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP); + global_svm_nodes[index].y = global_svm_nodes.size(); + global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); + } + /* generate surface shader */ { scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL); compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); - global_svm_nodes[index*2 + 0].y = global_svm_nodes.size(); - global_svm_nodes[index*2 + 1].y = global_svm_nodes.size(); - global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); - } - - if(shader->graph_bump) { - scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL); - compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE); - global_svm_nodes[index*2 + 1].y = global_svm_nodes.size(); + /* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */ + if(shader->displacement_method == DISPLACE_TRUE || !shader->graph_bump) { + global_svm_nodes[index].y = global_svm_nodes.size(); + } global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); } @@ -773,8 +800,7 @@ void SVMCompiler::compile(Scene *scene, { scoped_timer timer((summary != NULL)? &summary->time_generate_volume: NULL); compile_type(shader, shader->graph, SHADER_TYPE_VOLUME); - global_svm_nodes[index*2 + 0].z = global_svm_nodes.size(); - global_svm_nodes[index*2 + 1].z = global_svm_nodes.size(); + global_svm_nodes[index].z = global_svm_nodes.size(); global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); } @@ -782,8 +808,7 @@ void SVMCompiler::compile(Scene *scene, { scoped_timer timer((summary != NULL)? &summary->time_generate_displacement: NULL); compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT); - global_svm_nodes[index*2 + 0].w = global_svm_nodes.size(); - global_svm_nodes[index*2 + 1].w = global_svm_nodes.size(); + global_svm_nodes[index].w = global_svm_nodes.size(); global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); } diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index e14d57d7601..99e91ca0c3e 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -99,6 +99,7 @@ public: int stack_assign(ShaderInput *input); int stack_assign_if_linked(ShaderInput *input); int stack_assign_if_linked(ShaderOutput *output); + int stack_find_offset(int size); int stack_find_offset(SocketType::Type type); void stack_clear_offset(SocketType::Type type, int offset); void stack_link(ShaderInput *input, ShaderOutput *output); diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt index db497013693..dafb807bdf3 100644 --- a/intern/cycles/subd/CMakeLists.txt +++ b/intern/cycles/subd/CMakeLists.txt @@ -16,18 +16,16 @@ set(SRC subd_dice.cpp subd_patch.cpp subd_split.cpp + subd_patch_table.cpp ) set(SRC_HEADERS subd_dice.h subd_patch.h + subd_patch_table.h subd_split.h ) -if(WITH_CYCLES_OPENSUBDIV) - add_definitions(-DWITH_OPENSUBDIV) -endif() - include_directories(${INC}) include_directories(SYSTEM ${INC_SYS}) diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index 36981a20f3c..a1bd349b167 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -57,7 +57,7 @@ void EdgeDice::reserve(int num_verts) Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); - mesh_P = &mesh->verts[0]; + mesh_P = mesh->verts.data(); mesh_N = attr_vN->data_float3(); } diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h index 3002ec780e8..33d13a4ab3a 100644 --- a/intern/cycles/subd/subd_dice.h +++ b/intern/cycles/subd/subd_dice.h @@ -49,7 +49,7 @@ struct SubdParams { test_steps = 3; split_threshold = 1; - dicing_rate = 0.1f; + dicing_rate = 1.0f; max_level = 12; camera = NULL; } diff --git a/intern/cycles/subd/subd_patch_table.cpp b/intern/cycles/subd/subd_patch_table.cpp new file mode 100644 index 00000000000..62572efa88a --- /dev/null +++ b/intern/cycles/subd/subd_patch_table.cpp @@ -0,0 +1,297 @@ +/* + * Based on code from OpenSubdiv released under this license: + * + * Copyright 2014 DreamWorks Animation LLC. + * + * Licensed under the Apache License, Version 2.0 (the "Apache License") + * with the following modification; you may not use this file except in + * compliance with the Apache License and the following modification to it: + * Section 6. Trademarks. is deleted and replaced with: + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor + * and its affiliates, except as required to comply with Section 4(c) of + * the License and to reproduce the content of the NOTICE file. + * + * You may obtain a copy of the Apache License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Apache License with the above modification is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the Apache License for the specific + * language governing permissions and limitations under the Apache License. + * + */ + +#include "subd_patch_table.h" +#include "kernel_types.h" + +#include "util_math.h" + +#ifdef WITH_OPENSUBDIV +#include <opensubdiv/far/patchTable.h> +#endif + +CCL_NAMESPACE_BEGIN + +#ifdef WITH_OPENSUBDIV + +using namespace OpenSubdiv; + +/* functions for building patch maps */ + +struct PatchMapQuadNode { + /* sets all the children to point to the patch of index */ + void set_child(int index) + { + for (int i = 0; i < 4; i++) { + children[i] = index | PATCH_MAP_NODE_IS_SET | PATCH_MAP_NODE_IS_LEAF; + } + } + + /* sets the child in quadrant to point to the node or patch of the given index */ + void set_child(unsigned char quadrant, int index, bool is_leaf=true) + { + assert(quadrant < 4); + children[quadrant] = index | PATCH_MAP_NODE_IS_SET | (is_leaf ? PATCH_MAP_NODE_IS_LEAF : 0); + } + + uint children[4]; +}; + +template<class T> +static int resolve_quadrant(T& median, T& u, T& v) +{ + int quadrant = -1; + + if(u < median) { + if(v < median) { + quadrant = 0; + } + else { + quadrant = 1; + v -= median; + } + } + else { + if(v < median) { + quadrant = 3; + } + else { + quadrant = 2; + v -= median; + } + u -= median; + } + + return quadrant; +} + +static void build_patch_map(PackedPatchTable& table, OpenSubdiv::Far::PatchTable* patch_table, int offset) +{ + int num_faces = 0; + + for(int array = 0; array < table.num_arrays; array++) { + Far::ConstPatchParamArray params = patch_table->GetPatchParams(array); + + for(int j = 0; j < patch_table->GetNumPatches(array); j++) { + num_faces = max(num_faces, (int)params[j].GetFaceId()); + } + } + num_faces++; + + vector<PatchMapQuadNode> quadtree; + quadtree.reserve(num_faces + table.num_patches); + quadtree.resize(num_faces); + + /* adjust offsets to make indices relative to the table */ + int handle_index = -(table.num_patches * PATCH_HANDLE_SIZE); + offset += table.total_size(); + + /* populate the quadtree from the FarPatchArrays sub-patches */ + for(int array = 0; array < table.num_arrays; array++) { + Far::ConstPatchParamArray params = patch_table->GetPatchParams(array); + + for(int i = 0; i < patch_table->GetNumPatches(array); i++, handle_index += PATCH_HANDLE_SIZE) { + const Far::PatchParam& param = params[i]; + unsigned short depth = param.GetDepth(); + + PatchMapQuadNode* node = &quadtree[params[i].GetFaceId()]; + + if(depth == (param.NonQuadRoot() ? 1 : 0)) { + /* special case : regular BSpline face w/ no sub-patches */ + node->set_child(handle_index + offset); + continue; + } + + int u = param.GetU(); + int v = param.GetV(); + int pdepth = param.NonQuadRoot() ? depth-2 : depth-1; + int half = 1 << pdepth; + + for(int j = 0; j < depth; j++) { + int delta = half >> 1; + + int quadrant = resolve_quadrant(half, u, v); + assert(quadrant >= 0); + + half = delta; + + if(j == pdepth) { + /* we have reached the depth of the sub-patch : add a leaf */ + assert(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)); + node->set_child(quadrant, handle_index + offset, true); + break; + } + else { + /* travel down the child node of the corresponding quadrant */ + if(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)) { + /* create a new branch in the quadrant */ + quadtree.push_back(PatchMapQuadNode()); + + int idx = (int)quadtree.size() - 1; + node->set_child(quadrant, idx*4 + offset, false); + + node = &quadtree[idx]; + } + else { + /* travel down an existing branch */ + uint idx = node->children[quadrant] & PATCH_MAP_NODE_INDEX_MASK; + node = &(quadtree[(idx - offset)/4]); + } + } + } + } + } + + /* copy into table */ + assert(table.table.size() == table.total_size()); + uint map_offset = table.total_size(); + + table.num_nodes = quadtree.size() * 4; + table.table.resize(table.total_size()); + + uint* data = &table.table[map_offset]; + + for(int i = 0; i < quadtree.size(); i++) { + for(int j = 0; j < 4; j++) { + assert(quadtree[i].children[j] & PATCH_MAP_NODE_IS_SET); + *(data++) = quadtree[i].children[j]; + } + } +} + +#endif + +/* packed patch table functions */ + +size_t PackedPatchTable::total_size() +{ + return num_arrays * PATCH_ARRAY_SIZE + + num_indices + + num_patches * (PATCH_PARAM_SIZE + PATCH_HANDLE_SIZE) + + num_nodes * PATCH_NODE_SIZE; +} + +void PackedPatchTable::pack(Far::PatchTable* patch_table, int offset) +{ + num_arrays = 0; + num_patches = 0; + num_indices = 0; + num_nodes = 0; + +#ifdef WITH_OPENSUBDIV + num_arrays = patch_table->GetNumPatchArrays(); + + for(int i = 0; i < num_arrays; i++) { + int patches = patch_table->GetNumPatches(i); + int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices(); + + num_patches += patches; + num_indices += patches * num_control; + } + + table.resize(total_size()); + uint* data = table.data(); + + uint* array = data; + uint* index = array + num_arrays * PATCH_ARRAY_SIZE; + uint* param = index + num_indices; + uint* handle = param + num_patches * PATCH_PARAM_SIZE; + + uint current_param = 0; + + for(int i = 0; i < num_arrays; i++) { + *(array++) = patch_table->GetPatchArrayDescriptor(i).GetType(); + *(array++) = patch_table->GetNumPatches(i); + *(array++) = (index - data) + offset; + *(array++) = (param - data) + offset; + + Far::ConstIndexArray indices = patch_table->GetPatchArrayVertices(i); + + for(int j = 0; j < indices.size(); j++) { + *(index++) = indices[j]; + } + + const Far::PatchParamTable& param_table = patch_table->GetPatchParamTable(); + + int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices(); + int patches = patch_table->GetNumPatches(i); + + for(int j = 0; j < patches; j++, current_param++) { + *(param++) = param_table[current_param].field0; + *(param++) = param_table[current_param].field1; + + *(handle++) = (array - data) - PATCH_ARRAY_SIZE + offset; + *(handle++) = (param - data) - PATCH_PARAM_SIZE + offset; + *(handle++) = j * num_control; + } + } + + build_patch_map(*this, patch_table, offset); +#else + (void)patch_table; + (void)offset; +#endif +} + +void PackedPatchTable::copy_adjusting_offsets(uint* dest, int doffset) +{ + uint* src = table.data(); + + /* arrays */ + for(int i = 0; i < num_arrays; i++) { + *(dest++) = *(src++); + *(dest++) = *(src++); + *(dest++) = *(src++) + doffset; + *(dest++) = *(src++) + doffset; + } + + /* indices */ + for(int i = 0; i < num_indices; i++) { + *(dest++) = *(src++); + } + + /* params */ + for(int i = 0; i < num_patches; i++) { + *(dest++) = *(src++); + *(dest++) = *(src++); + } + + /* handles */ + for(int i = 0; i < num_patches; i++) { + *(dest++) = *(src++) + doffset; + *(dest++) = *(src++) + doffset; + *(dest++) = *(src++); + } + + /* nodes */ + for(int i = 0; i < num_nodes; i++) { + *(dest++) = *(src++) + doffset; + } +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/subd/subd_patch_table.h b/intern/cycles/subd/subd_patch_table.h new file mode 100644 index 00000000000..3166a1691d8 --- /dev/null +++ b/intern/cycles/subd/subd_patch_table.h @@ -0,0 +1,63 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SUBD_PATCH_TABLE_H__ +#define __SUBD_PATCH_TABLE_H__ + +#include "util_types.h" +#include "util_vector.h" + +#ifdef WITH_OPENSUBDIV +#ifdef _MSC_VER +# include "iso646.h" +#endif + +#include <opensubdiv/far/patchTable.h> +#endif + +CCL_NAMESPACE_BEGIN + +#ifdef WITH_OPENSUBDIV +using namespace OpenSubdiv; +#else +/* forward declare for when OpenSubdiv is unavailable */ +namespace Far { struct PatchTable; } +#endif + +#define PATCH_ARRAY_SIZE 4 +#define PATCH_PARAM_SIZE 2 +#define PATCH_HANDLE_SIZE 3 +#define PATCH_NODE_SIZE 1 + +struct PackedPatchTable { + array<uint> table; + + size_t num_arrays; + size_t num_indices; + size_t num_patches; + size_t num_nodes; + + /* calculated size from num_* members */ + size_t total_size(); + + void pack(Far::PatchTable* patch_table, int offset = 0); + void copy_adjusting_offsets(uint* dest, int doffset); +}; + +CCL_NAMESPACE_END + +#endif /* __SUBD_PATCH_TABLE_H__ */ + diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt index 80fe893826a..9af777fb9dd 100644 --- a/intern/cycles/test/CMakeLists.txt +++ b/intern/cycles/test/CMakeLists.txt @@ -26,6 +26,7 @@ set(ALL_CYCLES_LIBRARIES cycles_device cycles_bvh cycles_graph + cycles_subd cycles_util ${OPENIMAGEIO_LIBRARIES} ) @@ -41,6 +42,16 @@ if(WITH_IMAGE_OPENJPEG AND NOT WITH_SYSTEM_OPENJPEG) extern_openjpeg ) endif() +if(WITH_CYCLES_OPENSUBDIV) + add_definitions(-DWITH_OPENSUBDIV) + include_directories( + SYSTEM + ${OPENSUBDIV_INCLUDE_DIR} + ) + list(APPEND ALL_CYCLES_LIBRARIES + ${OPENSUBDIV_LIBRARIES} + ) +endif() list(APPEND ALL_CYCLES_LIBRARIES ${BOOST_LIBRARIES} ) diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp index 633e517ce9f..60e41be16aa 100644 --- a/intern/cycles/test/render_graph_finalize_test.cpp +++ b/intern/cycles/test/render_graph_finalize_test.cpp @@ -403,6 +403,26 @@ TEST(render_graph, constant_fold_invert_fac_0) /* * Tests: + * - Folding of Invert with zero Fac and constant input. + */ +TEST(render_graph, constant_fold_invert_fac_0_const) +{ + DEFINE_COMMON_VARIABLES(builder, log); + + EXPECT_ANY_MESSAGE(log); + CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to constant (0.2, 0.5, 0.8)."); + + builder + .add_node(ShaderNodeBuilder<InvertNode>("Invert") + .set("Fac", 0.0f) + .set("Color", make_float3(0.2f, 0.5f, 0.8f))) + .output_color("Invert::Color"); + + graph.finalize(&scene); +} + +/* + * Tests: * - Folding of MixRGB Add with all constant inputs (clamp false). */ TEST(render_graph, constant_fold_mix_add) @@ -1344,6 +1364,33 @@ TEST(render_graph, constant_fold_rgb_curves_fac_0) graph.finalize(&scene); } + +/* + * Tests: + * - Folding of RGB Curves with zero Fac and all constant inputs. + */ +TEST(render_graph, constant_fold_rgb_curves_fac_0_const) +{ + DEFINE_COMMON_VARIABLES(builder, log); + + EXPECT_ANY_MESSAGE(log); + CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to constant (0.3, 0.5, 0.7)."); + + array<float3> curve; + init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257); + + builder + .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves") + .set(&CurvesNode::curves, curve) + .set(&CurvesNode::min_x, 0.1f) + .set(&CurvesNode::max_x, 0.9f) + .set("Fac", 0.0f) + .set("Color", make_float3(0.3f, 0.5f, 0.7f))) + .output_color("Curves::Color"); + + graph.finalize(&scene); +} + /* * Tests: * - Folding of Vector Curves with all constant inputs. diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index e6140b3ed09..f5674bdc15c 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -25,10 +25,6 @@ set(SRC util_windows.cpp ) -if(NOT CYCLES_STANDALONE_REPOSITORY) - add_definitions(-DWITH_GLEW_MX) -endif() - if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) list(APPEND SRC util_view.cpp @@ -71,6 +67,7 @@ set(SRC_HEADERS util_ssef.h util_ssei.h util_stack_allocator.h + util_static_assert.h util_stats.h util_string.h util_system.h diff --git a/intern/cycles/util/util_debug.h b/intern/cycles/util/util_debug.h index 1787ff648ee..73fd228b5d9 100644 --- a/intern/cycles/util/util_debug.h +++ b/intern/cycles/util/util_debug.h @@ -20,6 +20,8 @@ #include <cassert> #include <iostream> +#include "util_static_assert.h" + CCL_NAMESPACE_BEGIN /* Global storage for all sort of flags used to fine-tune behavior of particular diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h index ae85ab3a915..5db3384cda4 100644 --- a/intern/cycles/util/util_half.h +++ b/intern/cycles/util/util_half.h @@ -33,17 +33,21 @@ CCL_NAMESPACE_BEGIN #else +/* CUDA has its own half data type, no need to define then */ +#ifndef __KERNEL_CUDA__ typedef unsigned short half; +#endif + struct half4 { half x, y, z, w; }; #ifdef __KERNEL_CUDA__ ccl_device_inline void float4_store_half(half *h, float4 f, float scale) { - h[0] = __float2half_rn(f.x * scale); - h[1] = __float2half_rn(f.y * scale); - h[2] = __float2half_rn(f.z * scale); - h[3] = __float2half_rn(f.w * scale); + h[0] = __float2half(f.x * scale); + h[1] = __float2half(f.y * scale); + h[2] = __float2half(f.z * scale); + h[3] = __float2half(f.w * scale); } #else diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 13aba0646d2..89a882d9b9d 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -572,6 +572,12 @@ ccl_device_inline float3 safe_normalize(const float3 a) return (t != 0.0f)? a/t: a; } +ccl_device_inline float3 safe_normalize_len(const float3 a, float *t) +{ + *t = len(a); + return (*t != 0.0f)? a/(*t): a; +} + #ifndef __KERNEL_OPENCL__ ccl_device_inline bool operator==(const float3 a, const float3 b) diff --git a/intern/cycles/util/util_static_assert.h b/intern/cycles/util/util_static_assert.h new file mode 100644 index 00000000000..1b945705145 --- /dev/null +++ b/intern/cycles/util/util_static_assert.h @@ -0,0 +1,64 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTIL_STATIC_ASSERT_H__ +#define __UTIL_STATIC_ASSERT_H__ + +CCL_NAMESPACE_BEGIN + +/* TODO(sergey): In theory CUDA might work with own static assert + * implementation since it's just pure C++. + */ +#ifndef __KERNEL_GPU__ +# if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +/* C++11 has built-in static_assert() */ +# else /* C++11 or MSVC2015 */ +template <bool Test> class StaticAssertFailure; +template <> class StaticAssertFailure<true> {}; +# define _static_assert_private_glue_impl(A, B) A ## B +# define _static_assert_glue(A, B) _static_assert_private_glue_impl(A, B) +# ifdef __COUNTER__ +# define static_assert(condition, message) \ + enum {_static_assert_glue(q_static_assert_result, __COUNTER__) = sizeof(StaticAssertFailure<!!(condition)>)} // NOLINT +# else /* __COUNTER__ */ +# define static_assert(condition, message) \ + enum {_static_assert_glue(q_static_assert_result, __LINE__) = sizeof(StaticAssertFailure<!!(condition)>)} // NOLINT +# endif /* __COUNTER__ */ +# endif /* C++11 or MSVC2015 */ +#else /* __KERNEL_GPU__ */ +# define static_assert(statement, message) +#endif /* __KERNEL_GPU__ */ + +/* TODO(sergey): For until C++11 is a bare minimum for us, + * we do a bit of a trickery to show meaningful message so + * it's more or less clear what's wrong when building without + * C++11. + * + * The thing here is: our non-C++11 implementation doesn't + * have a way to print any message after preprocessor + * substitution so we rely on the message which is passed to + * static_assert() since that's the only message visible when + * compilation fails. + * + * After C++11 bump it should be possible to glue structure + * name to the error message, + */ +# define static_assert_align(st, align) \ + static_assert((sizeof(st) % (align) == 0), "Structure must be strictly aligned") // NOLINT + +CCL_NAMESPACE_END + +#endif /* __UTIL_STATIC_ASSERT_H__ */ diff --git a/intern/cycles/util/util_texture.h b/intern/cycles/util/util_texture.h index 2ef47283029..aff928ea2ee 100644 --- a/intern/cycles/util/util_texture.h +++ b/intern/cycles/util/util_texture.h @@ -24,58 +24,58 @@ CCL_NAMESPACE_BEGIN /* CPU */ #define TEX_NUM_FLOAT4_CPU 1024 #define TEX_NUM_BYTE4_CPU 1024 +#define TEX_NUM_HALF4_CPU 1024 #define TEX_NUM_FLOAT_CPU 1024 #define TEX_NUM_BYTE_CPU 1024 -#define TEX_NUM_HALF4_CPU 1024 #define TEX_NUM_HALF_CPU 1024 #define TEX_START_FLOAT4_CPU 0 #define TEX_START_BYTE4_CPU TEX_NUM_FLOAT4_CPU -#define TEX_START_FLOAT_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU) -#define TEX_START_BYTE_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_FLOAT_CPU) -#define TEX_START_HALF4_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_FLOAT_CPU + TEX_NUM_BYTE_CPU) -#define TEX_START_HALF_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_FLOAT_CPU + TEX_NUM_BYTE_CPU + TEX_NUM_HALF4_CPU) +#define TEX_START_HALF4_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU) +#define TEX_START_FLOAT_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_HALF4_CPU) +#define TEX_START_BYTE_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_HALF4_CPU + TEX_NUM_FLOAT_CPU) +#define TEX_START_HALF_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_HALF4_CPU + TEX_NUM_FLOAT_CPU + TEX_NUM_BYTE_CPU) /* CUDA (Geforce 4xx and 5xx) */ #define TEX_NUM_FLOAT4_CUDA 5 -#define TEX_NUM_BYTE4_CUDA 88 +#define TEX_NUM_BYTE4_CUDA 85 +#define TEX_NUM_HALF4_CUDA 0 #define TEX_NUM_FLOAT_CUDA 0 #define TEX_NUM_BYTE_CUDA 0 -#define TEX_NUM_HALF4_CUDA 0 #define TEX_NUM_HALF_CUDA 0 #define TEX_START_FLOAT4_CUDA 0 #define TEX_START_BYTE4_CUDA TEX_NUM_FLOAT4_CUDA -#define TEX_START_FLOAT_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA) -#define TEX_START_BYTE_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_FLOAT_CUDA) -#define TEX_START_HALF4_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_FLOAT_CUDA + TEX_NUM_BYTE_CUDA) -#define TEX_START_HALF_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_FLOAT_CUDA + TEX_NUM_BYTE_CUDA + TEX_NUM_HALF4_CUDA) +#define TEX_START_HALF4_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA) +#define TEX_START_FLOAT_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_HALF4_CUDA) +#define TEX_START_BYTE_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_HALF4_CUDA + TEX_NUM_FLOAT_CUDA) +#define TEX_START_HALF_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_HALF4_CUDA + TEX_NUM_FLOAT_CUDA + TEX_NUM_BYTE_CUDA) /* CUDA (Kepler, Geforce 6xx and above) */ #define TEX_NUM_FLOAT4_CUDA_KEPLER 1024 #define TEX_NUM_BYTE4_CUDA_KEPLER 1024 +#define TEX_NUM_HALF4_CUDA_KEPLER 1024 #define TEX_NUM_FLOAT_CUDA_KEPLER 1024 #define TEX_NUM_BYTE_CUDA_KEPLER 1024 -#define TEX_NUM_HALF4_CUDA_KEPLER 0 -#define TEX_NUM_HALF_CUDA_KEPLER 0 +#define TEX_NUM_HALF_CUDA_KEPLER 1024 #define TEX_START_FLOAT4_CUDA_KEPLER 0 #define TEX_START_BYTE4_CUDA_KEPLER TEX_NUM_FLOAT4_CUDA_KEPLER -#define TEX_START_FLOAT_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER) -#define TEX_START_BYTE_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_FLOAT_CUDA_KEPLER) -#define TEX_START_HALF4_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_FLOAT_CUDA_KEPLER + TEX_NUM_BYTE_CUDA_KEPLER) -#define TEX_START_HALF_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_FLOAT_CUDA_KEPLER + TEX_NUM_BYTE_CUDA_KEPLER + TEX_NUM_HALF4_CUDA_KEPLER) +#define TEX_START_HALF4_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER) +#define TEX_START_FLOAT_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_HALF4_CUDA_KEPLER) +#define TEX_START_BYTE_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_HALF4_CUDA_KEPLER + TEX_NUM_FLOAT_CUDA_KEPLER) +#define TEX_START_HALF_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_HALF4_CUDA_KEPLER + TEX_NUM_FLOAT_CUDA_KEPLER + TEX_NUM_BYTE_CUDA_KEPLER) /* OpenCL */ #define TEX_NUM_FLOAT4_OPENCL 1024 #define TEX_NUM_BYTE4_OPENCL 1024 -#define TEX_NUM_FLOAT_OPENCL 0 -#define TEX_NUM_BYTE_OPENCL 0 #define TEX_NUM_HALF4_OPENCL 0 +#define TEX_NUM_FLOAT_OPENCL 1024 +#define TEX_NUM_BYTE_OPENCL 1024 #define TEX_NUM_HALF_OPENCL 0 #define TEX_START_FLOAT4_OPENCL 0 #define TEX_START_BYTE4_OPENCL TEX_NUM_FLOAT4_OPENCL -#define TEX_START_FLOAT_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL) -#define TEX_START_BYTE_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_FLOAT_OPENCL) -#define TEX_START_HALF4_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_FLOAT_OPENCL + TEX_NUM_BYTE_OPENCL) -#define TEX_START_HALF_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_FLOAT_OPENCL + TEX_NUM_BYTE_OPENCL + TEX_NUM_HALF4_OPENCL) +#define TEX_START_HALF4_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL) +#define TEX_START_FLOAT_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_HALF4_OPENCL) +#define TEX_START_BYTE_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_HALF4_OPENCL + TEX_NUM_FLOAT_OPENCL) +#define TEX_START_HALF_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_HALF4_OPENCL + TEX_NUM_FLOAT_OPENCL + TEX_NUM_BYTE_OPENCL) /* Color to use when textures are not found. */ diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index 6fed18a3db8..bfc8f55feed 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -323,6 +323,15 @@ ccl_device_inline Transform transform_clear_scale(const Transform& tfm) return ntfm; } +ccl_device_inline Transform transform_empty() +{ + return make_transform( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0); +} + #endif /* Motion Transform */ diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h index 6f8c3f6f3de..546b17570bb 100644 --- a/intern/cycles/util/util_vector.h +++ b/intern/cycles/util/util_vector.h @@ -222,6 +222,11 @@ public: return datasize_; } + T* data() + { + return data_; + } + const T* data() const { return data_; diff --git a/intern/elbeem/intern/controlparticles.cpp b/intern/elbeem/intern/controlparticles.cpp index 526fac0cc6b..f6329ad4b67 100644 --- a/intern/elbeem/intern/controlparticles.cpp +++ b/intern/elbeem/intern/controlparticles.cpp @@ -1316,7 +1316,8 @@ void ControlParticles::finishControl(std::vector<ControlForces> &forces, LbmFloa if(cvweight>1.) { cvweight = 1.; } // thus cvweight is in the range of 0..influenceVelocity, currently not normalized by numCParts cvweight *= ivel; - if(cvweight<0.) cvweight=0.; if(cvweight>1.) cvweight=1.; + if(cvweight<0.) cvweight=0.; + if(cvweight>1.) cvweight=1.; // LBM, FIXME todo use relaxation factor //pvel = (cvel*0.5 * cvweight) + (pvel * (1.0-cvweight)); forces[i].weightVel = cvweight; diff --git a/intern/elbeem/intern/isosurface.h b/intern/elbeem/intern/isosurface.h index 15b923866d3..30fd9adfee1 100644 --- a/intern/elbeem/intern/isosurface.h +++ b/intern/elbeem/intern/isosurface.h @@ -67,8 +67,10 @@ class IsoSurface : /*! set # of subdivisions, this has to be done before init! */ void setSubdivs(int s) { if(mInitDone) errFatal("IsoSurface::setSubdivs","Changing subdivs after init!", SIMWORLD_INITERROR); - if(s<1) s=1; if(s>10) s=10; - mSubdivs = s; } + if(s<1) s=1; + if(s>10) s=10; + mSubdivs = s; + } int getSubdivs() { return mSubdivs;} /*! set full edge settings, this has to be done before init! */ void setUseFulledgeArrays(bool set) { diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index f1484a298d3..ff1922af4f3 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -433,6 +433,7 @@ extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, GHOST_TButtonMask mask, int *isDown); +#ifdef WITH_INPUT_NDOF /*************************************************************************************** * Access to 3D mouse. ***************************************************************************************/ @@ -442,6 +443,7 @@ extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, * \param deadzone Deadzone of the 3D mouse (both for rotation and pan) relative to full range */ extern void GHOST_setNDOFDeadZone(float deadzone); +#endif /*************************************************************************************** diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 08045b93db9..03193d6e1da 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -377,11 +377,13 @@ public: */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0; +#ifdef WITH_INPUT_NDOF /** * Sets 3D mouse deadzone * \param deadzone: Deadzone of the 3D mouse (both for rotation and pan) relative to full range */ virtual void setNDOFDeadZone(float deadzone) = 0; +#endif /** * Toggles console diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 0dd5d15b011..9ee4599a4a6 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -172,8 +172,10 @@ typedef enum { GHOST_kEventWheel, /// Mouse wheel event GHOST_kEventTrackpad, /// Trackpad event +#ifdef WITH_INPUT_NDOF GHOST_kEventNDOFMotion, /// N degree of freedom device motion event GHOST_kEventNDOFButton, /// N degree of freedom device button event +#endif GHOST_kEventKeyDown, GHOST_kEventKeyUp, @@ -478,6 +480,7 @@ typedef enum { GHOST_kFinished } GHOST_TProgress; +#ifdef WITH_INPUT_NDOF typedef struct { /** N-degree of freedom device data v3 [GSoC 2010] */ // Each component normally ranges from -1 to +1, but can exceed that. @@ -497,6 +500,7 @@ typedef struct { GHOST_TButtonAction action; short button; } GHOST_TEventNDOFButtonData; +#endif // WITH_INPUT_NDOF typedef struct { /** The key code. */ diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index ccd7f57f9a4..41bc735e1e2 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -406,12 +406,13 @@ GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, } +#ifdef WITH_INPUT_NDOF void GHOST_setNDOFDeadZone(float deadzone) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); system->setNDOFDeadZone(deadzone); } - +#endif void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept) { diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp index abce3ea6588..64ee692797b 100644 --- a/intern/ghost/intern/GHOST_ContextWGL.cpp +++ b/intern/ghost/intern/GHOST_ContextWGL.cpp @@ -183,6 +183,7 @@ static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd, PIXELFORMATDESCRIPTOR !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */ !(pfd.iPixelType == PFD_TYPE_RGBA) || (pfd.cDepthBits < 16) || + (pfd.cColorBits > 32) || /* 64 bit formats disable aero */ (pfd.dwFlags & PFD_GENERIC_FORMAT)) /* no software renderers */ { return 0; diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index b4037896b93..754e1091860 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -22,9 +22,12 @@ /** \file ghost/intern/GHOST_EventNDOF.h * \ingroup GHOST - * Declaration of GHOST_EventManager class. */ +#ifndef WITH_INPUT_NDOF +# error NDOF code included in non-NDOF-enabled build +#endif + #ifndef __GHOST_EVENTNDOF_H__ #define __GHOST_EVENTNDOF_H__ diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index d3c70bbac50..83d06ef5871 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -21,6 +21,10 @@ * ***** END GPL LICENSE BLOCK ***** */ +#ifndef WITH_INPUT_NDOF +# error NDOF code included in non-NDOF-enabled build +#endif + #ifndef __GHOST_NDOFMANAGER_H__ #define __GHOST_NDOFMANAGER_H__ diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h index 464ba48145e..3f1bfcf57fc 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -24,8 +24,6 @@ #ifndef __GHOST_NDOFMANAGERCOCOA_H__ #define __GHOST_NDOFMANAGERCOCOA_H__ -#ifdef WITH_INPUT_NDOF - #include "GHOST_NDOFManager.h" // Event capture is handled within the NDOF manager on Macintosh, @@ -40,6 +38,4 @@ public: bool available(); }; - -#endif // WITH_INPUT_NDOF #endif // #include guard diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 6fee39dcb82..3cce6bf520b 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -21,8 +21,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef WITH_INPUT_NDOF - #define DEBUG_NDOF_DRIVER false #include "GHOST_NDOFManagerCocoa.h" @@ -115,13 +113,15 @@ static void* load_func(void* module, const char* func_name) #define LOAD_FUNC(name) name = (name##_ptr) load_func(module, #name) +static void* module; // handle to the whole driver + static bool load_driver_functions() { if (driver_loaded) { return true; } - void* module = dlopen("3DconnexionClient.framework/3DconnexionClient", RTLD_LAZY | RTLD_LOCAL); + module = dlopen("3DconnexionClient.framework/3DconnexionClient", RTLD_LAZY | RTLD_LOCAL); if (module) { LOAD_FUNC(SetConnexionHandlers); @@ -145,8 +145,6 @@ static bool load_driver_functions() has_old_driver = (SetConnexionClientButtonMask == NULL); } - - dlclose(module); // functions will remain loaded } #if DEBUG_NDOF_DRIVER else { @@ -161,6 +159,10 @@ static bool load_driver_functions() return driver_loaded; } +static void unload_driver() +{ + dlclose(module); +} static void DeviceAdded(uint32_t unused) { @@ -210,7 +212,9 @@ static void DeviceEvent(uint32_t unused, uint32_t msg_type, void* msg_arg) case kConnexionCmdHandleButtons: { int button_bits = has_old_driver ? s->buttons8 : s->buttons; +#ifdef DEBUG_NDOF_BUTTONS printf("button bits: 0x%08x\n", button_bits); +#endif ndof_manager->updateButtons(button_bits, now); ghost_system->notifyExternalEventProcessed(); break; @@ -266,6 +270,7 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() if (driver_loaded) { UnregisterConnexionClient(clientID); CleanupConnexionHandlers(); + unload_driver(); ghost_system = NULL; ndof_manager = NULL; @@ -276,5 +281,3 @@ bool GHOST_NDOFManagerCocoa::available() { return driver_loaded; } - -#endif // WITH_INPUT_NDOF diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp index 8fea2a0261b..ded13b5c094 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp @@ -21,8 +21,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef WITH_INPUT_NDOF - #include "GHOST_NDOFManagerUnix.h" #include "GHOST_System.h" @@ -144,5 +142,3 @@ bool GHOST_NDOFManagerUnix::processEvents() return anyProcessed; } - -#endif /* WITH_INPUT_NDOF */ diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.h b/intern/ghost/intern/GHOST_NDOFManagerUnix.h index 278a8cb6fe0..3fd171d9e76 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.h +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.h @@ -24,8 +24,6 @@ #ifndef __GHOST_NDOFMANAGERUNIX_H__ #define __GHOST_NDOFMANAGERUNIX_H__ -#ifdef WITH_INPUT_NDOF - #include "GHOST_NDOFManager.h" /* Event capture is handled within the NDOF manager on Linux, @@ -43,5 +41,4 @@ private: bool m_available; }; -#endif /* WITH_INPUT_NDOF */ #endif /* __GHOST_NDOFMANAGERUNIX_H__ */ diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp index 7ccd2e602b4..0023ee7e1d0 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp @@ -22,8 +22,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef WITH_INPUT_NDOF // use contents of this file - #include "GHOST_NDOFManagerWin32.h" @@ -40,5 +38,3 @@ bool GHOST_NDOFManagerWin32::available() // always available since RawInput is built into Windows return true; } - -#endif // WITH_INPUT_NDOF diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h index 9b5192817eb..2f7bc9ee732 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerWin32.h +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h @@ -25,8 +25,6 @@ #ifndef __GHOST_NDOFMANAGERWIN32_H__ #define __GHOST_NDOFMANAGERWIN32_H__ -#ifdef WITH_INPUT_NDOF - #include "GHOST_NDOFManager.h" @@ -37,6 +35,4 @@ public: bool available(); }; - -#endif // WITH_INPUT_NDOF #endif // #include guard diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index c53580818e6..56d68b98ce0 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -38,11 +38,13 @@ #include "GHOST_DisplayManager.h" #include "GHOST_EventManager.h" -#include "GHOST_NDOFManager.h" #include "GHOST_TimerTask.h" #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" +#ifdef WITH_INPUT_NDOF +# include "GHOST_NDOFManager.h" +#endif GHOST_System::GHOST_System() : m_nativePixel(false), @@ -292,14 +294,12 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown return success; } +#ifdef WITH_INPUT_NDOF void GHOST_System::setNDOFDeadZone(float deadzone) { -#ifdef WITH_INPUT_NDOF this->m_ndofManager->setDeadZone(deadzone); -#else - (void)deadzone; -#endif } +#endif GHOST_TSuccess GHOST_System::init() { @@ -345,6 +345,7 @@ GHOST_TSuccess GHOST_System::exit() delete m_ndofManager; m_ndofManager = NULL; #endif + return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index a10259bc9e9..af083996d91 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -48,7 +48,9 @@ class GHOST_Event; class GHOST_TimerManager; class GHOST_Window; class GHOST_WindowManager; +#ifdef WITH_INPUT_NDOF class GHOST_NDOFManager; +#endif /** * Implementation of platform independent functionality of the GHOST_ISystem @@ -236,6 +238,7 @@ public: */ GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const; +#ifdef WITH_INPUT_NDOF /*************************************************************************************** * Access to 3D mouse. ***************************************************************************************/ @@ -245,6 +248,7 @@ public: * \param deadzone: Deadzone of the 3D mouse (both for rotation and pan) relative to full range */ void setNDOFDeadZone(float deadzone); +#endif /*************************************************************************************** * Other (internal) functionality. diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 1ce8002520f..f884b0fadb1 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -57,7 +57,7 @@ #include "GHOST_WindowWin32.h" #ifdef WITH_INPUT_NDOF -#include "GHOST_NDOFManagerWin32.h" + #include "GHOST_NDOFManagerWin32.h" #endif // Key code values not found in winuser.h @@ -125,9 +125,9 @@ static void initRawInput() { #ifdef WITH_INPUT_NDOF -#define DEVICE_COUNT 2 + #define DEVICE_COUNT 2 #else -#define DEVICE_COUNT 1 + #define DEVICE_COUNT 1 #endif RAWINPUTDEVICE devices[DEVICE_COUNT]; diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 727bc9a01fb..653c0ccb472 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -838,7 +838,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) case KeyRelease: { XKeyEvent *xke = &(xe->xkey); - KeySym key_sym; + KeySym key_sym = XK_VoidSymbol; KeySym key_sym_str; char ascii; #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) @@ -870,26 +870,30 @@ GHOST_SystemX11::processEvent(XEvent *xe) * * To address this, we: * - * - Try to get a 'number' key_sym using XLookupKeysym (with or without shift modifier). + * - Try to get a 'number' key_sym using XLookupKeysym (with virtual shift modifier), + * in a very restrictive set of cases. * - Fallback to XLookupString to get a key_sym from active user-defined keymap. * - * Note that this enforces users to use an ascii-compatible keymap with Blender - but at least it gives - * predictable and consistent results. + * Note that: + * - This effectively 'lock' main number keys to always output number events (except when using alt-gr). + * - This enforces users to use an ascii-compatible keymap with Blender - but at least it gives + * predictable and consistent results. * * Also, note that nothing in XLib sources [1] makes it obvious why those two functions give different * key_sym results... * * [1] http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/KeyBind.c */ - if ((xke->keycode >= 10 && xke->keycode < 20)) { + /* Mode_switch 'modifier' is AltGr - when this one or Shift are enabled, we do not want to apply + * that 'forced number' hack. */ + const unsigned int mode_switch_mask = XkbKeysymToModifiers(xke->display, XK_Mode_switch); + const unsigned int number_hack_forbidden_kmods_mask = mode_switch_mask | ShiftMask; + if ((xke->keycode >= 10 && xke->keycode < 20) && ((xke->state & number_hack_forbidden_kmods_mask) == 0)) { key_sym = XLookupKeysym(xke, ShiftMask); if (!((key_sym >= XK_0) && (key_sym <= XK_9))) { - key_sym = XLookupKeysym(xke, 0); + key_sym = XK_VoidSymbol; } } - else { - key_sym = XLookupKeysym(xke, 0); - } if (!XLookupString(xke, &ascii, 1, &key_sym_str, NULL)) { ascii = '\0'; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 6a27d7aadf9..2aa950f8278 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -649,7 +649,7 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 3, 2, #endif - GHOST_OPENGL_WGL_CONTEXT_FLAGS, + (m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0), GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY); #else # error diff --git a/intern/itasc/ConstraintSet.cpp b/intern/itasc/ConstraintSet.cpp index e21cd36e4c8..0baf580ca68 100644 --- a/intern/itasc/ConstraintSet.cpp +++ b/intern/itasc/ConstraintSet.cpp @@ -145,27 +145,29 @@ bool ConstraintSet::closeLoop(){ //toggle=!toggle; //svd_boost_Macie(Jf,U,S,V,B,temp,1e-3*threshold,toggle); int ret = KDL::svd_eigen_HH(m_Jf,m_U,m_S,m_V,m_temp); - if(ret<0) - return false; + if(ret<0) + return false; // the reference point and frame of the jacobian is the base frame // m_externalPose-m_internalPose is the twist to extend the end effector // to get the required pose => change the reference point to the base frame Twist twist_delta(diff(m_internalPose,m_externalPose)); twist_delta=twist_delta.RefPoint(-m_internalPose.p); - for(unsigned int i=0;i<6;i++) - m_tdelta(i)=twist_delta(i); - //TODO: use damping in constraintset inversion? - for(unsigned int i=0;i<6;i++) - if(m_S(i)<m_threshold){ + for(unsigned int i=0;i<6;i++) + m_tdelta(i)=twist_delta(i); + //TODO: use damping in constraintset inversion? + for(unsigned int i=0;i<6;i++) { + if(m_S(i)<m_threshold){ m_B.row(i).setConstant(0.0); - }else - m_B.row(i) = m_U.col(i)/m_S(i); + } else { + m_B.row(i) = m_U.col(i)/m_S(i); + } + } - m_Jf_inv.noalias()=m_V*m_B; + m_Jf_inv.noalias()=m_V*m_B; - m_chi.noalias()+=m_Jf_inv*m_tdelta; - updateJacobian(); + m_chi.noalias()+=m_Jf_inv*m_tdelta; + updateJacobian(); // m_externalPose-m_internalPose in end effector frame // this is just to compare the pose, a different formula would work too return Equal(m_internalPose.Inverse()*m_externalPose,F_identity,m_threshold); diff --git a/intern/itasc/Scene.cpp b/intern/itasc/Scene.cpp index 7ed8fc4e63c..5768a994970 100644 --- a/intern/itasc/Scene.cpp +++ b/intern/itasc/Scene.cpp @@ -146,11 +146,11 @@ bool Scene::addObject(const std::string& name, Object* object, UncontrolledObjec bool Scene::addConstraintSet(const std::string& name,ConstraintSet* task,const std::string& object1,const std::string& object2, const std::string& ee1, const std::string& ee2) { - //Check if objects exist: - ObjectMap::iterator object1_it = objects.find(object1); - ObjectMap::iterator object2_it = objects.find(object2); - if(object1_it==objects.end()||object2_it==objects.end()) - return false; + //Check if objects exist: + ObjectMap::iterator object1_it = objects.find(object1); + ObjectMap::iterator object2_it = objects.find(object2); + if(object1_it==objects.end()||object2_it==objects.end()) + return false; int ee1_index = object1_it->second->object->addEndEffector(ee1); int ee2_index = object2_it->second->object->addEndEffector(ee2); if (ee1_index < 0 || ee2_index < 0) @@ -159,11 +159,11 @@ bool Scene::addConstraintSet(const std::string& name,ConstraintSet* task,const s constraints.insert(ConstraintMap::value_type(name,new ConstraintSet_struct( task,object1_it,ee1_index,object2_it,ee2_index, Range(m_ncTotal,task->getNrOfConstraints()),Range(6*m_nsets,6)))); - if(!result.second) - return false; - m_ncTotal+=task->getNrOfConstraints(); - m_nsets+=1; - return true; + if(!result.second) + return false; + m_ncTotal+=task->getNrOfConstraints(); + m_nsets+=1; + return true; } bool Scene::addSolver(Solver* _solver){ diff --git a/intern/itasc/WSDLSSolver.cpp b/intern/itasc/WSDLSSolver.cpp index 6fdd8e6e06c..2514dbb9041 100644 --- a/intern/itasc/WSDLSSolver.cpp +++ b/intern/itasc/WSDLSSolver.cpp @@ -60,7 +60,7 @@ bool WSDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& y e_scalar N, M; // Create the Weighted jacobian - m_AWq.noalias() = A*Wq; + m_AWq.noalias() = A*Wq; for (i=0; i<m_nc; i++) m_WyAWq.row(i) = Wy(i)*m_AWq.row(i); @@ -72,11 +72,11 @@ bool WSDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& y } else { ret = KDL::svd_eigen_HH(m_WyAWq,m_U,m_S,m_V,m_temp); } - if(ret<0) - return false; + if(ret<0) + return false; m_Wy_ydot = Wy.array() * ydot.array(); - m_WqV.noalias() = Wq*m_V; + m_WqV.noalias() = Wq*m_V; qdot.setZero(); e_scalar maxDeltaS = e_scalar(0.0); e_scalar prevS = e_scalar(0.0); diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc index 0cf6fcfef43..05bd3728f93 100644 --- a/intern/opensubdiv/opensubdiv_gpu_capi.cc +++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc @@ -115,7 +115,7 @@ static Transform g_transform; struct OpenSubdiv_GLMeshFVarData { OpenSubdiv_GLMeshFVarData() : - texture_buffer(0) { + texture_buffer(0), offset_buffer(0) { } ~OpenSubdiv_GLMeshFVarData() diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index 030953cf614..b54cadd40bc 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -892,18 +892,6 @@ style="stop-color:#ffedd5;stop-opacity:1;" /> </linearGradient> <linearGradient - inkscape:collect="always" - id="linearGradient24735"> - <stop - style="stop-color:#000000;stop-opacity:1;" - offset="0" - id="stop24737" /> - <stop - style="stop-color:#000000;stop-opacity:0;" - offset="1" - id="stop24739" /> - </linearGradient> - <linearGradient id="linearGradient24727"> <stop style="stop-color:#3d361a;stop-opacity:1;" @@ -1329,30 +1317,6 @@ y1="132.15414" x2="130.10634" y2="117.10313" /> - <linearGradient - id="linearGradient30777" - inkscape:collect="always"> - <stop - id="stop30779" - offset="0" - style="stop-color:#acacac;stop-opacity:1" /> - <stop - id="stop30781" - offset="1" - style="stop-color:black;stop-opacity:0;" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient29485"> - <stop - style="stop-color:black;stop-opacity:1;" - offset="0" - id="stop29487" /> - <stop - style="stop-color:black;stop-opacity:0;" - offset="1" - id="stop29489" /> - </linearGradient> <filter inkscape:collect="always" x="-0.55821538" @@ -1397,19 +1361,6 @@ style="stop-color:#9a9a9a;stop-opacity:1.0000000;" id="stop15568" /> </radialGradient> - <filter - inkscape:collect="always" - x="-0.45600089" - width="1.9120018" - y="-0.50666559" - height="2.0133312" - id="filter63011" - color-interpolation-filters="sRGB"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="1.899998" - id="feGaussianBlur63013" /> - </filter> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath13106"> @@ -5796,88 +5747,6 @@ x2="256" y2="459" gradientUnits="userSpaceOnUse" /> - <radialGradient - inkscape:collect="always" - xlink:href="#aigrd2" - id="radialGradient21565" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.2798768,0,0,0.279916,6.0465962,-0.3619733)" - cx="20.892099" - cy="114.5684" - fx="20.892099" - fy="114.5684" - r="5.256" /> - <radialGradient - inkscape:collect="always" - xlink:href="#aigrd2" - id="radialGradient21567" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.2798768,0,0,0.279916,6.0465962,-0.3619733)" - cx="20.892099" - cy="114.5684" - fx="20.892099" - fy="114.5684" - r="5.256" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient1610" - id="linearGradient21594" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" - x1="236.94902" - y1="-14.103641" - x2="276.89801" - y2="32.076183" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060" - id="linearGradient21596" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-47.00001,58.00194)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient1610" - id="linearGradient21647" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" - x1="236.94902" - y1="-14.103641" - x2="276.89801" - y2="31.515814" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060" - id="linearGradient21649" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-47.00001,58.00194)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient1610" - id="linearGradient21977" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" - x1="236.94902" - y1="-14.103641" - x2="276.89801" - y2="31.515814" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060" - id="linearGradient21979" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-47.00001,58.00194)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath22590"> @@ -5976,68 +5845,6 @@ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> </clipPath> <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient1610" - id="linearGradient23978" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" - x1="236.94902" - y1="-14.103641" - x2="276.89801" - y2="31.515814" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060" - id="linearGradient23980" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-47.00001,58.00194)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient31320" - id="linearGradient23982" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.733333,808.99997,-697.8)" - x1="150.5" - y1="239.9987" - x2="150.5" - y2="237" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient29485" - id="linearGradient23986" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0,1,1,0,715,364)" - x1="147.0625" - y1="243.76387" - x2="142.9375" - y2="243.69914" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient30777" - id="linearGradient23988" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,1.2857143,364,645.14283)" - x1="148" - y1="244.11113" - x2="144" - y2="244.11113" /> - <linearGradient - id="linearGradient3564" - inkscape:collect="always"> - <stop - id="stop3566" - offset="0" - style="stop-color:white;stop-opacity:1;" /> - <stop - id="stop3568" - offset="1" - style="stop-color:white;stop-opacity:0;" /> - </linearGradient> - <linearGradient id="linearGradient39155"> <stop id="stop39157" @@ -6049,79 +5856,6 @@ style="stop-color:#dadada;stop-opacity:1;" /> </linearGradient> <linearGradient - id="linearGradient39171" - inkscape:collect="always"> - <stop - id="stop39173" - offset="0" - style="stop-color:white;stop-opacity:1;" /> - <stop - id="stop39175" - offset="1" - style="stop-color:white;stop-opacity:0;" /> - </linearGradient> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient18821" - id="radialGradient21442" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)" - cx="75.554794" - cy="500.26215" - fx="75.554794" - fy="500.26215" - r="3.1650217" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient39155" - id="linearGradient21444" - gradientUnits="userSpaceOnUse" - x1="31.1875" - y1="18.875" - x2="29.875" - y2="34.375" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3564" - id="linearGradient21446" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)" - x1="185.9903" - y1="193.33229" - x2="190.46461" - y2="-458.05771" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient39171" - id="radialGradient21448" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)" - cx="26.109201" - cy="19.668886" - fx="26.109201" - fy="19.668886" - r="20.278975" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient1610" - id="linearGradient22274" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" - x1="236.94902" - y1="-14.103641" - x2="276.89801" - y2="32.076183" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060" - id="linearGradient22276" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-47.00001,58.00194)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient319" id="linearGradient38718" @@ -8869,123 +8603,6 @@ y2="287.50357" /> <linearGradient inkscape:collect="always" - xlink:href="#linearGradient24727" - id="linearGradient24809" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)" - x1="59.158501" - y1="437.02835" - x2="45.021851" - y2="349.81818" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient24735" - id="linearGradient24811" - gradientUnits="userSpaceOnUse" - x1="807" - y1="101.5" - x2="841" - y2="101.5" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient24711" - id="linearGradient24813" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)" - x1="63.539974" - y1="421.80756" - x2="63.407566" - y2="347.78201" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient16500" - id="linearGradient24815" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-127,4e-6)" - x1="954" - y1="102" - x2="936" - y2="114.99999" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient24727" - id="linearGradient24839" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)" - x1="59.158501" - y1="437.02835" - x2="45.021851" - y2="349.81818" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient24735" - id="linearGradient24841" - gradientUnits="userSpaceOnUse" - x1="807" - y1="101.5" - x2="841" - y2="101.5" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient24144" - id="linearGradient24843" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)" - x1="64.019142" - y1="419.06366" - x2="63.407566" - y2="347.78201" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient16500" - id="linearGradient24845" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-127,4e-6)" - x1="954" - y1="102" - x2="936" - y2="114.99999" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient24727" - id="linearGradient24867" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)" - x1="59.158501" - y1="437.02835" - x2="45.021851" - y2="349.81818" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient24735" - id="linearGradient24869" - gradientUnits="userSpaceOnUse" - x1="807" - y1="101.5" - x2="841" - y2="101.5" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient24711" - id="linearGradient24871" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)" - x1="63.659767" - y1="422.46088" - x2="63.407566" - y2="347.78201" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient16500" - id="linearGradient24873" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-127,4e-6)" - x1="954" - y1="102" - x2="936" - y2="114.99999" /> - <linearGradient - inkscape:collect="always" xlink:href="#linearGradient24679" id="linearGradient25073" gradientUnits="userSpaceOnUse" @@ -15527,50 +15144,6 @@ <linearGradient inkscape:collect="always" xlink:href="#linearGradient44939-8" - id="linearGradient44402" - gradientUnits="userSpaceOnUse" - x1="351.15625" - y1="108.35222" - x2="345.40625" - y2="108.00847" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient44939-8" - id="linearGradient44404" - gradientUnits="userSpaceOnUse" - x1="351.71875" - y1="106.93575" - x2="347.1875" - y2="106.7795" /> - <filter - inkscape:collect="always" - id="filter44473" - x="-0.12578467" - width="1.2515693" - y="-0.11472401" - height="1.229448" - color-interpolation-filters="sRGB"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="0.81235925" - id="feGaussianBlur44475" /> - </filter> - <filter - inkscape:collect="always" - id="filter44477" - x="-0.12176471" - width="1.2435294" - y="-0.11828571" - height="1.2365714" - color-interpolation-filters="sRGB"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="0.8625" - id="feGaussianBlur44479" /> - </filter> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient44939-8" id="linearGradient44485" gradientUnits="userSpaceOnUse" x1="279.75" @@ -16037,46 +15610,6 @@ r="3.5" /> <linearGradient inkscape:collect="always" - xlink:href="#linearGradient1610" - id="linearGradient30321" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" - x1="240.70209" - y1="-9.4293213" - x2="276.89801" - y2="31.515814" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060" - id="linearGradient30323" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-47.00001,58.00194)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient1610" - id="linearGradient30368" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" - x1="236.94902" - y1="-14.103641" - x2="276.89801" - y2="31.515814" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060" - id="linearGradient30370" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-47.00001,58.00194)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> - <linearGradient - inkscape:collect="always" xlink:href="#linearGradient30208" id="linearGradient25056" gradientUnits="userSpaceOnUse" @@ -17453,16 +16986,6 @@ xlink:href="#linearGradient34488-1-8" inkscape:collect="always" /> <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient1610-71-6-9-7" - id="linearGradient21875-7-1-0-1" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" - x1="236.94902" - y1="-14.103641" - x2="278.34866" - y2="32.902874" /> - <linearGradient id="linearGradient1610-71-6-9-7"> <stop style="stop-color:black;stop-opacity:1;" @@ -17486,29 +17009,6 @@ inkscape:export-xdpi="90" inkscape:export-ydpi="90" /> </clipPath> - <filter - inkscape:collect="always" - x="-0.45600089" - width="1.9120018" - y="-0.50666559" - height="2.0133312" - id="filter63011-6-7-0-8" - color-interpolation-filters="sRGB"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="1.899998" - id="feGaussianBlur63013-0-1-0-8" /> - </filter> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060-6-6-2-4" - id="linearGradient21877-3-2-7-2" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-47.00001,58.00194)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> <linearGradient id="linearGradient5060-6-6-2-4"> <stop @@ -17521,16 +17021,6 @@ style="stop-color:#000000;stop-opacity:0;" /> </linearGradient> <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4671-6-4-1-7" - id="linearGradient34959-9-2-1" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)" - x1="1666.1765" - y1="639.65356" - x2="1659.0875" - y2="629.23273" /> - <linearGradient id="linearGradient4671-6-4-1-7"> <stop id="stop4673-7-6-4-1" @@ -17542,16 +17032,6 @@ style="stop-color:#ffe873;stop-opacity:1" /> </linearGradient> <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4689-1-6-4-2" - id="linearGradient34961-3-6-5" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)" - x1="1641.4773" - y1="607.50525" - x2="1663.2872" - y2="626.40344" /> - <linearGradient id="linearGradient4689-1-6-4-2"> <stop id="stop4691-6-2-6-7" @@ -17564,95 +17044,6 @@ </linearGradient> <linearGradient inkscape:collect="always" - xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4" - id="linearGradient34963-5-9-1" - gradientUnits="userSpaceOnUse" - x1="922.89703" - y1="339.66599" - x2="924.10608" - y2="344.10001" /> - <linearGradient - inkscape:collect="always" - id="linearGradient3966-5-1-4-8-9-88-8-4"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop3968-7-9-0-8-2-1-3-2" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop3970-6-6-6-2-8-2-5-3" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4" - id="linearGradient34965-1-5-2" - gradientUnits="userSpaceOnUse" - x1="919.09998" - y1="345.42163" - x2="922.104" - y2="355.75" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3966-5-1-4-8-9-8-9-5-5" - id="linearGradient34967-4-1-8" - gradientUnits="userSpaceOnUse" - x1="922.64624" - y1="342.71866" - x2="921.82654" - y2="341.98108" /> - <linearGradient - inkscape:collect="always" - id="linearGradient3966-5-1-4-8-9-8-9-5-5"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop3968-7-9-0-8-2-9-8-5-7" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop3970-6-6-6-2-8-0-2-8-6" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4" - id="linearGradient34969-4-4-1" - gradientUnits="userSpaceOnUse" - x1="917.75" - y1="355.5" - x2="917.25" - y2="353" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4" - id="linearGradient34971-5-0-9" - gradientUnits="userSpaceOnUse" - x1="923" - y1="343.75" - x2="923" - y2="344.75" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4" - id="radialGradient34973-2-5-7" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4166677,-7.678944e-6,1.853542e-6,0.58333478,-1309.0016,145.80659)" - cx="924" - cy="349.20001" - fx="924" - fy="349.20001" - r="6" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4" - id="linearGradient34975-9-4-9" - gradientUnits="userSpaceOnUse" - x1="921.34045" - y1="341.34042" - x2="922.16492" - y2="342.16492" /> - <linearGradient - inkscape:collect="always" id="linearGradient3944-4-6-7-7"> <stop style="stop-color:#ffffff;stop-opacity:1;" @@ -21294,16 +20685,6 @@ x2="50.907307" y2="95.401253" /> <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient14829" - id="linearGradient14814" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.4126967,0,0,2.7035619,-722.19531,285.57729)" - x1="236.94902" - y1="-14.103641" - x2="276.89801" - y2="32.076183" /> - <linearGradient id="linearGradient14829"> <stop id="stop14831" @@ -21314,28 +20695,6 @@ offset="1" style="stop-color:#757575;stop-opacity:1;" /> </linearGradient> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient14632" - id="linearGradient14816" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-214.43013,42.779961)" - x1="148.54834" - y1="301.96149" - x2="166.33298" - y2="317.25269" /> - <linearGradient - inkscape:collect="always" - id="linearGradient14632"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop14634" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop14636" /> - </linearGradient> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath13106-0"> @@ -21349,29 +20708,6 @@ inkscape:export-xdpi="90" inkscape:export-ydpi="90" /> </clipPath> - <filter - inkscape:collect="always" - x="-0.45600089" - width="1.9120018" - y="-0.50666559" - height="2.0133312" - id="filter63011-8" - color-interpolation-filters="sRGB"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="1.899998" - id="feGaussianBlur63013-0" /> - </filter> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5060-9" - id="linearGradient14818" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(-233.12445,-35.715412)" - x1="160.14388" - y1="376.27383" - x2="174.29811" - y2="383.69843" /> <linearGradient id="linearGradient5060-9"> <stop @@ -21383,17 +20719,6 @@ offset="1" style="stop-color:#000000;stop-opacity:0;" /> </linearGradient> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient18821-9" - id="radialGradient14820" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)" - cx="75.554794" - cy="500.26215" - fx="75.554794" - fy="500.26215" - r="3.1650217" /> <linearGradient id="linearGradient18821-9"> <stop @@ -21406,15 +20731,6 @@ id="stop18825-4" /> </linearGradient> <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient39155-5" - id="linearGradient14822" - gradientUnits="userSpaceOnUse" - x1="31.1875" - y1="18.875" - x2="29.875" - y2="34.375" /> - <linearGradient id="linearGradient39155-5"> <stop id="stop39157-4" @@ -21427,51 +20743,6 @@ </linearGradient> <linearGradient inkscape:collect="always" - xlink:href="#linearGradient3564-9" - id="linearGradient14825" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)" - x1="185.9903" - y1="193.33229" - x2="190.46461" - y2="-458.05771" /> - <linearGradient - id="linearGradient3564-9" - inkscape:collect="always"> - <stop - id="stop3566-9" - offset="0" - style="stop-color:white;stop-opacity:1;" /> - <stop - id="stop3568-2" - offset="1" - style="stop-color:white;stop-opacity:0;" /> - </linearGradient> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient39171-8" - id="radialGradient14827" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)" - cx="26.109201" - cy="19.668886" - fx="26.109201" - fy="19.668886" - r="20.278975" /> - <linearGradient - id="linearGradient39171-8" - inkscape:collect="always"> - <stop - id="stop39173-9" - offset="0" - style="stop-color:white;stop-opacity:1;" /> - <stop - id="stop39175-5" - offset="1" - style="stop-color:white;stop-opacity:0;" /> - </linearGradient> - <linearGradient - inkscape:collect="always" xlink:href="#linearGradient14829" id="linearGradient14800" gradientUnits="userSpaceOnUse" @@ -31044,6 +30315,1029 @@ y1="238" x2="226.625" y2="251.71078" /> + <linearGradient + y2="32.076183" + x2="276.89801" + y1="-14.103641" + x1="236.94902" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient22274-8" + xlink:href="#linearGradient1610-2" + inkscape:collect="always" /> + <linearGradient + id="linearGradient1610-2"> + <stop + id="stop1611-8-9" + offset="0" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0.5" + id="stop6596" /> + <stop + id="stop1612-0-6" + offset="1" + style="stop-color:#c8c8c8;stop-opacity:1;" /> + </linearGradient> + <clipPath + id="clipPath13106-5" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path34850-6-6" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <filter + style="color-interpolation-filters:sRGB" + id="filter63011-5" + height="2.0133312" + y="-0.50666559" + width="1.9120018" + x="-0.45600089" + inkscape:collect="always"> + <feGaussianBlur + id="feGaussianBlur63013-8" + stdDeviation="1.899998" + inkscape:collect="always" /> + </filter> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient22276-5" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6172" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6174" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <radialGradient + r="3.1650217" + fy="500.26215" + fx="75.554794" + cy="500.26215" + cx="75.554794" + gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)" + gradientUnits="userSpaceOnUse" + id="radialGradient21442-6-790" + xlink:href="#linearGradient18821-1-16" + inkscape:collect="always" /> + <linearGradient + id="linearGradient18821-1-16"> + <stop + id="stop20589" + offset="0" + style="stop-color:#e3604f;stop-opacity:1;" /> + <stop + id="stop20591" + offset="1" + style="stop-color:#e3604f;stop-opacity:0;" /> + </linearGradient> + <linearGradient + y2="34.375" + x2="29.875" + y1="18.875" + x1="31.1875" + gradientUnits="userSpaceOnUse" + id="linearGradient21444-0-352" + xlink:href="#linearGradient39155-0-813" + inkscape:collect="always" /> + <linearGradient + id="linearGradient39155-0-813"> + <stop + style="stop-color:#e6e6e6;stop-opacity:1;" + offset="0" + id="stop20595" /> + <stop + style="stop-color:#c4c4c4;stop-opacity:1;" + offset="1" + id="stop20597" /> + </linearGradient> + <linearGradient + y2="-458.05771" + x2="190.46461" + y1="193.33229" + x1="185.9903" + gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)" + gradientUnits="userSpaceOnUse" + id="linearGradient21446-3-145" + xlink:href="#linearGradient3564-2-380" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3564-2-380"> + <stop + style="stop-color:#e6e6e6;stop-opacity:1;" + offset="0" + id="stop20601" /> + <stop + style="stop-color:#e6e6e6;stop-opacity:0;" + offset="1" + id="stop20603" /> + </linearGradient> + <radialGradient + r="20.278975" + fy="19.668886" + fx="26.109201" + cy="19.668886" + cx="26.109201" + gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)" + gradientUnits="userSpaceOnUse" + id="radialGradient21448-8-143" + xlink:href="#linearGradient3564-2-380" + inkscape:collect="always" /> + <linearGradient + y2="32.902874" + x2="278.34866" + y1="-14.103641" + x1="236.94902" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient21875-7-1-0-1" + xlink:href="#linearGradient16595" + inkscape:collect="always" /> + <clipPath + id="clipPath13106-9-2-9-9-4" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path34850-4-7-0-4-0" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + inkscape:connector-curvature="0" /> + </clipPath> + <filter + style="color-interpolation-filters:sRGB" + id="filter63011-6-7-0-8" + height="2.0133312" + y="-0.50666559" + width="1.9120018" + x="-0.45600089" + inkscape:collect="always"> + <feGaussianBlur + id="feGaussianBlur63013-0-1-0-8" + stdDeviation="1.899998" + inkscape:collect="always" /> + </filter> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient21877-3-2-7-2" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6208" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6210" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + inkscape:connector-curvature="0" /> + </clipPath> + <linearGradient + y2="629.23273" + x2="1659.0875" + y1="639.65356" + x1="1666.1765" + gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)" + gradientUnits="userSpaceOnUse" + id="linearGradient34959-9-2-1" + xlink:href="#linearGradient4671-6-4-1-7" + inkscape:collect="always" /> + <linearGradient + y2="626.40344" + x2="1663.2872" + y1="607.50525" + x1="1641.4773" + gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)" + gradientUnits="userSpaceOnUse" + id="linearGradient34961-3-6-5" + xlink:href="#linearGradient4689-1-6-4-2" + inkscape:collect="always" /> + <linearGradient + y2="344.10001" + x2="924.10608" + y1="339.66599" + x1="922.89703" + gradientUnits="userSpaceOnUse" + id="linearGradient34963-5-9-1" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="355.75" + x2="922.104" + y1="345.42163" + x1="919.09998" + gradientUnits="userSpaceOnUse" + id="linearGradient34965-1-5-2" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="341.98108" + x2="921.82654" + y1="342.71866" + x1="922.64624" + gradientUnits="userSpaceOnUse" + id="linearGradient34967-4-1-8" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="353" + x2="917.25" + y1="355.5" + x1="917.75" + gradientUnits="userSpaceOnUse" + id="linearGradient34969-4-4-1" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="344.75" + x2="923" + y1="343.75" + x1="923" + gradientUnits="userSpaceOnUse" + id="linearGradient34971-5-0-9" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <radialGradient + r="6" + fy="349.20001" + fx="924" + cy="349.20001" + cx="924" + gradientTransform="matrix(2.4166677,-7.678944e-6,1.853542e-6,0.58333478,-1309.0016,145.80659)" + gradientUnits="userSpaceOnUse" + id="radialGradient34973-2-5-7" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="342.16492" + x2="922.16492" + y1="341.34042" + x1="921.34045" + gradientUnits="userSpaceOnUse" + id="linearGradient34975-9-4-9" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="349.81818" + x2="45.021851" + y1="437.02835" + x1="59.158501" + gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)" + gradientUnits="userSpaceOnUse" + id="linearGradient24867" + xlink:href="#linearGradient24727" + inkscape:collect="always" /> + <linearGradient + y2="101.5" + x2="841" + y1="101.5" + x1="807" + gradientUnits="userSpaceOnUse" + id="linearGradient24869" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <linearGradient + y2="347.78201" + x2="63.407566" + y1="422.46088" + x1="63.659767" + gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)" + gradientUnits="userSpaceOnUse" + id="linearGradient24871" + xlink:href="#linearGradient24711" + inkscape:collect="always" /> + <linearGradient + y2="114.99999" + x2="936" + y1="102" + x1="954" + gradientTransform="translate(-127,4e-6)" + gradientUnits="userSpaceOnUse" + id="linearGradient24873" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <filter + style="color-interpolation-filters:sRGB" + inkscape:label="Drop Shadow" + id="filter6146" + x="-0.30000001" + width="1.35" + y="-0.15000001" + height="1.4"> + <feFlood + flood-opacity="0.40000000000000002" + flood-color="rgb(0,0,0)" + result="flood" + id="feFlood6148" /> + <feComposite + in="flood" + in2="SourceGraphic" + operator="in" + result="composite1" + id="feComposite6150" /> + <feGaussianBlur + in="composite1" + stdDeviation="1.5" + result="blur" + id="feGaussianBlur6152" /> + <feOffset + dx="-2" + dy="2" + result="offset" + id="feOffset6154" /> + <feComposite + in="SourceGraphic" + in2="offset" + operator="over" + result="composite2" + id="feComposite6156" /> + </filter> + <linearGradient + y2="108.00847" + x2="345.40625" + y1="108.35222" + x1="351.15625" + gradientUnits="userSpaceOnUse" + id="linearGradient44402" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="106.7795" + x2="347.1875" + y1="106.93575" + x1="351.71875" + gradientUnits="userSpaceOnUse" + id="linearGradient44404" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="349.81818" + x2="45.021851" + y1="437.02835" + x1="59.158501" + gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)" + gradientUnits="userSpaceOnUse" + id="linearGradient24839" + xlink:href="#linearGradient24727" + inkscape:collect="always" /> + <linearGradient + y2="101.5" + x2="841" + y1="101.5" + x1="807" + gradientUnits="userSpaceOnUse" + id="linearGradient24841" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <linearGradient + y2="347.78201" + x2="63.407566" + y1="419.06366" + x1="64.019142" + gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)" + gradientUnits="userSpaceOnUse" + id="linearGradient24843" + xlink:href="#linearGradient24144" + inkscape:collect="always" /> + <linearGradient + y2="114.99999" + x2="936" + y1="102" + x1="954" + gradientTransform="translate(-127,4e-6)" + gradientUnits="userSpaceOnUse" + id="linearGradient24845" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <linearGradient + y2="349.81818" + x2="45.021851" + y1="437.02835" + x1="59.158501" + gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)" + gradientUnits="userSpaceOnUse" + id="linearGradient24809" + xlink:href="#linearGradient24727" + inkscape:collect="always" /> + <linearGradient + y2="101.5" + x2="841" + y1="101.5" + x1="807" + gradientUnits="userSpaceOnUse" + id="linearGradient24811" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <linearGradient + y2="347.78201" + x2="63.407566" + y1="421.80756" + x1="63.539974" + gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)" + gradientUnits="userSpaceOnUse" + id="linearGradient24813" + xlink:href="#linearGradient24711" + inkscape:collect="always" /> + <linearGradient + y2="114.99999" + x2="936" + y1="102" + x1="954" + gradientTransform="translate(-127,4e-6)" + gradientUnits="userSpaceOnUse" + id="linearGradient24815" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <filter + style="color-interpolation-filters:sRGB" + inkscape:label="Drop Shadow" + id="filter6078" + x="-0.30000001" + width="1.35" + height="1.4" + y="-0.15000001"> + <feFlood + flood-opacity="0.40000000000000002" + flood-color="rgb(0,0,0)" + result="flood" + id="feFlood6080" /> + <feComposite + in="flood" + in2="SourceGraphic" + operator="in" + result="composite1" + id="feComposite6082" /> + <feGaussianBlur + in="composite1" + stdDeviation="1.5" + result="blur" + id="feGaussianBlur6084" /> + <feOffset + dx="-2" + dy="2" + result="offset" + id="feOffset6086" /> + <feComposite + in="SourceGraphic" + in2="offset" + operator="over" + result="composite2" + id="feComposite6088" /> + </filter> + <linearGradient + y2="32.076183" + x2="276.89801" + y1="-14.103641" + x1="236.94902" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient22274" + xlink:href="#linearGradient16595" + inkscape:collect="always" /> + <clipPath + id="clipPath13106-7" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path34850-1" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <filter + style="color-interpolation-filters:sRGB" + id="filter63011" + height="2.0133312" + y="-0.50666559" + width="1.9120018" + x="-0.45600089" + inkscape:collect="always"> + <feGaussianBlur + id="feGaussianBlur63013" + stdDeviation="1.899998" + inkscape:collect="always" /> + </filter> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient22276" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6380" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6382" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <radialGradient + r="3.1650217" + fy="500.26215" + fx="75.554794" + cy="500.26215" + cx="75.554794" + gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)" + gradientUnits="userSpaceOnUse" + id="radialGradient21442" + xlink:href="#linearGradient18821" + inkscape:collect="always" /> + <linearGradient + y2="34.375" + x2="29.875" + y1="18.875" + x1="31.1875" + gradientUnits="userSpaceOnUse" + id="linearGradient21444" + xlink:href="#linearGradient39155" + inkscape:collect="always" /> + <linearGradient + y2="-458.05771" + x2="190.46461" + y1="193.33229" + x1="185.9903" + gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)" + gradientUnits="userSpaceOnUse" + id="linearGradient21446" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <radialGradient + r="20.278975" + fy="19.668886" + fx="26.109201" + cy="19.668886" + cx="26.109201" + gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)" + gradientUnits="userSpaceOnUse" + id="radialGradient21448" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="31.515814" + x2="276.89801" + y1="-14.103641" + x1="236.94902" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient23978" + xlink:href="#linearGradient16595" + inkscape:collect="always" /> + <clipPath + id="clipPath6411" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6413" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient23980" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6426" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6428" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="237" + x2="150.5" + y1="239.9987" + x1="150.5" + gradientTransform="matrix(1,0,0,0.733333,808.99997,-697.8)" + gradientUnits="userSpaceOnUse" + id="linearGradient23982" + xlink:href="#linearGradient18134" + inkscape:collect="always" /> + <linearGradient + y2="243.69914" + x2="142.9375" + y1="243.76387" + x1="147.0625" + gradientTransform="matrix(0,1,1,0,715,364)" + gradientUnits="userSpaceOnUse" + id="linearGradient23986" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <linearGradient + y2="244.11113" + x2="144" + y1="244.11113" + x1="148" + gradientTransform="matrix(1,0,0,1.2857143,364,645.14283)" + gradientUnits="userSpaceOnUse" + id="linearGradient23988" + xlink:href="#linearGradient30777" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient30777"> + <stop + style="stop-color:#acacac;stop-opacity:1" + offset="0" + id="stop30779" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop30781" /> + </linearGradient> + <clipPath + id="clipPath23877-4" + clipPathUnits="userSpaceOnUse"> + <rect + style="display:inline;overflow:visible;visibility:visible;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;enable-background:accumulate" + id="rect23879-6" + width="15" + height="6" + x="952" + y="-540" + transform="scale(1,-1)" /> + </clipPath> + <linearGradient + y2="31.515814" + x2="276.89801" + y1="-14.103641" + x1="236.94902" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient30368" + xlink:href="#linearGradient16595" + inkscape:collect="always" /> + <clipPath + id="clipPath6455" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6457" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient30370" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6470" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6472" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <clipPath + id="clipPath20586-3" + clipPathUnits="userSpaceOnUse"> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + transform="matrix(1.870472,0.1894819,-0.6587894,2.4281336,319.59052,-798.11661)" + id="path34889-5" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" /> + </clipPath> + <filter + style="color-interpolation-filters:sRGB" + id="filter20578-5" + height="3.0439126" + y="-1.0219563" + width="2.1164308" + x="-0.55821538" + inkscape:collect="always"> + <feGaussianBlur + id="feGaussianBlur20580-2" + stdDeviation="2.0410255" + inkscape:collect="always" /> + </filter> + <clipPath + id="clipPath6482" + clipPathUnits="userSpaceOnUse"> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + transform="matrix(1.870472,0.1894819,-0.6587894,2.4281336,319.59052,-798.11661)" + id="path6484" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" /> + </clipPath> + <linearGradient + y2="32.076183" + x2="276.89801" + y1="-14.103641" + x1="236.94902" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient21594" + xlink:href="#linearGradient16595" + inkscape:collect="always" /> + <clipPath + id="clipPath6497" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6499" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient21596" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6512" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6514" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="31.515814" + x2="276.89801" + y1="-14.103641" + x1="236.94902" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient21647" + xlink:href="#linearGradient16595" + inkscape:collect="always" /> + <clipPath + id="clipPath6527" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6529" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient21649" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6542" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6544" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <radialGradient + r="5.256" + fy="114.5684" + fx="20.892099" + cy="114.5684" + cx="20.892099" + gradientTransform="matrix(0.2798768,0,0,0.279916,6.0465962,-0.3619733)" + gradientUnits="userSpaceOnUse" + id="radialGradient21565" + xlink:href="#aigrd2-3" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + fy="114.5684" + fx="20.892099" + r="5.256" + cy="114.5684" + cx="20.892099" + id="aigrd2-3"> + <stop + id="stop15566-9" + style="stop-color:#F0F0F0" + offset="0" /> + <stop + id="stop15568-7" + style="stop-color:#9a9a9a;stop-opacity:1.0000000;" + offset="1.0000000" /> + </radialGradient> + <radialGradient + r="5.256" + fy="114.5684" + fx="20.892099" + cy="114.5684" + cx="20.892099" + gradientTransform="matrix(0.2798768,0,0,0.279916,6.0465962,-0.3619733)" + gradientUnits="userSpaceOnUse" + id="radialGradient21567" + xlink:href="#aigrd2-3" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + fy="114.5684" + fx="20.892099" + r="5.256" + cy="114.5684" + cx="20.892099" + id="radialGradient6555"> + <stop + id="stop6557" + style="stop-color:#F0F0F0" + offset="0" /> + <stop + id="stop6559" + style="stop-color:#9a9a9a;stop-opacity:1.0000000;" + offset="1.0000000" /> + </radialGradient> + <linearGradient + y2="31.515814" + x2="276.89801" + y1="-9.4293213" + x1="240.70209" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient30321" + xlink:href="#linearGradient16595" + inkscape:collect="always" /> + <clipPath + id="clipPath6568" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6570" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient30323" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6583" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6585" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="31.515814" + x2="276.89801" + y1="-14.103641" + x1="236.94902" + gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)" + gradientUnits="userSpaceOnUse" + id="linearGradient21977" + xlink:href="#linearGradient16595" + inkscape:collect="always" /> + <clipPath + id="clipPath6599" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6601" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> + <linearGradient + y2="383.69843" + x2="174.29811" + y1="376.27383" + x1="160.14388" + gradientTransform="translate(-47.00001,58.00194)" + gradientUnits="userSpaceOnUse" + id="linearGradient21979" + xlink:href="#linearGradient18495" + inkscape:collect="always" /> + <clipPath + id="clipPath6614" + clipPathUnits="userSpaceOnUse"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path6616" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + </clipPath> </defs> <sodipodi:namedview id="base" @@ -31055,16 +31349,16 @@ objecttolerance="10000" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="10.192144" - inkscape:cx="406.73801" - inkscape:cy="204.25086" + inkscape:zoom="1.274018" + inkscape:cx="519.70993" + inkscape:cy="325.90484" inkscape:document-units="px" - inkscape:current-layer="g24024-1" + inkscape:current-layer="layer1" showgrid="true" - inkscape:window-width="1680" - inkscape:window-height="987" - inkscape:window-x="-8" - inkscape:window-y="-8" + inkscape:window-width="1920" + inkscape:window-height="1005" + inkscape:window-x="-2" + inkscape:window-y="27" inkscape:snap-nodes="false" inkscape:snap-bbox="true" showguides="true" @@ -75998,1951 +76292,6 @@ </g> </g> <g - id="g32752" - inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\v. 2.5.06\prvicons 2.5.06.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <rect - y="180" - x="872" - height="192" - width="192" - id="rect30285" - style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.39191818;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - transform="translate(856,-203)" - id="g21955" - style="opacity:0.3;display:inline;enable-background:new"> - <rect - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect21957" - width="48" - height="48" - x="108" - y="430" - rx="2.4004419" - ry="0" /> - <g - id="g21959"> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21961" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient21977);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" - id="path21963" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path21965" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path21967" - style="fill:none;stroke:url(#linearGradient21979);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21969" - sodipodi:nodetypes="cccccc" /> - <path - inkscape:connector-curvature="0" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path21971" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21973" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21975" - sodipodi:nodetypes="ccc" /> - </g> - </g> - <g - id="g30335"> - <g - id="g21367" - transform="translate(760,-202)"> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21369" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient30321);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" - id="path21371" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path21373" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path21375" - style="fill:none;stroke:url(#linearGradient30323);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21377" - sodipodi:nodetypes="cccccc" /> - <path - inkscape:connector-curvature="0" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path21569" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21379" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21381" - sodipodi:nodetypes="ccc" /> - </g> - <path - inkscape:connector-curvature="0" - style="font-size:33.49144363px;font-style:normal;font-weight:normal;fill:#214478;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" - d="m 891.07148,245 -0.0715,9 2.39012,0 C 896,254 896,253 896.5,251 l 0.5,0 0,7 -0.5,0 c -0.5,-2 -0.5,-3 -3.10988,-3 L 891,255 l 0,7 c 0,2.5 1,3.25 3.14146,3.39973 l -0.004,0.60029 L 885,266 l 0.004,-0.60029 C 887,265.25 888,264.5 888.00001,262 L 888,248 c 0,-2.5 -1,-3.25 -3,-3.5 l 0,-0.5 16,0 0,5 -0.5,0 c -0.50001,-1.99999 -1.5,-4 -4.5,-4 l -4.92852,0 z" - id="text13209" - sodipodi:nodetypes="ccccccccccccccccccccccc" /> - </g> - <g - style="display:inline;enable-background:new" - id="g21625" - transform="translate(904,-154)" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <rect - ry="0" - rx="2.4004419" - y="430" - x="108" - height="48" - width="48" - id="rect21627" - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - id="g21629"> - <path - inkscape:connector-curvature="0" - style="fill:url(#linearGradient21647);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - id="path21631" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <g - style="opacity:0.5;fill:#000000;display:inline" - id="g16261" - transform="matrix(1.2499985,0,0,1,-87.6203,-147.85351)"> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect35099" - width="17.600004" - height="1" - x="167.69646" - y="598.85352" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect35101" - width="17.600004" - height="1" - x="167.69646" - y="600.85352" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15690" - width="17.600004" - height="1" - x="167.69646" - y="602.85352" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15692" - width="17.600004" - height="1" - x="167.69646" - y="604.85352" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15694" - width="17.600004" - height="1" - x="167.69646" - y="606.85352" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15696" - width="17.600004" - height="1" - x="167.69646" - y="608.85352" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15698" - width="17.600004" - height="1" - x="167.69646" - y="610.85352" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15700" - width="17.600004" - height="1" - x="167.69646" - y="612.85352" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15732" - width="14.400002" - height="1" - x="167.69646" - y="614.85352" - rx="0.09920612" - ry="0.065390877" /> - <g - transform="translate(150.89645,557.85352)" - id="g4849" - style="fill:#000000;display:inline"> - <rect - ry="0.065390877" - rx="0.12125195" - y="29" - x="16.799992" - height="1" - width="17.600004" - id="rect15736" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <rect - ry="0.065390877" - rx="0.12125195" - y="31" - x="16.799992" - height="1" - width="17.600004" - id="rect15738" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <rect - ry="0.065390877" - rx="0.12125195" - y="33" - x="16.799992" - height="1" - width="17.600004" - id="rect15740" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <rect - ry="0.065390877" - rx="0.12125195" - y="35" - x="16.799992" - height="1" - width="17.600004" - id="rect15742" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <rect - ry="0.065390877" - rx="0.055114571" - y="37" - x="16.799992" - height="1" - width="8.0000095" - id="rect15744" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - </g> - <rect - ry="0.065390304" - rx="0.0057410933" - y="617.85352" - x="184.49646" - height="0.99999124" - width="0.83333319" - id="rect16334" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - </g> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21633" - sodipodi:nodetypes="cccc" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21635" - d="m 115,444 12,0 -1,-11 -11,11 z" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> - <path - inkscape:connector-curvature="0" - clip-path="none" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 117.5,443.75 9,-2.5 0,-6" - style="fill:none;stroke:url(#linearGradient21649);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path21637" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" - id="path21639" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21641" - d="m 116,443 11,1 -2,-10 -9,9 z" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" /> - <path - inkscape:connector-curvature="0" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - id="path21643" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <g - id="g35119" - transform="translate(2,-160.99999)" - style="display:inline"> - <g - style="display:inline" - transform="translate(105.39645,589.71201)" - id="g16097"> - <g - id="g16099" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4" - transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)"> - <radialGradient - id="radialGradient16101" - cx="20.892099" - cy="114.5684" - r="5.256" - fx="20.892099" - fy="114.5684" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - style="stop-color:#F0F0F0" - id="stop16103" /> - <stop - offset="1" - style="stop-color:#474747" - id="stop16105" /> - </radialGradient> - <radialGradient - id="radialGradient16109" - cx="20.892099" - cy="64.567902" - r="5.257" - fx="20.892099" - fy="64.567902" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - style="stop-color:#F0F0F0" - id="stop16111" /> - <stop - offset="1" - style="stop-color:#474747" - id="stop16113" /> - </radialGradient> - </g> - <path - inkscape:connector-curvature="0" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" - d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z" - id="path16107" /> - <path - inkscape:connector-curvature="0" - style="fill:url(#radialGradient21565);fill-rule:nonzero;stroke:none" - d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z" - id="path16117" /> - </g> - <g - id="g16131" - transform="translate(105.39645,579.71201)" - style="display:inline"> - <g - transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4" - id="g16133"> - <radialGradient - gradientUnits="userSpaceOnUse" - fy="114.5684" - fx="20.892099" - r="5.256" - cy="114.5684" - cx="20.892099" - id="radialGradient16135"> - <stop - id="stop16137" - style="stop-color:#F0F0F0" - offset="0" /> - <stop - id="stop16140" - style="stop-color:#474747" - offset="1" /> - </radialGradient> - <radialGradient - gradientUnits="userSpaceOnUse" - fy="64.567902" - fx="20.892099" - r="5.257" - cy="64.567902" - cx="20.892099" - id="radialGradient16142"> - <stop - id="stop16144" - style="stop-color:#F0F0F0" - offset="0" /> - <stop - id="stop16146" - style="stop-color:#474747" - offset="1" /> - </radialGradient> - </g> - <path - inkscape:connector-curvature="0" - id="path35139" - d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" /> - <path - inkscape:connector-curvature="0" - id="path35141" - d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z" - style="fill:url(#radialGradient21567);fill-rule:nonzero;stroke:none" /> - </g> - </g> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path21645" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.5,435 0,38.5 -30.5,0" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - </g> - </g> - <g - style="display:inline;enable-background:new" - id="g21572" - transform="translate(808,-203)" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <rect - ry="0" - rx="2.4004419" - y="430" - x="108" - height="48" - width="48" - id="rect21574" - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - id="g21576"> - <path - inkscape:connector-curvature="0" - style="fill:url(#linearGradient21594);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - id="path21578" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21580" - sodipodi:nodetypes="cccc" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21582" - d="m 115,444 12,0 -1,-11 -11,11 z" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> - <path - inkscape:connector-curvature="0" - clip-path="none" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 117.5,443.75 9,-2.5 0,-6" - style="fill:none;stroke:url(#linearGradient21596);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path21584" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" - id="path21586" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21588" - d="m 116,443 11,1 -2,-10 -9,9 z" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" /> - <path - inkscape:connector-curvature="0" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - id="path21590" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path21592" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.5,435 0,38.5 -30.5,0" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - </g> - </g> - <g - id="g30382"> - <g - id="g23655" - transform="translate(760,-154)"> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path23657" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient30368);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" - id="path23659" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path23661" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path23663" - style="fill:none;stroke:url(#linearGradient30370);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path23665" - sodipodi:nodetypes="cccccc" /> - <path - inkscape:connector-curvature="0" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path23667" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path23669" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path23671" - sodipodi:nodetypes="ccc" /> - </g> - <path - inkscape:connector-curvature="0" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 888,295 1,0 0,14 -1,0 0,-14 z" - id="path23675" - sodipodi:nodetypes="ccccc" /> - <path - inkscape:connector-curvature="0" - id="path23677" - d="m 900,294 1.00002,-1 0,14 -1.00002,0 0,-13 z" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:nodetypes="ccccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccc" - id="path23679" - d="m 901.00003,292 0,2.25 -13.00002,2 0,-2.25 13.00002,-2 z" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - id="g23681" - transform="matrix(1.1428564,0,0,1.2000001,822.71436,-355.40005)"> - <path - transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" - d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z" - sodipodi:ry="2.25" - sodipodi:rx="4.5" - sodipodi:cy="554" - sodipodi:cx="53" - id="path23683" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" /> - <path - sodipodi:type="arc" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate" - id="path23685" - sodipodi:cx="53" - sodipodi:cy="554" - sodipodi:rx="4.5" - sodipodi:ry="2.25" - d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z" - transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)" - inkscape:transform-center-y="0.3813435" - clip-path="url(#clipPath20586)" /> - </g> - <path - inkscape:connector-curvature="0" - style="opacity:0.38999999;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 901.00003,292 -1e-5,1 -13.00002,2 10e-6,-1 13.00002,-2 z" - id="path23694" - sodipodi:nodetypes="ccccc" /> - <g - transform="matrix(1.1428564,0,0,1.2000001,834.71436,-357.40005)" - id="g23717"> - <path - sodipodi:type="arc" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path23724" - sodipodi:cx="53" - sodipodi:cy="554" - sodipodi:rx="4.5" - sodipodi:ry="2.25" - d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z" - transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" /> - <path - clip-path="url(#clipPath20586)" - inkscape:transform-center-y="0.3813435" - transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)" - d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z" - sodipodi:ry="2.25" - sodipodi:rx="4.5" - sodipodi:cy="554" - sodipodi:cx="53" - id="path23726" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate" - sodipodi:type="arc" /> - </g> - </g> - <g - id="g23922" - transform="translate(-16,-220)" - style="display:inline;enable-background:new"> - <g - style="display:inline" - id="g23924" - transform="translate(824,66)" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <rect - ry="0" - rx="2.4004419" - y="430" - x="108" - height="48" - width="48" - id="rect23926" - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - id="g23928"> - <path - inkscape:connector-curvature="0" - style="fill:url(#linearGradient23978);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - id="path23930" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path23932" - sodipodi:nodetypes="cccc" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path23934" - d="m 115,444 12,0 -1,-11 -11,11 z" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> - <path - inkscape:connector-curvature="0" - clip-path="none" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 117.5,443.75 9,-2.5 0,-6" - style="fill:none;stroke:url(#linearGradient23980);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path23936" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" - id="path23938" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path23940" - d="m 116,443 11,1 -2,-10 -9,9 z" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" /> - <path - inkscape:connector-curvature="0" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - id="path23942" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path23944" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.5,435 0,38.5 -30.5,0" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - </g> - </g> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccc" - id="path23946" - d="m 952,530 0,10 1,0 1,0 11,0 1,0 1,0 0,-10 -15,0 z m 1,2 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> - <rect - transform="scale(1,-1)" - style="fill:url(#linearGradient23982);fill-opacity:1;fill-rule:nonzero;stroke:none" - id="rect23948" - width="13" - height="5.5" - x="953" - y="-524" /> - <path - inkscape:connector-curvature="0" - id="path23952" - transform="translate(76,0)" - d="m 876,514 0,17 15,0 0,-17 -1,0 0,1 -1,0 0,-1 -11,0 0,1 -1,0 0,-1 -1,0 z m 1,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccc" - style="fill:url(#linearGradient23986);fill-opacity:1;fill-rule:nonzero;stroke:none" - d="m 952,507 3,0 0,3 9,0 0,-3 3,0 0,7 -15,0 0,-7 z m 1,0 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z m 12,-4 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z" - id="path23954" /> - <rect - transform="matrix(0,1,1,0,0,0)" - ry="0" - y="955" - x="507" - height="9" - width="3" - id="rect23956" - style="fill:url(#linearGradient23988);fill-opacity:1;fill-rule:nonzero;stroke:none" /> - <rect - style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="rect23958" - width="9" - height="9" - x="512" - y="955" - ry="0" - transform="matrix(0,1,1,0,0,0)" /> - <rect - transform="matrix(0,1,1,0,0,0)" - ry="0" - y="955" - x="523" - height="9" - width="9" - id="rect23960" - style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" /> - <path - transform="matrix(0,-0.5624971,0.5624971,0,893.12531,590.74965)" - sodipodi:type="arc" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path23962" - sodipodi:cx="132" - sodipodi:cy="118" - sodipodi:rx="8" - sodipodi:ry="8" - d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" - d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" - sodipodi:ry="8" - sodipodi:rx="8" - sodipodi:cy="118" - sodipodi:cx="132" - id="path23964" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - sodipodi:type="arc" - transform="matrix(0,-0.5624964,0.5624964,0,893.12545,601.74956)" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccccccccc" - id="path23966" - d="m 961.00001,519.00005 -3,0 0,-0.99992 0.99994,0 6e-5,-2.00008 -1,0 0,-1 1,0 0,-1 1.00006,0 0,4.00008 0.99994,0 0,0.99992 z" /> - <path - inkscape:connector-curvature="0" - d="m 958,525 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" - id="path23968" /> - <rect - style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="rect23970" - width="6" - height="9" - x="534" - y="955" - ry="0" - transform="matrix(0,1,1,0,0,0)" /> - <g - clip-path="url(#clipPath23877)" - id="g23972"> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" - d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" - sodipodi:ry="8" - sodipodi:rx="8" - sodipodi:cy="118" - sodipodi:cx="132" - id="path23974" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - sodipodi:type="arc" - transform="matrix(0,-0.5624964,0.5624964,0,893.12545,612.74956)" /> - <path - inkscape:connector-curvature="0" - d="m 958,536 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,1 -2,0 0,1 2,0 0,-1 z" - id="path23976" /> - </g> - </g> - <g - transform="translate(208,88)" - id="g45475" - style="display:inline;enable-background:new"> - <g - style="display:inline" - id="g22242" - transform="translate(696,-194)" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <rect - ry="0" - rx="2.4004419" - y="430" - x="108" - height="48" - width="48" - id="rect22244" - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - id="g22246"> - <path - inkscape:connector-curvature="0" - style="fill:url(#linearGradient22274);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - id="path22249" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path22251" - sodipodi:nodetypes="cccc" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path22253" - d="m 115,444 12,0 -1,-11 -11,11 z" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> - <path - inkscape:connector-curvature="0" - clip-path="none" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 117.5,443.75 9,-2.5 0,-6" - style="fill:none;stroke:url(#linearGradient22276);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path22264" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" - id="path22266" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path22268" - d="m 116,443 11,1 -2,-10 -9,9 z" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" /> - <path - inkscape:connector-curvature="0" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - id="path22270" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path22272" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.5,435 0,38.5 -30.5,0" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - </g> - </g> - <g - id="g21517" - inkscape:label="Layer 1" - transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)"> - <path - transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" - d="M 43.487067,38.98439 A 15.467961,5.3033009 0 0 1 28.019106,44.287691 15.467961,5.3033009 0 0 1 12.551145,38.98439 15.467961,5.3033009 0 0 1 28.019106,33.681089 15.467961,5.3033009 0 0 1 43.487067,38.98439 Z" - sodipodi:ry="5.3033009" - sodipodi:rx="15.467961" - sodipodi:cy="38.98439" - sodipodi:cx="28.019106" - id="path35486" - style="opacity:0.54857142;fill:url(#radialGradient21442);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="csssssssssscccsscccscccssccc" - d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z" - id="path2482" - style="fill:#f57900;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" /> - <path - transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" - d="M 42.75,25.75 A 11.5625,10.125 0 0 1 31.1875,35.875 11.5625,10.125 0 0 1 19.625,25.75 11.5625,10.125 0 0 1 31.1875,15.625 11.5625,10.125 0 0 1 42.75,25.75 Z" - sodipodi:ry="10.125" - sodipodi:rx="11.5625" - sodipodi:cy="25.75" - sodipodi:cx="31.1875" - id="path39153" - style="fill:url(#linearGradient21444);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" /> - <path - inkscape:connector-curvature="0" - style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" - d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 z" - id="path21414" - sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" /> - <path - inkscape:connector-curvature="0" - d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z" - id="path2478" - style="fill:#3465a4;fill-rule:evenodd;stroke:none" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc" - id="path39166" - d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 z" - style="opacity:0.51999996;fill:url(#radialGradient21448);fill-opacity:1;fill-rule:evenodd;stroke:none" /> - </g> - </g> - <g - style="opacity:0.5" - id="g24847" - transform="translate(162,248)"> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccssssccc" - style="fill:url(#linearGradient24867);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path24849" - d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" /> - <path - inkscape:connector-curvature="0" - id="path24851" - style="opacity:0.07999998;fill:url(#linearGradient24869);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" - sodipodi:nodetypes="cccccccccccccccccccccccccccccc" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="74.800003" - inkscape:export-xdpi="74.800003" - inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" - sodipodi:nodetypes="csccsczc" - id="path24853" - d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" - style="fill:url(#linearGradient24871);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <path - inkscape:connector-curvature="0" - d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z" - id="path24855" - style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - sodipodi:nodetypes="ccssccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" - d="m 840.5,89 0,4.5" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - id="path24857" /> - <path - inkscape:connector-curvature="0" - id="path24859" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccsc" - d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0" - style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" - id="path24861" /> - <path - inkscape:connector-curvature="0" - d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" - id="path24863" - style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:nodetypes="ccccsscccssssccc" /> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:url(#linearGradient24873);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3" - id="path24865" - sodipodi:nodetypes="csscc" /> - </g> - <g - style="opacity:0.5" - transform="translate(114,248)" - id="g24784"> - <path - inkscape:connector-curvature="0" - d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" - id="path24789" - style="fill:url(#linearGradient24809);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:nodetypes="ccccccssssccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccccccccccccccccccccccccc" - d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" - style="opacity:0.07999998;fill:url(#linearGradient24811);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - id="path24791" /> - <path - inkscape:connector-curvature="0" - style="fill:url(#linearGradient24813);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" - id="path24793" - sodipodi:nodetypes="csccsczc" - inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" - inkscape:export-xdpi="74.800003" - inkscape:export-ydpi="74.800003" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccssccc" - style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path24796" - d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z" /> - <path - inkscape:connector-curvature="0" - id="path24799" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - d="m 840.5,89 0,4.5" - sodipodi:nodetypes="cc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - id="path24801" /> - <path - inkscape:connector-curvature="0" - id="path24803" - style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" - d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0" - sodipodi:nodetypes="cccccccsc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccsscccssssccc" - style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path24805" - d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="csscc" - id="path24807" - d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3" - style="fill:none;stroke:url(#linearGradient24815);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> - </g> - <g - transform="translate(0,-2)" - style="opacity:0.4;stroke:#3d361a;filter:url(#filter44473)" - id="g44424"> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" - id="path44406" - d="m 950.25,362 -5.25,0 -1,-1 0,-10" - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path44408" - d="M 948.25,354.25 944,350.00563 939.75,354.25" - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" /> - </g> - <g - transform="translate(617,273)" - id="g44334" - style="display:inline;enable-background:new"> - <rect - style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect44336" - width="16" - height="16" - x="320" - y="73" /> - <g - transform="translate(0,-21)" - id="g44338"> - <g - id="g44340"> - <g - transform="translate(0,21)" - id="g44342"> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" - id="path44344" - d="m 333.25,87 -5.25,0 -1,-1 0,-10" - style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path44346" - d="M 331.25,79.25 327,75.005631 322.75,79.25" - style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - </g> - <g - transform="translate(0,21)" - id="g44348"> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 333.25,87 -5.25,0 -1,-1 0,-10" - id="path44350" - sodipodi:nodetypes="cccc" /> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="M 331.25,79.25 327,75.005631 322.75,79.25" - id="path44352" - sodipodi:nodetypes="ccc" /> - </g> - </g> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 328.5,107.5 5,0 m -7,-9 0,8.5 m -4.25,-7 4.5,-4.5" - id="path44354" - sodipodi:nodetypes="cccccc" /> - </g> - </g> - <g - transform="translate(66,248)" - id="g24818" - style="display:inline;enable-background:new"> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccssssccc" - style="fill:url(#linearGradient24839);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path24821" - d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" /> - <path - inkscape:connector-curvature="0" - id="path24823" - style="opacity:0.07999998;fill:url(#linearGradient24841);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" - sodipodi:nodetypes="cccccccccccccccccccccccccccccc" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="74.800003" - inkscape:export-xdpi="74.800003" - inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" - sodipodi:nodetypes="csccsczc" - id="path24825" - d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-16 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,17 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" - style="fill:url(#linearGradient24843);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <path - inkscape:connector-curvature="0" - d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z" - id="path24827" - style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - sodipodi:nodetypes="ccssccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" - d="m 840.5,89 0,7.5" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - id="path24829" /> - <path - inkscape:connector-curvature="0" - id="path24831" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - d="m 848.5,98.75 0,14.75 c 0,1.25 0.25,3 -1.25,4" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccsc" - d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-16 34,0 m -29,-10 c 0,0.5 0.5286,1 1,1 l 20,0" - style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" - id="path24833" /> - <path - inkscape:connector-curvature="0" - d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-16 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-8 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" - id="path24835" - style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:nodetypes="ccccsscccssssccc" /> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:url(#linearGradient24845);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 841.5,96.500004 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,15.999996 c 0,2.25 -1.25,3 -2.5,3" - id="path24837" - sodipodi:nodetypes="csscc" /> - </g> - <g - style="opacity:0.4;filter:url(#filter44477)" - id="g44455"> - <path - inkscape:connector-curvature="0" - transform="translate(645,252.05)" - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - id="path44446" - sodipodi:nodetypes="cs" /> - <path - inkscape:connector-curvature="0" - transform="translate(645,252.05)" - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 343,108.25 0,-4.25 4.25,0" - id="path44449" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - transform="matrix(-1,0,0,-1,1343,456.05)" - sodipodi:nodetypes="cs" - id="path44451" - d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <path - inkscape:connector-curvature="0" - transform="matrix(-1,0,0,-1,1343,456.05)" - sodipodi:nodetypes="ccc" - id="path44453" - d="m 343,108.25 0,-4.25 4.25,0" - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - </g> - <g - transform="translate(645,273.05)" - id="g44356" - style="display:inline;enable-background:new"> - <rect - y="73" - x="341" - height="16" - width="16" - id="rect44358" - style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - transform="translate(0,-21)" - id="g44360"> - <g - id="g44362"> - <g - id="g44364"> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cs" - id="path44366" - d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path44368" - d="m 343,108.25 0,-4.25 4.25,0" - style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - </g> - <g - id="g44370"> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 343,108.25 0,-4.25 4.25,0" - id="path44372" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - id="path44374" - sodipodi:nodetypes="cs" /> - </g> - <path - inkscape:connector-curvature="0" - id="path44376" - d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z" - style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - </g> - <g - id="g44378" - transform="matrix(-1,0,0,-1,698,204)"> - <g - id="g44380"> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - id="path44382" - sodipodi:nodetypes="cs" /> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 343,108.25 0,-4.25 4.25,0" - id="path44384" - sodipodi:nodetypes="ccc" /> - </g> - <g - id="g44386"> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path44388" - d="m 343,108.25 0,-4.25 4.25,0" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cs" - id="path44390" - d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - </g> - <path - inkscape:connector-curvature="0" - style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z" - id="path44392" /> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:url(#linearGradient44402);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 344.90625,106.59375 c 2.52573,2.51828 6.66805,2.52691 9.1875,0 l 0.5,-0.5" - id="path44394" - sodipodi:nodetypes="ccc" /> - </g> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 350.5,99.5 4,0 0,-4" - id="path44396" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 347.5,103.5 -4.5,0 c -0.25,0 -0.5,0.25 -0.5,0.5 l 0,4.5" - id="path44398" - sodipodi:nodetypes="cccc" /> - <path - inkscape:connector-curvature="0" - style="fill:none;stroke:url(#linearGradient44404);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 345.59375,105.90625 c 2.07803,2.0719 5.36384,2.10325 7.53125,0.1875 L 354,105.25" - id="path44400" - sodipodi:nodetypes="ccc" /> - </g> - </g> - <g - id="g34977" - style="display:inline;enable-background:new"> - <g - style="display:inline" - id="g21853-3" - transform="translate(856,-154)" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <rect - ry="0" - rx="2.4004419" - y="430" - x="108" - height="48" - width="48" - id="rect21855-8" - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - id="g21857-6"> - <path - inkscape:connector-curvature="0" - style="fill:url(#linearGradient21875-7-1-0-1);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - id="path21859-9" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21861-8" - sodipodi:nodetypes="cccc" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106-9-2-9-9)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21863-6" - d="m 115,444 12,0 -1,-11 -11,11 z" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-6-7-0-8)" /> - <path - inkscape:connector-curvature="0" - clip-path="none" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 117.5,443.75 9,-2.5 0,-6" - style="fill:none;stroke:url(#linearGradient21877-3-2-7-2);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path21865-6" - sodipodi:nodetypes="ccc" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" - id="path21867-2" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - clip-path="url(#clipPath13106-9-2-9-9)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21869-3" - d="m 116,443 11,1 -2,-10 -9,9 z" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011-6-7-0-8)" /> - <path - inkscape:connector-curvature="0" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - id="path21871-8" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccc" - id="path21873-2" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.5,435 0,38.5 -30.5,0" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - </g> - </g> - <g - id="g34938" - transform="translate(63,-47)"> - <path - id="path61236" - style="color:#000000;fill:url(#linearGradient34959-9-2-1);fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:0.17893334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 919.5,356.5067 0,-3 c 0,-1.73575 1.26424,-3 3,-3 l 5,0 c 1.73576,0 3,-1.26425 3,-3 l 0,-3.0064 2.5,0.006 c 2,0 3.5,2.5 3.5,6 0,3.5 -1.25,6 -3.5,6 -4.98134,0 -12.77318,0 -2.5,0 l 0,2.75 c 0,2.5 -2,3.24997 -5.5,3.24998 l 0,2e-5 c -3.5,0.0104 -5.5,-0.75 -5.5,-3.25 l 0,-2.7628" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cssssccsscsccsc" /> - <path - sodipodi:nodetypes="cssssccsscsccsc" - inkscape:connector-curvature="0" - d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3.0064 -2.5,-0.006 c -2,0 -3.5,-2.5 -3.5,-6 0,-3.5 1.25,-6 3.5,-6 4.98134,0 12.77318,0 2.5,0 l 0,-2.75 c 0,-2.5 2,-3.24997 5.5,-3.24998 l 0,-2e-5 c 3.5,-0.0104 5.5,0.75 5.5,3.25 l 0,2.7628" - style="color:#000000;fill:url(#linearGradient34961-3-6-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.17893334;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path61233" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccscccsccccsccccc" - id="path61167" - d="m 925,338.50002 c -3.5,10e-6 -5.5,0.74998 -5.5,3.24998 l 0,2.75 5.5,0 -8,0 c -2.25,0 -3.5,2.5 -3.5,6 0,3.5 1.5,6 3.5,6 l 2.5,0.0128 0,2.9872 c 0,2 2,3.01281 5.5,3.0128 3.5,-1e-5 5.5,-1.0128 5.5,-3.0128 l 0,-3 -5.5,0 8,0 c 2,0 3.5,-2.5 3.5,-6 0,-3.5 -1.5,-6 -3.5,-6 l -2.5,0.0128 0,-2.7628 c 0,-2.5 -2,-3.26045 -5.5,-3.25 z" - style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-miterlimit:4;stroke-opacity:0.8627451;stroke-dasharray:none" /> - <path - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" - id="path61169" - d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3" - style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.78431373;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <path - d="m 923,342 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z" - sodipodi:ry="1" - sodipodi:rx="1" - sodipodi:cy="342" - sodipodi:cx="922" - id="path61220" - style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" /> - <path - d="m 929,359 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z" - sodipodi:ry="1" - sodipodi:rx="1" - sodipodi:cy="359" - sodipodi:cx="928" - id="path61222" - style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" /> - <g - style="opacity:0.4" - id="g61345"> - <path - style="fill:none;stroke:url(#linearGradient34963-5-9-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" - d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75" - id="path61333" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cszsc" /> - <path - style="fill:none;stroke:url(#linearGradient34965-1-5-2);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5 0,3 1.28917,5 2.5,5 l 1.5,0" - id="path61335" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccszsc" /> - <path - style="fill:none;stroke:none" - d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5" - id="path61337" - inkscape:connector-curvature="0" /> - <path - style="fill:none;stroke:none" - d="m 918.5,355.25 0,-1.75 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5" - id="path61339" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cssssc" /> - <path - transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" - sodipodi:type="arc" - style="color:#000000;fill:none;stroke:url(#linearGradient34967-4-1-8);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path61355" - sodipodi:cx="922" - sodipodi:cy="342" - sodipodi:rx="1" - sodipodi:ry="1" - d="m 923,342 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z" /> - </g> - <g - style="opacity:0.8;stroke:#ff0000" - transform="matrix(-1,0,0,-1,1850,701)" - id="g34104"> - <path - sodipodi:nodetypes="cszsc" - inkscape:connector-curvature="0" - id="path34106" - d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75" - style="fill:none;stroke:none" /> - <path - sodipodi:nodetypes="csc" - inkscape:connector-curvature="0" - id="path34108" - d="m 914.5,350.5 c 0,3 1.28917,5 2.5,5 l 1.5,0" - style="fill:none;stroke:url(#linearGradient34969-4-4-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> - <path - inkscape:connector-curvature="0" - id="path34110" - d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5" - style="fill:none;stroke:url(#linearGradient34971-5-0-9);stroke-linecap:round;stroke-linejoin:round" /> - <path - sodipodi:nodetypes="cssssc" - inkscape:connector-curvature="0" - id="path34113" - d="m 918.5,355.5 0,-2 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5" - style="fill:none;stroke:url(#radialGradient34973-2-5-7);stroke-linecap:round;stroke-linejoin:round" /> - <path - d="m 923,342 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z" - sodipodi:ry="1" - sodipodi:rx="1" - sodipodi:cy="342" - sodipodi:cx="922" - id="path34115" - style="color:#000000;fill:none;stroke:url(#linearGradient34975-9-4-9);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" - transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" /> - <path - style="fill:none;stroke:none" - d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5" - id="path34901" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccsc" /> - </g> - </g> - </g> - <g - style="display:inline;enable-background:new" - id="g14765" - inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_big_redone 5a.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - transform="translate(1090.1244,-109.28264)"> - <rect - ry="0" - rx="2.4004419" - y="336.28265" - x="-78.124435" - height="48" - width="48" - id="rect14767" - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path14769" - d="m -60.624426,339.78264 22.999995,0 0,41 -32.999995,0 0,-31 10,-10 z" - style="fill:url(#linearGradient14814);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="cccc" - id="path14771" - style="opacity:0.7;fill:none;stroke:url(#linearGradient14816);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:0.56470588" - d="m -38.874431,340.78264 c -4.875,0 -21.749995,0 -21.749995,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-8)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path14773" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106-0)" - inkscape:connector-curvature="0" - transform="translate(-186.12444,-93.717362)" /> - <path - sodipodi:nodetypes="ccc" - id="path14775" - style="fill:none;stroke:url(#linearGradient14818);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m -68.624426,350.03264 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m -70.624426,349.03264 0,31.75 32.999995,0 0,-41 -23.749995,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path14777" - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011-8)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path14779" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106-0)" - inkscape:connector-curvature="0" - transform="translate(-186.12444,-93.717362)" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path14781" - d="m -70.124426,349.28264 0.0108,0.72434 9.9892,-2.72434 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:0.75294118;fill-rule:evenodd;stroke:none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m -38.624431,341.28264 0,38.5 -30.499995,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path14783" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> - <g - transform="matrix(0.5406242,0,0,0.5829534,-67.987756,347.93806)" - inkscape:label="Layer 1" - id="g14785"> - <path - sodipodi:type="arc" - style="opacity:0.54857142;fill:url(#radialGradient14820);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path14788" - sodipodi:cx="28.019106" - sodipodi:cy="38.98439" - sodipodi:rx="15.467961" - sodipodi:ry="5.3033009" - d="M 43.487067,38.98439 A 15.467961,5.3033009 0 0 1 28.019106,44.287691 15.467961,5.3033009 0 0 1 12.551145,38.98439 15.467961,5.3033009 0 0 1 28.019106,33.681089 15.467961,5.3033009 0 0 1 43.487067,38.98439 Z" - transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" /> - <path - style="fill:#f57900;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" - id="path14790" - d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z" - sodipodi:nodetypes="csssssssssscccsscccscccssccc" - inkscape:connector-curvature="0" /> - <path - sodipodi:type="arc" - style="fill:url(#linearGradient14822);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path14792" - sodipodi:cx="31.1875" - sodipodi:cy="25.75" - sodipodi:rx="11.5625" - sodipodi:ry="10.125" - d="M 42.75,25.75 A 11.5625,10.125 0 0 1 31.1875,35.875 11.5625,10.125 0 0 1 19.625,25.75 11.5625,10.125 0 0 1 31.1875,15.625 11.5625,10.125 0 0 1 42.75,25.75 Z" - transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" /> - <path - sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" - id="path14794" - d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 z" - style="opacity:0.4857143;fill:none;stroke:url(#linearGradient14825);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" - inkscape:connector-curvature="0" /> - <path - style="fill:#3465a4;fill-rule:evenodd;stroke:none" - id="path14796" - d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.51999996;fill:url(#radialGradient14827);fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 z" - id="path14798" - sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc" - inkscape:connector-curvature="0" /> - </g> - </g> - </g> - <g id="ICON_FULLSCREEN_ENTER" inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\fullscreen.png" inkscape:export-xdpi="90" @@ -92433,6 +90782,1880 @@ sodipodi:nodetypes="ccsccsc" inkscape:connector-curvature="0" /> </g> + <rect + y="180.18372" + x="871.95667" + height="192" + width="192" + id="rect30285" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.39191818;marker:none;enable-background:accumulate" /> + <g + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + transform="translate(859.95667,-201.81628)" + id="g21955" + style="display:inline;opacity:0.3;enable-background:new"> + <rect + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" + id="rect21957" + width="48" + height="48" + x="108" + y="430" + rx="2.4004419" + ry="0" /> + <g + id="g21959"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path21961" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient21977);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" + id="path21963" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 115,444 12,0 -1,-11 -11,11 z" + id="path21965" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106-7)" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21967" + style="fill:none;stroke:url(#linearGradient21979);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 117.5,443.75 9,-2.5 0,-6" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21969" + sodipodi:nodetypes="cccccc" /> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 116,443 11,1 -2,-10 -9,9 z" + id="path21971" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106-7)" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path21973" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.5,435 0,38.5 -30.5,0" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21975" + sodipodi:nodetypes="ccc" /> + </g> + </g> + <g + style="display:inline;enable-background:new" + transform="translate(3.9566736,0.18371585)" + id="g30335"> + <g + id="g21367" + transform="translate(760,-202)"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path21369" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient30321);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" + id="path21371" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 115,444 12,0 -1,-11 -11,11 z" + id="path21373" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106-7)" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21375" + style="fill:none;stroke:url(#linearGradient30323);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 117.5,443.75 9,-2.5 0,-6" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21377" + sodipodi:nodetypes="cccccc" /> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 116,443 11,1 -2,-10 -9,9 z" + id="path21569" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106-7)" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path21379" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.5,435 0,38.5 -30.5,0" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21381" + sodipodi:nodetypes="ccc" /> + </g> + <path + inkscape:connector-curvature="0" + style="font-style:normal;font-weight:normal;font-size:33.49144363px;font-family:'Bitstream Vera Sans';display:inline;fill:#214478;fill-opacity:1;stroke:none" + d="m 891.07148,245 -0.0715,9 2.39012,0 C 896,254 896,253 896.5,251 l 0.5,0 0,7 -0.5,0 c -0.5,-2 -0.5,-3 -3.10988,-3 L 891,255 l 0,7 c 0,2.5 1,3.25 3.14146,3.39973 l -0.004,0.60029 L 885,266 l 0.004,-0.60029 C 887,265.25 888,264.5 888.00001,262 L 888,248 c 0,-2.5 -1,-3.25 -3,-3.5 l 0,-0.5 16,0 0,5 -0.5,0 c -0.50001,-1.99999 -1.5,-4 -4.5,-4 l -4.92852,0 z" + id="text13209" + sodipodi:nodetypes="ccccccccccccccccccccccc" /> + </g> + <g + style="display:inline;enable-background:new" + id="g21625" + transform="translate(907.95667,-153.81628)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect21627" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <g + id="g21629"> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient21647);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path21631" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <g + style="display:inline;opacity:0.5;fill:#000000" + id="g16261" + transform="matrix(1.2499985,0,0,1,-87.6203,-147.85351)"> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect35099" + width="17.600004" + height="1" + x="167.69646" + y="598.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect35101" + width="17.600004" + height="1" + x="167.69646" + y="600.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15690" + width="17.600004" + height="1" + x="167.69646" + y="602.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15692" + width="17.600004" + height="1" + x="167.69646" + y="604.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15694" + width="17.600004" + height="1" + x="167.69646" + y="606.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15696" + width="17.600004" + height="1" + x="167.69646" + y="608.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15698" + width="17.600004" + height="1" + x="167.69646" + y="610.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15700" + width="17.600004" + height="1" + x="167.69646" + y="612.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15732" + width="14.400002" + height="1" + x="167.69646" + y="614.85352" + rx="0.09920612" + ry="0.065390877" /> + <g + transform="translate(150.89645,557.85352)" + id="g4849" + style="display:inline;fill:#000000"> + <rect + ry="0.065390877" + rx="0.12125195" + y="29" + x="16.799992" + height="1" + width="17.600004" + id="rect15736" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + ry="0.065390877" + rx="0.12125195" + y="31" + x="16.799992" + height="1" + width="17.600004" + id="rect15738" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + ry="0.065390877" + rx="0.12125195" + y="33" + x="16.799992" + height="1" + width="17.600004" + id="rect15740" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + ry="0.065390877" + rx="0.12125195" + y="35" + x="16.799992" + height="1" + width="17.600004" + id="rect15742" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + ry="0.065390877" + rx="0.055114571" + y="37" + x="16.799992" + height="1" + width="8.0000095" + id="rect15744" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + </g> + <rect + ry="0.065390304" + rx="0.0057410933" + y="617.85352" + x="184.49646" + height="0.99999124" + width="0.83333319" + id="rect16334" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + </g> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21633" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-7)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21635" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient21649);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path21637" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path21639" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-7)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21641" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path21643" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <g + id="g35119" + transform="translate(2,-160.99999)" + style="display:inline"> + <g + style="display:inline" + transform="translate(105.39645,589.71201)" + id="g16097"> + <g + id="g16099" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4" + transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)"> + <radialGradient + id="radialGradient16101" + cx="20.892099" + cy="114.5684" + r="5.256" + fx="20.892099" + fy="114.5684" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#F0F0F0" + id="stop16103" /> + <stop + offset="1" + style="stop-color:#474747" + id="stop16105" /> + </radialGradient> + <radialGradient + id="radialGradient16109" + cx="20.892099" + cy="64.567902" + r="5.257" + fx="20.892099" + fy="64.567902" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#F0F0F0" + id="stop16111" /> + <stop + offset="1" + style="stop-color:#474747" + id="stop16113" /> + </radialGradient> + </g> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z" + id="path16107" /> + <path + inkscape:connector-curvature="0" + style="fill:url(#radialGradient21565);fill-rule:nonzero;stroke:none" + d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z" + id="path16117" /> + </g> + <g + id="g16131" + transform="translate(105.39645,579.71201)" + style="display:inline"> + <g + transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4" + id="g16133"> + <radialGradient + gradientUnits="userSpaceOnUse" + fy="114.5684" + fx="20.892099" + r="5.256" + cy="114.5684" + cx="20.892099" + id="radialGradient16135"> + <stop + id="stop16137" + style="stop-color:#F0F0F0" + offset="0" /> + <stop + id="stop16140" + style="stop-color:#474747" + offset="1" /> + </radialGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + fy="64.567902" + fx="20.892099" + r="5.257" + cy="64.567902" + cx="20.892099" + id="radialGradient16142"> + <stop + id="stop16144" + style="stop-color:#F0F0F0" + offset="0" /> + <stop + id="stop16146" + style="stop-color:#474747" + offset="1" /> + </radialGradient> + </g> + <path + inkscape:connector-curvature="0" + id="path35139" + d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z" + style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + inkscape:connector-curvature="0" + id="path35141" + d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z" + style="fill:url(#radialGradient21567);fill-rule:nonzero;stroke:none" /> + </g> + </g> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21645" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> + </g> + <g + style="display:inline;enable-background:new" + id="g21572" + transform="translate(811.95667,-201.81628)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect21574" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <g + id="g21576"> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient21594);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path21578" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21580" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-7)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21582" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient21596);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path21584" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path21586" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-7)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21588" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path21590" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21592" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> + </g> + <g + style="display:inline;enable-background:new" + transform="translate(3.9566736,0.18371585)" + id="g30382"> + <g + id="g23655" + transform="translate(760,-154)"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path23657" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient30368);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" + id="path23659" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 115,444 12,0 -1,-11 -11,11 z" + id="path23661" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106-7)" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path23663" + style="fill:none;stroke:url(#linearGradient30370);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 117.5,443.75 9,-2.5 0,-6" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path23665" + sodipodi:nodetypes="cccccc" /> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 116,443 11,1 -2,-10 -9,9 z" + id="path23667" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106-7)" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path23669" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.5,435 0,38.5 -30.5,0" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path23671" + sodipodi:nodetypes="ccc" /> + </g> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" + d="m 888,295 1,0 0,14 -1,0 0,-14 z" + id="path23675" + sodipodi:nodetypes="ccccc" /> + <path + inkscape:connector-curvature="0" + id="path23677" + d="m 900,294 1.00002,-1 0,14 -1.00002,0 0,-13 z" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" + sodipodi:nodetypes="ccccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" + id="path23679" + d="m 901.00003,292 0,2.25 -13.00002,2 0,-2.25 13.00002,-2 z" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" /> + <g + id="g23681" + transform="matrix(1.1428564,0,0,1.2000001,822.71436,-355.40005)"> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" + id="path23683" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" /> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + style="display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;filter:url(#filter20578-5);enable-background:accumulate" + id="path23685" + transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)" + inkscape:transform-center-y="0.3813435" + clip-path="url(#clipPath20586-3)" /> + </g> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;opacity:0.38999999;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" + d="m 901.00003,292 -1e-5,1 -13.00002,2 10e-6,-1 13.00002,-2 z" + id="path23694" + sodipodi:nodetypes="ccccc" /> + <g + transform="matrix(1.1428564,0,0,1.2000001,834.71436,-357.40005)" + id="g23717"> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" + id="path23724" + transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" /> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + clip-path="url(#clipPath20586-3)" + inkscape:transform-center-y="0.3813435" + transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)" + id="path23726" + style="display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;filter:url(#filter20578-5);enable-background:accumulate" /> + </g> + </g> + <g + id="g23922" + transform="translate(-12.043326,-219.81628)" + style="display:inline;enable-background:new"> + <g + style="display:inline" + id="g23924" + transform="translate(824,66)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect23926" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <g + id="g23928"> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient23978);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path23930" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path23932" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-7)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path23934" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient23980);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path23936" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path23938" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-7)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path23940" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path23942" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path23944" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> + </g> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccc" + id="path23946" + d="m 952,530 0,10 1,0 1,0 11,0 1,0 1,0 0,-10 -15,0 z m 1,2 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <rect + transform="scale(1,-1)" + style="fill:url(#linearGradient23982);fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect23948" + width="13" + height="5.5" + x="953" + y="-524" /> + <path + inkscape:connector-curvature="0" + id="path23952" + transform="translate(76,0)" + d="m 876,514 0,17 15,0 0,-17 -1,0 0,1 -1,0 0,-1 -11,0 0,1 -1,0 0,-1 -1,0 z m 1,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccc" + style="fill:url(#linearGradient23986);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 952,507 3,0 0,3 9,0 0,-3 3,0 0,7 -15,0 0,-7 z m 1,0 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z m 12,-4 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z" + id="path23954" /> + <rect + transform="matrix(0,1,1,0,0,0)" + ry="0" + y="955" + x="507" + height="9" + width="3" + id="rect23956" + style="fill:url(#linearGradient23988);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <rect + style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect23958" + width="9" + height="9" + x="512" + y="955" + ry="0" + transform="matrix(0,1,1,0,0,0)" /> + <rect + transform="matrix(0,1,1,0,0,0)" + ry="0" + y="955" + x="523" + height="9" + width="9" + id="rect23960" + style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <circle + r="8" + cy="118" + cx="132" + transform="matrix(0,-0.5624971,0.5624971,0,893.12531,590.74965)" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="path23962" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <circle + r="8" + cy="118" + cx="132" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" + id="path23964" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + transform="matrix(0,-0.5624964,0.5624964,0,893.12545,601.74956)" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccc" + id="path23966" + d="m 961.00001,519.00005 -3,0 0,-0.99992 0.99994,0 6e-5,-2.00008 -1,0 0,-1 1,0 0,-1 1.00006,0 0,4.00008 0.99994,0 0,0.99992 z" /> + <path + inkscape:connector-curvature="0" + d="m 958,525 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" + id="path23968" /> + <rect + style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect23970" + width="6" + height="9" + x="534" + y="955" + ry="0" + transform="matrix(0,1,1,0,0,0)" /> + <g + clip-path="url(#clipPath23877-4)" + id="g23972"> + <circle + r="8" + cy="118" + cx="132" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" + id="path23974" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + transform="matrix(0,-0.5624964,0.5624964,0,893.12545,612.74956)" /> + <path + inkscape:connector-curvature="0" + d="m 958,536 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,1 -2,0 0,1 2,0 0,-1 z" + id="path23976" /> + </g> + </g> + <g + transform="translate(211.95667,88.183716)" + id="g45475" + style="display:inline;enable-background:new"> + <g + style="display:inline" + id="g22242" + transform="translate(696,-194)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect22244" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <g + id="g22246"> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient22274);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path22249" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path22251" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-7)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path22253" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient22276);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path22264" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path22266" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-7)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path22268" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path22270" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path22272" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> + </g> + <g + id="g21517" + inkscape:label="Layer 1" + transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)"> + <ellipse + ry="5.3033009" + rx="15.467961" + cy="38.98439" + cx="28.019106" + transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" + id="path35486" + style="display:inline;overflow:visible;visibility:visible;opacity:0.54857142;fill:url(#radialGradient21442);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="csssssssssscccsscccscccssccc" + d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z" + id="path2482" + style="fill:#f57900;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" /> + <ellipse + ry="10.125" + rx="11.5625" + cy="25.75" + cx="31.1875" + transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" + id="path39153" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient21444);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" + d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 Z" + id="path21414" + sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" /> + <path + inkscape:connector-curvature="0" + d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z" + id="path2478" + style="fill:#3465a4;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc" + id="path39166" + d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 Z" + style="opacity:0.51999996;fill:url(#radialGradient21448);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + </g> + </g> + <g + transform="translate(-0.04332638,0.18371585)" + style="display:inline;enable-background:new" + id="g6090"> + <g + id="g24784" + transform="translate(116,247.5)" + style="opacity:0.5"> + <path + sodipodi:nodetypes="ccccccssssccc" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24809);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="path24789" + d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" + inkscape:connector-curvature="0" /> + <path + id="path24791" + style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:url(#linearGradient24811);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" + sodipodi:nodetypes="cccccccccccccccccccccccccccccc" + inkscape:connector-curvature="0" /> + <path + inkscape:export-ydpi="74.800003" + inkscape:export-xdpi="74.800003" + inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" + sodipodi:nodetypes="csccsczc" + id="path24793" + d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24813);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 Z" + id="path24796" + style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + sodipodi:nodetypes="ccssccc" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="cc" + d="m 840.5,89 0,4.5" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="path24799" + inkscape:connector-curvature="0" /> + <path + id="path24801" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4" + sodipodi:nodetypes="ccc" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="cccccccsc" + d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0" + style="display:inline;opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path24803" + inkscape:connector-curvature="0" /> + <path + d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" + id="path24805" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + sodipodi:nodetypes="ccccsscccssssccc" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:url(#linearGradient24815);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3" + id="path24807" + sodipodi:nodetypes="csscc" + inkscape:connector-curvature="0" /> + </g> + <g + style="display:inline;filter:url(#filter6078);enable-background:new" + id="g44334" + transform="translate(619,272.5)"> + <rect + y="73" + x="320" + height="16" + width="16" + id="rect44336" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;enable-background:accumulate" /> + <g + id="g44338" + transform="translate(0,-21)"> + <g + id="g44340"> + <g + id="g44342" + transform="translate(0,21)"> + <path + style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 333.25,87 -5.25,0 -1,-1 0,-10" + id="path44344" + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 331.25,79.25 327,75.005631 322.75,79.25" + id="path44346" + sodipodi:nodetypes="ccc" + inkscape:connector-curvature="0" /> + </g> + <g + id="g44348" + transform="translate(0,21)"> + <path + sodipodi:nodetypes="cccc" + id="path44350" + d="m 333.25,87 -5.25,0 -1,-1 0,-10" + style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccc" + id="path44352" + d="M 331.25,79.25 327,75.005631 322.75,79.25" + style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:connector-curvature="0" /> + </g> + </g> + <path + sodipodi:nodetypes="cccccc" + id="path44354" + d="m 328.5,107.5 5,0 m -7,-9 0,8.5 m -4.25,-7 4.5,-4.5" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + </g> + </g> + </g> + <g + transform="translate(67.956674,247.68372)" + id="g24818" + style="display:inline;enable-background:new"> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccssssccc" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24839);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="path24821" + d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" /> + <path + inkscape:connector-curvature="0" + id="path24823" + style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:url(#linearGradient24841);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" + sodipodi:nodetypes="cccccccccccccccccccccccccccccc" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="74.800003" + inkscape:export-xdpi="74.800003" + inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" + sodipodi:nodetypes="csccsczc" + id="path24825" + d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-16 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,17 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24843);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 Z" + id="path24827" + style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + sodipodi:nodetypes="ccssccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + d="m 840.5,89 0,7.5" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="path24829" /> + <path + inkscape:connector-curvature="0" + id="path24831" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + d="m 848.5,98.75 0,14.75 c 0,1.25 0.25,3 -1.25,4" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccsc" + d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-16 34,0 m -29,-10 c 0,0.5 0.5286,1 1,1 l 20,0" + style="display:inline;opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path24833" /> + <path + inkscape:connector-curvature="0" + d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-16 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-8 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" + id="path24835" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + sodipodi:nodetypes="ccccsscccssssccc" /> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:url(#linearGradient24845);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 841.5,96.500004 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,15.999996 c 0,2.25 -1.25,3 -2.5,3" + id="path24837" + sodipodi:nodetypes="csscc" /> + </g> + <g + transform="translate(-0.04332638,0.18371585)" + style="display:inline;enable-background:new" + id="g6158"> + <g + transform="translate(164,247.5)" + id="g24847" + style="opacity:0.5"> + <path + d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" + id="path24849" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24867);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + sodipodi:nodetypes="ccccccssssccc" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="cccccccccccccccccccccccccccccc" + d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" + style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:url(#linearGradient24869);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="path24851" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24871);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" + d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" + id="path24853" + sodipodi:nodetypes="csccsczc" + inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" + inkscape:export-xdpi="74.800003" + inkscape:export-ydpi="74.800003" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccssccc" + style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="path24855" + d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 Z" + inkscape:connector-curvature="0" /> + <path + id="path24857" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + d="m 840.5,89 0,4.5" + sodipodi:nodetypes="cc" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccc" + d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="path24859" + inkscape:connector-curvature="0" /> + <path + id="path24861" + style="display:inline;opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0" + sodipodi:nodetypes="cccccccsc" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccccsscccssssccc" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + id="path24863" + d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="csscc" + id="path24865" + d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3" + style="fill:none;stroke:url(#linearGradient24873);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + inkscape:connector-curvature="0" /> + </g> + <g + style="display:inline;filter:url(#filter6146);enable-background:new" + id="g44356" + transform="translate(647,272.55)"> + <rect + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;enable-background:accumulate" + id="rect44358" + width="16" + height="16" + x="341" + y="73" /> + <g + id="g44360" + transform="translate(0,-21)"> + <g + id="g44362"> + <g + id="g44364"> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" + id="path44366" + sodipodi:nodetypes="cs" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + d="m 343,108.25 0,-4.25 4.25,0" + id="path44368" + sodipodi:nodetypes="ccc" + inkscape:connector-curvature="0" /> + </g> + <g + id="g44370"> + <path + sodipodi:nodetypes="ccc" + id="path44372" + d="m 343,108.25 0,-4.25 4.25,0" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="cs" + id="path44374" + d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + </g> + <path + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;enable-background:accumulate" + d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z" + id="path44376" + inkscape:connector-curvature="0" /> + </g> + <g + transform="matrix(-1,0,0,-1,698,204)" + id="g44378"> + <g + id="g44380"> + <path + sodipodi:nodetypes="cs" + id="path44382" + d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccc" + id="path44384" + d="m 343,108.25 0,-4.25 4.25,0" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + </g> + <g + id="g44386"> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + d="m 343,108.25 0,-4.25 4.25,0" + id="path44388" + sodipodi:nodetypes="ccc" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" + id="path44390" + sodipodi:nodetypes="cs" + inkscape:connector-curvature="0" /> + </g> + <path + id="path44392" + d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccc" + id="path44394" + d="m 344.90625,106.59375 c 2.52573,2.51828 6.66805,2.52691 9.1875,0 l 0.5,-0.5" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient44402);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + </g> + <path + sodipodi:nodetypes="ccc" + id="path44396" + d="m 350.5,99.5 4,0 0,-4" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="cccc" + id="path44398" + d="m 347.5,103.5 -4.5,0 c -0.25,0 -0.5,0.25 -0.5,0.5 l 0,4.5" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccc" + id="path44400" + d="m 345.59375,105.90625 c 2.07803,2.0719 5.36384,2.10325 7.53125,0.1875 L 354,105.25" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient44404);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + </g> + </g> + </g> + <g + transform="translate(3.9566736,0.18371585)" + id="g34977" + style="display:inline;enable-background:new"> + <g + style="display:inline" + id="g21853-3" + transform="translate(856,-154)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect21855-8" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <g + id="g21857-6"> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient21875-7-1-0-1);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path21859-9" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21861-8" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-9-2-9-9-4)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21863-6" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-6-7-0-8)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient21877-3-2-7-2);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path21865-6" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path21867-2" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-9-2-9-9-4)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21869-3" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-6-7-0-8)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path21871-8" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21873-2" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> + </g> + <g + id="g34938" + transform="translate(63,-47)"> + <path + id="path61236" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient34959-9-2-1);fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:0.17893334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + d="m 919.5,356.5067 0,-3 c 0,-1.73575 1.26424,-3 3,-3 l 5,0 c 1.73576,0 3,-1.26425 3,-3 l 0,-3.0064 2.5,0.006 c 2,0 3.5,2.5 3.5,6 0,3.5 -1.25,6 -3.5,6 -4.98134,0 -12.77318,0 -2.5,0 l 0,2.75 c 0,2.5 -2,3.24997 -5.5,3.24998 l 0,2e-5 c -3.5,0.0104 -5.5,-0.75 -5.5,-3.25 l 0,-2.7628" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cssssccsscsccsc" /> + <path + sodipodi:nodetypes="cssssccsscsccsc" + inkscape:connector-curvature="0" + d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3.0064 -2.5,-0.006 c -2,0 -3.5,-2.5 -3.5,-6 0,-3.5 1.25,-6 3.5,-6 4.98134,0 12.77318,0 2.5,0 l 0,-2.75 c 0,-2.5 2,-3.24997 5.5,-3.24998 l 0,-2e-5 c 3.5,-0.0104 5.5,0.75 5.5,3.25 l 0,2.7628" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient34961-3-6-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.17893334;marker:none;enable-background:accumulate" + id="path61233" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccscccsccccsccccc" + id="path61167" + d="m 925,338.50002 c -3.5,10e-6 -5.5,0.74998 -5.5,3.24998 l 0,2.75 5.5,0 -8,0 c -2.25,0 -3.5,2.5 -3.5,6 0,3.5 1.5,6 3.5,6 l 2.5,0.0128 0,2.9872 c 0,2 2,3.01281 5.5,3.0128 3.5,-1e-5 5.5,-1.0128 5.5,-3.0128 l 0,-3 -5.5,0 8,0 c 2,0 3.5,-2.5 3.5,-6 0,-3.5 -1.5,-6 -3.5,-6 l -2.5,0.0128 0,-2.7628 c 0,-2.5 -2,-3.26045 -5.5,-3.25 z" + style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.8627451" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path61169" + d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.78431373;marker:none;enable-background:accumulate" /> + <circle + r="1" + cy="342" + cx="922" + id="path61220" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;enable-background:accumulate" /> + <circle + r="1" + cy="359" + cx="928" + id="path61222" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;enable-background:accumulate" /> + <g + style="opacity:0.4" + id="g61345"> + <path + style="fill:none;stroke:url(#linearGradient34963-5-9-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" + d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75" + id="path61333" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cszsc" /> + <path + style="fill:none;stroke:url(#linearGradient34965-1-5-2);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5 0,3 1.28917,5 2.5,5 l 1.5,0" + id="path61335" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccszsc" /> + <path + style="fill:none;stroke:none" + d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5" + id="path61337" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:none" + d="m 918.5,355.25 0,-1.75 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5" + id="path61339" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cssssc" /> + <circle + r="1" + cy="342" + cx="922" + transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient34967-4-1-8);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;enable-background:accumulate" + id="path61355" /> + </g> + <g + style="opacity:0.8;stroke:#ff0000" + transform="matrix(-1,0,0,-1,1850,701)" + id="g34104"> + <path + sodipodi:nodetypes="cszsc" + inkscape:connector-curvature="0" + id="path34106" + d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75" + style="fill:none;stroke:none" /> + <path + sodipodi:nodetypes="csc" + inkscape:connector-curvature="0" + id="path34108" + d="m 914.5,350.5 c 0,3 1.28917,5 2.5,5 l 1.5,0" + style="fill:none;stroke:url(#linearGradient34969-4-4-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path34110" + d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5" + style="fill:none;stroke:url(#linearGradient34971-5-0-9);stroke-linecap:round;stroke-linejoin:round" /> + <path + sodipodi:nodetypes="cssssc" + inkscape:connector-curvature="0" + id="path34113" + d="m 918.5,355.5 0,-2 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5" + style="fill:none;stroke:url(#radialGradient34973-2-5-7);stroke-linecap:round;stroke-linejoin:round" /> + <circle + r="1" + cy="342" + cx="922" + id="path34115" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient34975-9-4-9);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;enable-background:accumulate" + transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" /> + <path + style="fill:none;stroke:none" + d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5" + id="path34901" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccsc" /> + </g> + </g> + </g> + <g + transform="translate(211.95667,-7.8162842)" + id="g45475-4" + style="display:inline;enable-background:new"> + <g + style="display:inline" + id="g22242-6" + transform="translate(696,-194)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect22244-9" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <g + id="g22246-2"> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient22274-8);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path22249-8" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path22251-9" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-5)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path22253-5" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-5)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient22276-5);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path22264-3" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path22266-6" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-5)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path22268-0" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-5)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path22270-1" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path22272-3" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> + </g> + <g + id="g21517-6" + inkscape:label="Layer 1" + transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)"> + <ellipse + ry="5.3033009" + rx="15.467961" + cy="38.98439" + cx="28.019106" + transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" + id="path35486-4" + style="display:inline;overflow:visible;visibility:visible;opacity:0.54857142;fill:url(#radialGradient21442-6-790);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="csssssssssscccsscccscccssccc" + d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z" + id="path2482-9" + style="fill:#dd6d00;fill-rule:evenodd;stroke:#993d00;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" /> + <ellipse + ry="10.125" + rx="11.5625" + cy="25.75" + cx="31.1875" + transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" + id="path39153-3" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient21444-0-352);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446-3-145);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" + d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 Z" + id="path21414-5" + sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" /> + <path + inkscape:connector-curvature="0" + d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z" + id="path2478-8" + style="fill:#2f5b94;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc" + id="path39166-5" + d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 Z" + style="opacity:0.51999996;fill:url(#radialGradient21448-8-143);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + </g> + </g> </g> <g inkscape:groupmode="layer" diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject 9628dc1922be2fb6281bc66f5f7512c2a57c294 +Subproject dc166057192ea882b5cc70484d4c8bacd7cb41b diff --git a/release/datafiles/prvicons.png b/release/datafiles/prvicons.png Binary files differindex 7209385da9c..ccd47438da6 100644 --- a/release/datafiles/prvicons.png +++ b/release/datafiles/prvicons.png diff --git a/release/datafiles/prvicons.svg b/release/datafiles/prvicons.svg index e0894ff2dc8..0d64bf78865 100644 --- a/release/datafiles/prvicons.svg +++ b/release/datafiles/prvicons.svg @@ -14,7 +14,7 @@ height="192" id="svg2" sodipodi:version="0.32" - inkscape:version="0.48.4 r9939" + inkscape:version="0.91 r13725" version="1.0" sodipodi:docname="prvicons.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" @@ -32,19 +32,19 @@ objecttolerance="10000" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="5.6568542" - inkscape:cx="118.09116" - inkscape:cy="73.89985" + inkscape:zoom="4.29" + inkscape:cx="86.93017" + inkscape:cy="96" inkscape:document-units="px" - inkscape:current-layer="g32752" - showgrid="false" + inkscape:current-layer="layer1" + showgrid="true" inkscape:window-width="1920" - inkscape:window-height="1018" - inkscape:window-x="-8" - inkscape:window-y="-8" + inkscape:window-height="1005" + inkscape:window-x="-2" + inkscape:window-y="27" inkscape:snap-nodes="true" - inkscape:snap-bbox="false" - showguides="true" + inkscape:snap-bbox="true" + showguides="false" inkscape:guide-bbox="true" inkscape:object-nodes="false" inkscape:object-paths="false" @@ -53,28 +53,29 @@ inkscape:window-maximized="1" inkscape:bbox-paths="false" inkscape:snap-global="true" - inkscape:snap-bbox-midpoints="false" + inkscape:snap-bbox-midpoints="true" inkscape:snap-grids="true" - inkscape:snap-to-guides="false" + inkscape:snap-to-guides="true" inkscape:snap-page="false" units="px" inkscape:snap-center="false" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" - fit-margin-bottom="0"> + fit-margin-bottom="0" + inkscape:snap-bbox-edge-midpoints="false"> <inkscape:grid originy="0px" originx="0px" snapvisiblegridlinesonly="true" empopacity="0.25098039" - empcolor="#7f7f7f" + empcolor="#7f1118" dotted="false" opacity="0.09803922" color="#808080" empspacing="4" - spacingy="0.25px" - spacingx="0.25px" + spacingy="4" + spacingx="4" enabled="true" visible="true" id="grid17394" @@ -15166,32 +15167,6 @@ id="linearGradient44404" xlink:href="#linearGradient44939-8" inkscape:collect="always" /> - <filter - color-interpolation-filters="sRGB" - height="1.229448" - y="-0.11472401" - width="1.2515693" - x="-0.12578467" - id="filter44473" - inkscape:collect="always"> - <feGaussianBlur - id="feGaussianBlur44475" - stdDeviation="0.81235925" - inkscape:collect="always" /> - </filter> - <filter - color-interpolation-filters="sRGB" - height="1.2365714" - y="-0.11828571" - width="1.2435294" - x="-0.12176471" - id="filter44477" - inkscape:collect="always"> - <feGaussianBlur - id="feGaussianBlur44479" - stdDeviation="0.8625" - inkscape:collect="always" /> - </filter> <linearGradient y2="106.5" x2="284.5" @@ -17793,19 +17768,6 @@ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" style="fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" /> </clipPath> - <filter - color-interpolation-filters="sRGB" - id="filter63011-8" - height="2.0133312" - y="-0.50666559" - width="1.9120018" - x="-0.45600089" - inkscape:collect="always"> - <feGaussianBlur - id="feGaussianBlur63013-2" - stdDeviation="1.899998" - inkscape:collect="always" /> - </filter> <linearGradient y2="383.69843" x2="174.29811" @@ -17928,6 +17890,78 @@ offset="1" id="stop39175-18" /> </linearGradient> + <filter + style="color-interpolation-filters:sRGB;" + inkscape:label="Drop Shadow" + id="filter6078" + x="-0.29999999999999999" + width="1.3500000000000001" + height="1.3999999999999999" + y="-0.14999999999999999"> + <feFlood + flood-opacity="0.40000000000000002" + flood-color="rgb(0,0,0)" + result="flood" + id="feFlood6080" /> + <feComposite + in="flood" + in2="SourceGraphic" + operator="in" + result="composite1" + id="feComposite6082" /> + <feGaussianBlur + in="composite1" + stdDeviation="1.5" + result="blur" + id="feGaussianBlur6084" /> + <feOffset + dx="-2" + dy="2" + result="offset" + id="feOffset6086" /> + <feComposite + in="SourceGraphic" + in2="offset" + operator="over" + result="composite2" + id="feComposite6088" /> + </filter> + <filter + style="color-interpolation-filters:sRGB;" + inkscape:label="Drop Shadow" + id="filter6146" + x="-0.29999999999999999" + width="1.3500000000000001" + y="-0.14999999999999999" + height="1.3999999999999999"> + <feFlood + flood-opacity="0.40000000000000002" + flood-color="rgb(0,0,0)" + result="flood" + id="feFlood6148" /> + <feComposite + in="flood" + in2="SourceGraphic" + operator="in" + result="composite1" + id="feComposite6150" /> + <feGaussianBlur + in="composite1" + stdDeviation="1.5" + result="blur" + id="feGaussianBlur6152" /> + <feOffset + dx="-2" + dy="2" + result="offset" + id="feOffset6154" /> + <feComposite + in="SourceGraphic" + in2="offset" + operator="over" + result="composite2" + id="feComposite6156" /> + </filter> </defs> <metadata id="metadata7"> @@ -17989,6 +18023,600 @@ id="path23347" style="fill:none;stroke:#ffffff;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> <g + inkscape:groupmode="layer" + id="layer4" + inkscape:label="sheet_layout" + sodipodi:insensitive="true"> + <path + inkscape:connector-curvature="0" + id="path19551-18-1" + d="m 35.75,29.5 0,1 -0.5,0 0,1 0.5,0 0,1 -0.75,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 0.5,0 0,-1 -0.5,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + id="path30643-7-0" + d="m 31.75,29.5 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z m 0.25,1 0,1 0.5,0 0,-1 -0.5,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path30647-6-1" + d="m 19,29.5 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path30649-7-4" + d="m 25,29.5 0,3 1,0 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <rect + y="33.5" + x="23" + height="1" + width="1" + id="rect30651-8-6" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect30653-7-0" + width="1" + height="1" + x="29" + y="33.5" /> + <rect + y="33.5" + x="15" + height="1" + width="1" + id="rect30725-8-7" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + id="path30723-1-1" + d="m 11,31.5 0,2.25 1,0 0,0.75 1,0 0,-0.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + sodipodi:nodetypes="ccccccccccccc" + inkscape:connector-curvature="0" /> + <g + transform="translate(-62,136.5)" + id="g72798" + style="display:inline;opacity:0.5;enable-background:new"> + <g + id="g72716"> + <path + id="path72434" + d="m 186,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <rect + y="-127" + x="219" + height="5" + width="1" + id="rect72436" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + id="path72438" + d="m 144,-127 0,4 -1,0 0,-1 -1,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-4 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72440" + d="m 189,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72442" + d="m 165,-127 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72446" + d="m 130,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72448" + d="m 154,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72450" + d="m 133,-127 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72452" + d="m 138,-127 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72454" + d="m 151,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72456" + d="m 146,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 209,-127 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z" + id="path72458" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 160,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + id="path72460" /> + <path + id="path72462" + d="m 171,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72464" + d="m 175,-127 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 179,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z" + id="path72466" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 194,-127 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z" + id="path72468" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 202,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z" + id="path72470" /> + <path + id="path72472" + d="m 205,-127 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path72474" + d="m 215,-127 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 222,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z" + id="path72476" /> + <path + id="path72478" + d="m 225,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 229,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z" + id="path72480" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 235,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z" + id="path72482" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 238,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z" + id="path72484" /> + <path + id="path72486" + d="m 242.75,-123 0,1 -0.75,0 0,1 1,0 0,-1 1,0 0,-1 -1.25,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path32008-7" + d="m 72,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32010-4" + d="m 76,-127 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + y="-127" + x="80" + height="5" + width="1" + id="rect32012-0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32015-9" + d="m 83,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32017-4" + d="m 89,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32019-8" + d="m 97,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32021-8" + d="m 93,-127 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32023-2" + d="m 102,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32026-4" + d="m 106,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 110,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z" + id="path32029-5" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 115,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + id="path32031-5" /> + <rect + y="-127" + x="121" + height="5" + width="1" + id="rect32033-1" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 124,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z" + id="path32035-7" /> + </g> + <g + id="g72757"> + <path + id="path72562" + d="m 78,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <rect + y="-119" + x="82" + height="5" + width="1" + id="rect72564" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + id="path72576" + d="m 72,-119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-2 -1,0 0,2 -1,0 0,-3 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72578" + d="m 130,-119 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72580" + d="m 94.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72582" + d="m 85,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 88,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z" + id="path72588" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 99,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z" + id="path72590" /> + <path + id="path72592" + d="m 103,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 107,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z" + id="path72594" /> + <path + id="path72596" + d="m 111,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 117,-119 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z" + id="path72598" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 121.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z" + id="path72600" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 125,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z" + id="path72602" /> + <rect + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect72604" + width="1" + height="5" + x="136" + y="-119" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 138,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + id="path72606" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 144.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z" + id="path72608" /> + <path + inkscape:connector-curvature="0" + id="path72610" + d="m 148,-119 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 153,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z" + id="path72612" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 157,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z" + id="path72614" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 163,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z" + id="path72616" /> + <rect + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect72618" + width="1" + height="5" + x="174" + y="-119" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 168,-119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-2 -1,0 0,2 -1,0 0,-3 -1,0 z" + id="path72620" /> + <path + id="path72622" + d="m 180,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + id="path72624" + d="m 176,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path32207-9-7" + d="m 187,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32209-6-7" + d="m 191,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32211-3-7" + d="m 195,-119 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32213-7-3" + d="m 199,-119 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32216-8-3" + d="m 203,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect32218-8-5" + width="1" + height="5" + x="207" + y="-119" /> + <path + inkscape:connector-curvature="0" + id="path32220-2-9" + d="m 210,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32222-9-9" + d="m 213,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32224-1-8" + d="m 217,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + id="path72678" + d="m 225,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 235,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z" + id="path72680" + inkscape:connector-curvature="0" /> + <rect + y="-119" + x="223" + height="5" + width="1" + id="rect72682" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + y="-115" + x="239" + height="1" + width="1" + id="rect72684" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + id="path72686" + d="m 230,-119 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + </g> + </g> + <g + transform="translate(-62,136.5)" + style="display:inline;enable-background:new" + id="g72880"> + <g + transform="translate(231,-90)" + id="g32242-4"> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m -12.25,-17 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z" + id="path32244-2" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m -9,-17 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z" + id="path32246-0" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m -3,-17 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z" + id="path32248-9" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 1,-17 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z" + id="path32250-7" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 6,-17 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z" + id="path32252-3" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 10,-17 0,1 2,0 0,1 1,0 0,-1 0,-1 -3,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" + id="path32254-7" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m -43.25,-17 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z" + id="path32256-2" /> + <path + inkscape:connector-curvature="0" + id="path32258-6" + d="m -40,-17 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32260-0" + d="m -35,-17 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m -31,-17 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z" + id="path32262-1" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m -27,-17 0,1 2,0 0,1 1,0 0,-1 0,-1 -3,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" + id="path32264-6" /> + <path + inkscape:connector-curvature="0" + id="path32266-5" + d="m -23,-17 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + id="path32268-7" + d="m -17,-17 0,4 -1,0 0,-1 -1,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-4 -1,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <rect + y="-19" + x="11" + height="1" + width="1" + id="rect32270-5" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + </g> + <g + id="g21967-4" + transform="translate(111.96875,-88)"> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 48,-20 0,0.75 -1,0 0,0.25 -0.25,0 0,1 -0.75,0 0,3 0.75,0 0,1 0.25,0 0,0.25 1,0 0,0.75 3,0 0,-0.75 1,0 0,-0.25 0.25,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -0.25,0 0,-0.25 -1,0 0,-0.75 -3,0 z m 0,1 3,0 0,1 1,0 0,3 -1,0 0,1 -3,0 0,-1 -1,0 0,-3 1,0 0,-1 z" + id="path32272-1" + sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccc" /> + <path + inkscape:connector-curvature="0" + id="path32274-2" + d="m 49,-18 0,0.75 -1,0 0,1.5 1,0 0,0.75 1.25,0 0,-1 -1.25,0 0,-1 1.25,0 0,-1 -1.25,0 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + sodipodi:nodetypes="ccccccccccccc" /> + </g> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 171.71875,-107 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z m 0.25,1 0,1 0.5,0 0,-1 -0.5,0 z" + id="path72688" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 175.96875,-107 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z" + id="path72690" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 177.96875,-107 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" + id="path72692" /> + <path + id="path72694" + d="m 166.96875,-107 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + d="m 182.96875,-106 0,1 1,0 0,-1 -1,0 z m -0.21875,3 0,1 -0.75,0 0,1 1,0 0,-1 1,0 0,-1 -1.25,0 z" + id="path72696" /> + </g> + </g> + <g transform="translate(-872,-180)" style="display:inline" id="layer1" @@ -18101,7 +18729,7 @@ id="g12156" /> <g transform="translate(-98,462.06404)" - style="opacity:0.65;display:inline" + style="display:inline;opacity:0.65" id="g12249" /> <g id="g12255" @@ -18109,7 +18737,7 @@ style="display:inline" /> <g id="g12325" - style="opacity:0.65;display:inline" + style="display:inline;opacity:0.65" transform="translate(-98,483.06404)" /> <g style="display:inline" @@ -18181,11 +18809,11 @@ height="0" width="1" id="rect17123" - style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;enable-background:accumulate" /> <g id="g51988" transform="translate(47,-247.0151)" - style="fill:#d45500;fill-opacity:1;display:inline" /> + style="display:inline;fill:#d45500;fill-opacity:1" /> <g transform="translate(10,254)" id="g57337" @@ -18198,7 +18826,7 @@ height="0" width="0" id="rect23719" - style="opacity:0.01000001;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="display:inline;overflow:visible;visibility:visible;opacity:0.01000001;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> <g transform="translate(341,-57.00032)" id="g24088" /> @@ -18227,14 +18855,14 @@ <g id="g24176" transform="translate(-65,-169.00755)" - style="fill:#d45500;fill-opacity:1;display:inline" /> + style="display:inline;fill:#d45500;fill-opacity:1" /> <g id="g28643" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90" transform="translate(-323.1613,214)" - style="fill:none;stroke:#ffffff;stroke-width:1.50000143;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1.50000143;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:7.40000057;stroke-opacity:1;marker:none;enable-background:accumulate" /> <g id="g29500" /> <g @@ -18264,7 +18892,7 @@ id="g33447" /> <g transform="translate(-870.9421,-297.02038)" - style="fill:#ffeeaa;display:inline" + style="display:inline;fill:#ffeeaa" id="g77742" /> <g id="g34782" @@ -18272,10 +18900,10 @@ inkscape:export-xdpi="90" inkscape:export-ydpi="90" transform="matrix(-1,0,0,-1,104.1613,262.99999)" - style="stroke:#ffffff;display:inline"> + style="display:inline;stroke:#ffffff"> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:7.40000057;stroke-opacity:1;marker:none;enable-background:accumulate" id="path34784" sodipodi:nodetypes="cz" d="" /> @@ -18285,10 +18913,10 @@ d="" sodipodi:nodetypes="cz" id="path34806" - style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:7.40000057;stroke-opacity:1;marker:none;enable-background:accumulate" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:7.40000057;stroke-opacity:1;marker:none;enable-background:accumulate" id="path34696" sodipodi:nodetypes="cz" d="" /> @@ -18299,21 +18927,21 @@ <g id="g36511" transform="translate(250,-41.00755)" - style="fill:#d45500;fill-opacity:1;display:inline" /> + style="display:inline;fill:#d45500;fill-opacity:1" /> <rect y="67" x="-25" height="0" width="1" id="rect39658" - style="opacity:0;fill:#fffeaa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" /> + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#fffeaa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;enable-background:new" /> <rect y="66" x="-24" height="1" width="0" id="rect39660" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" /> + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;enable-background:new" /> <g id="g40090" mask="url(#mask38561)" @@ -18328,1254 +18956,1170 @@ id="g40736" /> </g> <g - style="stroke-width:5.41920376;stroke-miterlimit:4;stroke-dasharray:none;display:inline" + style="display:inline;stroke-width:5.41920376;stroke-miterlimit:4;stroke-dasharray:none" id="g38570" transform="matrix(0.5478212,-0.56064,0.5419177,0.5545983,197.19518,557.21673)" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90" /> + <rect + y="180" + x="872" + height="192" + width="192" + id="rect30285" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.39191818;marker:none;enable-background:accumulate" /> <g inkscape:export-ydpi="90" inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\v. 2.5.06\prvicons v.2.5.06.png" - id="g32752"> + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + transform="translate(860,-202)" + id="g21955" + style="display:inline;opacity:0.3;enable-background:new"> <rect - style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.39191818;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect30285" - width="192" - height="192" - x="872" - y="180" /> + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" + id="rect21957" + width="48" + height="48" + x="108" + y="430" + rx="2.4004419" + ry="0" /> <g - style="opacity:0.3;display:inline;enable-background:new" - id="g21955" - transform="translate(856,-203)" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <rect - ry="0" - rx="2.4004419" - y="430" - x="108" - height="48" - width="48" - id="rect21957" - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - <g - id="g21959"> - <path - style="fill:url(#linearGradient21977);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - id="path21961" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21963" - sodipodi:nodetypes="cccc" - inkscape:connector-curvature="0" /> - <path - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21965" - d="m 115,444 12,0 -1,-11 -11,11 z" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - inkscape:connector-curvature="0" /> - <path - clip-path="none" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 117.5,443.75 9,-2.5 0,-6" - style="fill:none;stroke:url(#linearGradient21979);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path21967" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="cccccc" - id="path21969" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21971" - d="m 116,443 11,1 -2,-10 -9,9 z" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - inkscape:connector-curvature="0" /> - <path - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - id="path21973" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path21975" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.5,435 0,38.5 -30.5,0" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - </g> + id="g21959"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path21961" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient21977);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" + id="path21963" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 115,444 12,0 -1,-11 -11,11 z" + id="path21965" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106)" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21967" + style="fill:none;stroke:url(#linearGradient21979);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 117.5,443.75 9,-2.5 0,-6" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21969" + sodipodi:nodetypes="cccccc" /> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 116,443 11,1 -2,-10 -9,9 z" + id="path21971" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106)" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path21973" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.5,435 0,38.5 -30.5,0" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21975" + sodipodi:nodetypes="ccc" /> </g> + </g> + <g + transform="translate(4,0)" + id="g30335"> <g - id="g30335"> - <g - transform="translate(760,-202)" - id="g21367"> - <path - style="fill:url(#linearGradient30321);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - id="path21369" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21371" - sodipodi:nodetypes="cccc" - inkscape:connector-curvature="0" /> - <path - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21373" - d="m 115,444 12,0 -1,-11 -11,11 z" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - inkscape:connector-curvature="0" /> - <path - clip-path="none" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 117.5,443.75 9,-2.5 0,-6" - style="fill:none;stroke:url(#linearGradient30323);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path21375" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="cccccc" - id="path21377" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - clip-path="url(#clipPath13106)" - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccc" - id="path21569" - d="m 116,443 11,1 -2,-10 -9,9 z" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - inkscape:connector-curvature="0" /> - <path - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - id="path21379" - sodipodi:nodetypes="cccccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path21381" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.5,435 0,38.5 -30.5,0" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - </g> + id="g21367" + transform="translate(760,-202)"> <path - sodipodi:nodetypes="ccccccccccccccccccccccc" - id="text13209" - d="m 891.07148,245 -0.0715,9 2.39012,0 C 896,254 896,253 896.5,251 l 0.5,0 0,7 -0.5,0 c -0.5,-2 -0.5,-3 -3.10988,-3 L 891,255 l 0,7 c 0,2.5 1,3.25 3.14146,3.39973 l -0.004,0.60029 L 885,266 l 0.004,-0.60029 C 887,265.25 888,264.5 888.00001,262 L 888,248 c 0,-2.5 -1,-3.25 -3,-3.5 l 0,-0.5 16,0 0,5 -0.5,0 c -0.50001,-1.99999 -1.5,-4 -4.5,-4 l -4.92852,0 z" - style="font-size:33.49144363px;font-style:normal;font-weight:normal;fill:#214478;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path21369" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient30321);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" + id="path21371" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 115,444 12,0 -1,-11 -11,11 z" + id="path21373" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106)" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21375" + style="fill:none;stroke:url(#linearGradient30323);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 117.5,443.75 9,-2.5 0,-6" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21377" + sodipodi:nodetypes="cccccc" /> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 116,443 11,1 -2,-10 -9,9 z" + id="path21569" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106)" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path21379" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.5,435 0,38.5 -30.5,0" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21381" + sodipodi:nodetypes="ccc" /> </g> + <path + inkscape:connector-curvature="0" + style="font-style:normal;font-weight:normal;font-size:33.49144363px;font-family:'Bitstream Vera Sans';display:inline;fill:#214478;fill-opacity:1;stroke:none" + d="m 891.07148,245 -0.0715,9 2.39012,0 C 896,254 896,253 896.5,251 l 0.5,0 0,7 -0.5,0 c -0.5,-2 -0.5,-3 -3.10988,-3 L 891,255 l 0,7 c 0,2.5 1,3.25 3.14146,3.39973 l -0.004,0.60029 L 885,266 l 0.004,-0.60029 C 887,265.25 888,264.5 888.00001,262 L 888,248 c 0,-2.5 -1,-3.25 -3,-3.5 l 0,-0.5 16,0 0,5 -0.5,0 c -0.50001,-1.99999 -1.5,-4 -4.5,-4 l -4.92852,0 z" + id="text13209" + sodipodi:nodetypes="ccccccccccccccccccccccc" /> + </g> + <g + style="display:inline;enable-background:new" + id="g21625" + transform="translate(908,-154)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect21627" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> <g - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - transform="translate(904,-154)" - id="g21625" - style="display:inline;enable-background:new"> - <rect - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect21627" - width="48" - height="48" - x="108" - y="430" - rx="2.4004419" - ry="0" /> + id="g21629"> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient21647);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path21631" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> <g - id="g21629"> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21631" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient21647);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - inkscape:connector-curvature="0" /> + style="display:inline;opacity:0.5;fill:#000000" + id="g16261" + transform="matrix(1.2499985,0,0,1,-87.6203,-147.85351)"> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect35099" + width="17.600004" + height="1" + x="167.69646" + y="598.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect35101" + width="17.600004" + height="1" + x="167.69646" + y="600.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15690" + width="17.600004" + height="1" + x="167.69646" + y="602.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15692" + width="17.600004" + height="1" + x="167.69646" + y="604.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15694" + width="17.600004" + height="1" + x="167.69646" + y="606.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15696" + width="17.600004" + height="1" + x="167.69646" + y="608.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15698" + width="17.600004" + height="1" + x="167.69646" + y="610.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15700" + width="17.600004" + height="1" + x="167.69646" + y="612.85352" + rx="0.12125195" + ry="0.065390877" /> + <rect + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="rect15732" + width="14.400002" + height="1" + x="167.69646" + y="614.85352" + rx="0.09920612" + ry="0.065390877" /> <g - transform="matrix(1.2499985,0,0,1,-87.6203,-147.85351)" - id="g16261" - style="opacity:0.5;fill:#000000;display:inline"> + transform="translate(150.89645,557.85352)" + id="g4849" + style="display:inline;fill:#000000"> <rect ry="0.065390877" rx="0.12125195" - y="598.85352" - x="167.69646" + y="29" + x="16.799992" height="1" width="17.600004" - id="rect35099" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> + id="rect15736" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> <rect ry="0.065390877" rx="0.12125195" - y="600.85352" - x="167.69646" + y="31" + x="16.799992" height="1" width="17.600004" - id="rect35101" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> + id="rect15738" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> <rect ry="0.065390877" rx="0.12125195" - y="602.85352" - x="167.69646" + y="33" + x="16.799992" height="1" width="17.600004" - id="rect15690" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> + id="rect15740" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> <rect ry="0.065390877" rx="0.12125195" - y="604.85352" - x="167.69646" + y="35" + x="16.799992" height="1" width="17.600004" - id="rect15692" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> + id="rect15742" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> <rect ry="0.065390877" - rx="0.12125195" - y="606.85352" - x="167.69646" - height="1" - width="17.600004" - id="rect15694" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <rect - ry="0.065390877" - rx="0.12125195" - y="608.85352" - x="167.69646" - height="1" - width="17.600004" - id="rect15696" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <rect - ry="0.065390877" - rx="0.12125195" - y="610.85352" - x="167.69646" + rx="0.055114571" + y="37" + x="16.799992" height="1" - width="17.600004" - id="rect15698" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <rect - ry="0.065390877" - rx="0.12125195" - y="612.85352" - x="167.69646" - height="1" - width="17.600004" - id="rect15700" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <rect - ry="0.065390877" - rx="0.09920612" - y="614.85352" - x="167.69646" - height="1" - width="14.400002" - id="rect15732" - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" /> - <g - style="fill:#000000;display:inline" - id="g4849" - transform="translate(150.89645,557.85352)"> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15736" - width="17.600004" - height="1" - x="16.799992" - y="29" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15738" - width="17.600004" - height="1" - x="16.799992" - y="31" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15740" - width="17.600004" - height="1" - x="16.799992" - y="33" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15742" - width="17.600004" - height="1" - x="16.799992" - y="35" - rx="0.12125195" - ry="0.065390877" /> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect15744" - width="8.0000095" - height="1" - x="16.799992" - y="37" - rx="0.055114571" - ry="0.065390877" /> - </g> - <rect - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" - id="rect16334" - width="0.83333319" - height="0.99999124" - x="184.49646" - y="617.85352" - rx="0.0057410933" - ry="0.065390304" /> + width="8.0000095" + id="rect15744" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> </g> - <path - sodipodi:nodetypes="cccc" - id="path21633" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path21635" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path21637" - style="fill:none;stroke:url(#linearGradient21649);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21639" - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path21641" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21643" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - inkscape:connector-curvature="0" /> + <rect + ry="0.065390304" + rx="0.0057410933" + y="617.85352" + x="184.49646" + height="0.99999124" + width="0.83333319" + id="rect16334" + style="display:block;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + </g> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21633" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21635" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient21649);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path21637" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path21639" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21641" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path21643" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <g + id="g35119" + transform="translate(2,-160.99999)" + style="display:inline"> <g style="display:inline" - transform="translate(2,-160.99999)" - id="g35119"> + transform="translate(105.39645,589.71201)" + id="g16097"> <g - id="g16097" - transform="translate(105.39645,589.71201)" - style="display:inline"> - <g - transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4" - id="g16099"> - <radialGradient - gradientUnits="userSpaceOnUse" - fy="114.5684" - fx="20.892099" - r="5.256" - cy="114.5684" - cx="20.892099" - id="radialGradient16101"> - <stop - id="stop16103" - style="stop-color:#F0F0F0" - offset="0" /> - <stop - id="stop16105" - style="stop-color:#474747" - offset="1" /> - </radialGradient> - <radialGradient - gradientUnits="userSpaceOnUse" - fy="64.567902" - fx="20.892099" - r="5.257" - cy="64.567902" - cx="20.892099" - id="radialGradient16109"> - <stop - id="stop16111" - style="stop-color:#F0F0F0" - offset="0" /> - <stop - id="stop16113" - style="stop-color:#474747" - offset="1" /> - </radialGradient> - </g> - <path - id="path16107" - d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" - inkscape:connector-curvature="0" /> - <path - id="path16117" - d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z" - style="fill:url(#radialGradient21565);fill-rule:nonzero;stroke:none" - inkscape:connector-curvature="0" /> + id="g16099" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4" + transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)"> + <radialGradient + id="radialGradient16101" + cx="20.892099" + cy="114.5684" + r="5.256" + fx="20.892099" + fy="114.5684" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#F0F0F0" + id="stop16103" /> + <stop + offset="1" + style="stop-color:#474747" + id="stop16105" /> + </radialGradient> + <radialGradient + id="radialGradient16109" + cx="20.892099" + cy="64.567902" + r="5.257" + fx="20.892099" + fy="64.567902" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#F0F0F0" + id="stop16111" /> + <stop + offset="1" + style="stop-color:#474747" + id="stop16113" /> + </radialGradient> </g> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z" + id="path16107" /> + <path + inkscape:connector-curvature="0" + style="fill:url(#radialGradient21565);fill-rule:nonzero;stroke:none" + d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z" + id="path16117" /> + </g> + <g + id="g16131" + transform="translate(105.39645,579.71201)" + style="display:inline"> <g - style="display:inline" - transform="translate(105.39645,579.71201)" - id="g16131"> - <g - id="g16133" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4" - transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)"> - <radialGradient - id="radialGradient16135" - cx="20.892099" - cy="114.5684" - r="5.256" - fx="20.892099" - fy="114.5684" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - style="stop-color:#F0F0F0" - id="stop16137" /> - <stop - offset="1" - style="stop-color:#474747" - id="stop16140" /> - </radialGradient> - <radialGradient - id="radialGradient16142" - cx="20.892099" - cy="64.567902" - r="5.257" - fx="20.892099" - fy="64.567902" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - style="stop-color:#F0F0F0" - id="stop16144" /> - <stop - offset="1" - style="stop-color:#474747" - id="stop16146" /> - </radialGradient> - </g> - <path - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" - d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z" - id="path35139" - inkscape:connector-curvature="0" /> - <path - style="fill:url(#radialGradient21567);fill-rule:nonzero;stroke:none" - d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z" - id="path35141" - inkscape:connector-curvature="0" /> + transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4" + id="g16133"> + <radialGradient + gradientUnits="userSpaceOnUse" + fy="114.5684" + fx="20.892099" + r="5.256" + cy="114.5684" + cx="20.892099" + id="radialGradient16135"> + <stop + id="stop16137" + style="stop-color:#F0F0F0" + offset="0" /> + <stop + id="stop16140" + style="stop-color:#474747" + offset="1" /> + </radialGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + fy="64.567902" + fx="20.892099" + r="5.257" + cy="64.567902" + cx="20.892099" + id="radialGradient16142"> + <stop + id="stop16144" + style="stop-color:#F0F0F0" + offset="0" /> + <stop + id="stop16146" + style="stop-color:#474747" + offset="1" /> + </radialGradient> </g> + <path + inkscape:connector-curvature="0" + id="path35139" + d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z" + style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + inkscape:connector-curvature="0" + id="path35141" + d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z" + style="fill:url(#radialGradient21567);fill-rule:nonzero;stroke:none" /> </g> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21645" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> </g> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21645" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> </g> + </g> + <g + style="display:inline;enable-background:new" + id="g21572" + transform="translate(812,-202)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect21574" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> <g - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" + id="g21576"> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient21594);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path21578" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21580" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21582" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient21596);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path21584" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path21586" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21588" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path21590" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21592" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> + </g> + <g + transform="translate(4,0)" + id="g30382"> + <g + id="g23655" + transform="translate(760,-154)"> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path23657" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + style="display:inline;fill:url(#linearGradient30368);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" + id="path23659" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 115,444 12,0 -1,-11 -11,11 z" + id="path23661" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106)" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path23663" + style="fill:none;stroke:url(#linearGradient30370);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 117.5,443.75 9,-2.5 0,-6" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path23665" + sodipodi:nodetypes="cccccc" /> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" + d="m 116,443 11,1 -2,-10 -9,9 z" + id="path23667" + sodipodi:nodetypes="cccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + clip-path="url(#clipPath13106)" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccccc" + id="path23669" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.5,435 0,38.5 -30.5,0" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path23671" + sodipodi:nodetypes="ccc" /> + </g> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" + d="m 888,295 1,0 0,14 -1,0 0,-14 z" + id="path23675" + sodipodi:nodetypes="ccccc" /> + <path + inkscape:connector-curvature="0" + id="path23677" + d="m 900,294 1.00002,-1 0,14 -1.00002,0 0,-13 z" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" + sodipodi:nodetypes="ccccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" + id="path23679" + d="m 901.00003,292 0,2.25 -13.00002,2 0,-2.25 13.00002,-2 z" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" /> + <g + id="g23681" + transform="matrix(1.1428564,0,0,1.2000001,822.71436,-355.40005)"> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" + id="path23683" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" /> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + style="display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;filter:url(#filter20578);enable-background:accumulate" + id="path23685" + transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)" + inkscape:transform-center-y="0.3813435" + clip-path="url(#clipPath20586)" /> + </g> + <path + inkscape:connector-curvature="0" + style="display:inline;overflow:visible;visibility:visible;opacity:0.38999999;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" + d="m 901.00003,292 -1e-5,1 -13.00002,2 10e-6,-1 13.00002,-2 z" + id="path23694" + sodipodi:nodetypes="ccccc" /> + <g + transform="matrix(1.1428564,0,0,1.2000001,834.71436,-357.40005)" + id="g23717"> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + style="display:inline;overflow:visible;visibility:visible;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" + id="path23724" + transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" /> + <ellipse + ry="2.25" + rx="4.5" + cy="554" + cx="53" + clip-path="url(#clipPath20586)" + inkscape:transform-center-y="0.3813435" + transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)" + id="path23726" + style="display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;filter:url(#filter20578);enable-background:accumulate" /> + </g> + </g> + <g + id="g23922" + transform="translate(-12,-220)" + style="display:inline;enable-background:new"> + <g + style="display:inline" + id="g23924" + transform="translate(824,66)" inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - transform="translate(808,-203)" - id="g21572" - style="display:inline;enable-background:new"> + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> <rect - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect21574" - width="48" - height="48" - x="108" - y="430" + ry="0" rx="2.4004419" - ry="0" /> + y="430" + x="108" + height="48" + width="48" + id="rect23926" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> <g - id="g21576"> + id="g23928"> <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21578" + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient23978);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient21594);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="cccc" - id="path21580" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + id="path23930" + sodipodi:nodetypes="cccccc" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> + inkscape:export-ydpi="90" /> <path - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path21582" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" + inkscape:connector-curvature="0" inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path21584" - style="fill:none;stroke:url(#linearGradient21596);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" - inkscape:connector-curvature="0" /> + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path23932" + sodipodi:nodetypes="cccc" /> <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106)" inkscape:export-ydpi="90" inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21586" - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path21588" sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" - inkscape:connector-curvature="0" /> + id="path23934" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> <path + inkscape:connector-curvature="0" + clip-path="none" inkscape:export-ydpi="90" inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient23980);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path23936" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" sodipodi:nodetypes="cccccc" - id="path21590" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - inkscape:connector-curvature="0" /> + id="path23938" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106)" inkscape:export-ydpi="90" inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21592" + sodipodi:nodetypes="cccc" + id="path23940" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path23942" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> + id="path23944" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> </g> </g> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccc" + id="path23946" + d="m 952,530 0,10 1,0 1,0 11,0 1,0 1,0 0,-10 -15,0 z m 1,2 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <rect + transform="scale(1,-1)" + style="fill:url(#linearGradient23982);fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect23948" + width="13" + height="5.5" + x="953" + y="-524" /> + <path + inkscape:connector-curvature="0" + id="path23952" + transform="translate(76,0)" + d="m 876,514 0,17 15,0 0,-17 -1,0 0,1 -1,0 0,-1 -11,0 0,1 -1,0 0,-1 -1,0 z m 1,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccc" + style="fill:url(#linearGradient23986);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 952,507 3,0 0,3 9,0 0,-3 3,0 0,7 -15,0 0,-7 z m 1,0 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z m 12,-4 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z" + id="path23954" /> + <rect + transform="matrix(0,1,1,0,0,0)" + ry="0" + y="955" + x="507" + height="9" + width="3" + id="rect23956" + style="fill:url(#linearGradient23988);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <rect + style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect23958" + width="9" + height="9" + x="512" + y="955" + ry="0" + transform="matrix(0,1,1,0,0,0)" /> + <rect + transform="matrix(0,1,1,0,0,0)" + ry="0" + y="955" + x="523" + height="9" + width="9" + id="rect23960" + style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <circle + r="8" + cy="118" + cx="132" + transform="matrix(0,-0.5624971,0.5624971,0,893.12531,590.74965)" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="path23962" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <circle + r="8" + cy="118" + cx="132" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" + id="path23964" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + transform="matrix(0,-0.5624964,0.5624964,0,893.12545,601.74956)" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccc" + id="path23966" + d="m 961.00001,519.00005 -3,0 0,-0.99992 0.99994,0 6e-5,-2.00008 -1,0 0,-1 1,0 0,-1 1.00006,0 0,4.00008 0.99994,0 0,0.99992 z" /> + <path + inkscape:connector-curvature="0" + d="m 958,525 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" + id="path23968" /> + <rect + style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect23970" + width="6" + height="9" + x="534" + y="955" + ry="0" + transform="matrix(0,1,1,0,0,0)" /> + <g + clip-path="url(#clipPath23877)" + id="g23972"> + <circle + r="8" + cy="118" + cx="132" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" + id="path23974" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + transform="matrix(0,-0.5624964,0.5624964,0,893.12545,612.74956)" /> + <path + inkscape:connector-curvature="0" + d="m 958,536 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,1 -2,0 0,1 2,0 0,-1 z" + id="path23976" /> + </g> + </g> + <g + transform="translate(212,88)" + id="g45475" + style="display:inline;enable-background:new"> <g - id="g30382"> + style="display:inline" + id="g22242" + transform="translate(696,-194)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect22244" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> <g - transform="translate(760,-154)" - id="g23655"> + id="g22246"> <path - style="fill:url(#linearGradient30368);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient22274);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - id="path23657" + id="path22249" sodipodi:nodetypes="cccccc" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> + inkscape:export-ydpi="90" /> <path + inkscape:connector-curvature="0" inkscape:export-ydpi="90" inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path23659" - sodipodi:nodetypes="cccc" - inkscape:connector-curvature="0" /> + id="path22251" + sodipodi:nodetypes="cccc" /> <path + inkscape:connector-curvature="0" clip-path="url(#clipPath13106)" inkscape:export-ydpi="90" inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" sodipodi:nodetypes="cccc" - id="path23661" + id="path22253" d="m 115,444 12,0 -1,-11 -11,11 z" - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - inkscape:connector-curvature="0" /> + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> <path + inkscape:connector-curvature="0" clip-path="none" inkscape:export-ydpi="90" inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" d="m 117.5,443.75 9,-2.5 0,-6" - style="fill:none;stroke:url(#linearGradient30370);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path23663" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> + style="fill:none;stroke:url(#linearGradient22276);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path22264" + sodipodi:nodetypes="ccc" /> <path + inkscape:connector-curvature="0" sodipodi:nodetypes="cccccc" - id="path23665" + id="path22266" style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> + inkscape:export-ydpi="90" /> <path + inkscape:connector-curvature="0" clip-path="url(#clipPath13106)" inkscape:export-ydpi="90" inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" sodipodi:nodetypes="cccc" - id="path23667" + id="path22268" d="m 116,443 11,1 -2,-10 -9,9 z" - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - inkscape:connector-curvature="0" /> + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" /> <path + inkscape:connector-curvature="0" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - id="path23669" + id="path22270" sodipodi:nodetypes="cccccc" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> + inkscape:export-ydpi="90" /> <path + inkscape:connector-curvature="0" sodipodi:nodetypes="ccc" - id="path23671" + id="path22272" style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" d="m 147.5,435 0,38.5 -30.5,0" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - </g> - <path - sodipodi:nodetypes="ccccc" - id="path23675" - d="m 888,295 1,0 0,14 -1,0 0,-14 z" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccccc" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 900,294 1.00002,-1 0,14 -1.00002,0 0,-13 z" - id="path23677" - inkscape:connector-curvature="0" /> - <path - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 901.00003,292 0,2.25 -13.00002,2 0,-2.25 13.00002,-2 z" - id="path23679" - sodipodi:nodetypes="ccccc" - inkscape:connector-curvature="0" /> - <g - transform="matrix(1.1428564,0,0,1.2000001,822.71436,-355.40005)" - id="g23681"> - <path - sodipodi:type="arc" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path23683" - sodipodi:cx="53" - sodipodi:cy="554" - sodipodi:rx="4.5" - sodipodi:ry="2.25" - d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z" - transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" /> - <path - clip-path="url(#clipPath20586)" - inkscape:transform-center-y="0.3813435" - transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)" - d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z" - sodipodi:ry="2.25" - sodipodi:rx="4.5" - sodipodi:cy="554" - sodipodi:cx="53" - id="path23685" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate" - sodipodi:type="arc" /> - </g> - <path - sodipodi:nodetypes="ccccc" - id="path23694" - d="m 901.00003,292 -1e-5,1 -13.00002,2 10e-6,-1 13.00002,-2 z" - style="opacity:0.38999999;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - inkscape:connector-curvature="0" /> - <g - id="g23717" - transform="matrix(1.1428564,0,0,1.2000001,834.71436,-357.40005)"> - <path - transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" - d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z" - sodipodi:ry="2.25" - sodipodi:rx="4.5" - sodipodi:cy="554" - sodipodi:cx="53" - id="path23724" - style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" /> - <path - sodipodi:type="arc" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate" - id="path23726" - sodipodi:cx="53" - sodipodi:cy="554" - sodipodi:rx="4.5" - sodipodi:ry="2.25" - d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z" - transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)" - inkscape:transform-center-y="0.3813435" - clip-path="url(#clipPath20586)" /> - </g> - </g> - <g - style="display:inline;enable-background:new" - transform="translate(-16,-220)" - id="g23922"> - <g - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - transform="translate(824,66)" - id="g23924" - style="display:inline"> - <rect - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect23926" - width="48" - height="48" - x="108" - y="430" - rx="2.4004419" - ry="0" /> - <g - id="g23928"> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path23930" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient23978);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="cccc" - id="path23932" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path23934" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path23936" - style="fill:none;stroke:url(#linearGradient23980);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path23938" - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path23940" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path23942" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path23944" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> - </g> - </g> - <path - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" - d="m 952,530 0,10 1,0 1,0 11,0 1,0 1,0 0,-10 -15,0 z m 1,2 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z" - id="path23946" - sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccc" - inkscape:connector-curvature="0" /> - <rect - y="-524" - x="953" - height="5.5" - width="13" - id="rect23948" - style="fill:url(#linearGradient23982);fill-opacity:1;fill-rule:nonzero;stroke:none" - transform="scale(1,-1)" /> - <path - style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" - d="m 876,514 0,17 15,0 0,-17 -1,0 0,1 -1,0 0,-1 -11,0 0,1 -1,0 0,-1 -1,0 z m 1,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z" - transform="translate(76,0)" - id="path23952" - inkscape:connector-curvature="0" /> - <path - id="path23954" - d="m 952,507 3,0 0,3 9,0 0,-3 3,0 0,7 -15,0 0,-7 z m 1,0 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z m 12,-4 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z" - style="fill:url(#linearGradient23986);fill-opacity:1;fill-rule:nonzero;stroke:none" - sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccc" - inkscape:connector-curvature="0" /> - <rect - style="fill:url(#linearGradient23988);fill-opacity:1;fill-rule:nonzero;stroke:none" - id="rect23956" - width="3" - height="9" - x="507" - y="955" - ry="0" - transform="matrix(0,1,1,0,0,0)" /> - <rect - transform="matrix(0,1,1,0,0,0)" - ry="0" - y="955" - x="512" - height="9" - width="9" - id="rect23958" - style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" /> - <rect - style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="rect23960" - width="9" - height="9" - x="523" - y="955" - ry="0" - transform="matrix(0,1,1,0,0,0)" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" - d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" - sodipodi:ry="8" - sodipodi:rx="8" - sodipodi:cy="118" - sodipodi:cx="132" - id="path23962" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - sodipodi:type="arc" - transform="matrix(0,-0.5624971,0.5624971,0,893.12531,590.74965)" /> - <path - transform="matrix(0,-0.5624964,0.5624964,0,893.12545,601.74956)" - sodipodi:type="arc" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path23964" - sodipodi:cx="132" - sodipodi:cy="118" - sodipodi:rx="8" - sodipodi:ry="8" - d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" /> - <path - d="m 961.00001,519.00005 -3,0 0,-0.99992 0.99994,0 6e-5,-2.00008 -1,0 0,-1 1,0 0,-1 1.00006,0 0,4.00008 0.99994,0 0,0.99992 z" - id="path23966" - sodipodi:nodetypes="ccccccccccccc" - inkscape:connector-curvature="0" /> - <path - id="path23968" - d="m 958,525 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z" - inkscape:connector-curvature="0" /> - <rect - transform="matrix(0,1,1,0,0,0)" - ry="0" - y="955" - x="534" - height="9" - width="6" - id="rect23970" - style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" /> - <g - id="g23972" - clip-path="url(#clipPath23877)"> - <path - transform="matrix(0,-0.5624964,0.5624964,0,893.12545,612.74956)" - sodipodi:type="arc" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path23974" - sodipodi:cx="132" - sodipodi:cy="118" - sodipodi:rx="8" - sodipodi:ry="8" - d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png" - inkscape:export-xdpi="90" inkscape:export-ydpi="90" /> - <path - id="path23976" - d="m 958,536 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,1 -2,0 0,1 2,0 0,-1 z" - inkscape:connector-curvature="0" /> </g> </g> <g - style="display:inline;enable-background:new" - id="g45475" - transform="translate(208,88)"> - <g - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - transform="translate(696,-194)" - id="g22242" - style="display:inline"> - <rect - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect22244" - width="48" - height="48" - x="108" - y="430" - rx="2.4004419" - ry="0" /> - <g - id="g22246"> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path22249" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient22274);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="cccc" - id="path22251" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path22253" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path22264" - style="fill:none;stroke:url(#linearGradient22276);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path22266" - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path22268" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106)" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path22270" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path22272" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> - </g> - </g> - <g - transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)" - inkscape:label="Layer 1" - id="g21517"> - <path - sodipodi:type="arc" - style="opacity:0.54857142;fill:url(#radialGradient21442);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path35486" - sodipodi:cx="28.019106" - sodipodi:cy="38.98439" - sodipodi:rx="15.467961" - sodipodi:ry="5.3033009" - d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z" - transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" /> - <path - style="fill:#f57900;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" - id="path2482" - d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z" - sodipodi:nodetypes="csssssssssscccsscccscccssccc" - inkscape:connector-curvature="0" /> - <path - sodipodi:type="arc" - style="fill:url(#linearGradient21444);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path39153" - sodipodi:cx="31.1875" - sodipodi:cy="25.75" - sodipodi:rx="11.5625" - sodipodi:ry="10.125" - d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z" - transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" /> - <path - sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" - id="path21414" - d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 z" - style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" - inkscape:connector-curvature="0" /> - <path - style="fill:#3465a4;fill-rule:evenodd;stroke:none" - id="path2478" - d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.51999996;fill:url(#radialGradient21448);fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 z" - id="path39166" - sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc" - inkscape:connector-curvature="0" /> - </g> - </g> - <g - transform="translate(162,248)" - id="g24847" - style="opacity:0.5"> - <path - d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" - id="path24849" - style="fill:url(#linearGradient24867);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:nodetypes="ccccccssssccc" - inkscape:connector-curvature="0" /> + id="g21517" + inkscape:label="Layer 1" + transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)"> + <ellipse + ry="5.3033009" + rx="15.467961" + cy="38.98439" + cx="28.019106" + transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" + id="path35486" + style="display:inline;overflow:visible;visibility:visible;opacity:0.54857142;fill:url(#radialGradient21442);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> <path - sodipodi:nodetypes="cccccccccccccccccccccccccccccc" - d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" - style="opacity:0.07999998;fill:url(#linearGradient24869);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - id="path24851" - inkscape:connector-curvature="0" /> - <path - style="fill:url(#linearGradient24871);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" - id="path24853" - sodipodi:nodetypes="csccsczc" - inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" - inkscape:export-xdpi="74.800003" - inkscape:export-ydpi="74.800003" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccssccc" - style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path24855" - d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z" - inkscape:connector-curvature="0" /> - <path - id="path24857" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - d="m 840.5,89 0,4.5" - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - id="path24859" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="csssssssssscccsscccscccssccc" + d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z" + id="path2482" + style="fill:#f57900;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" /> + <ellipse + ry="10.125" + rx="11.5625" + cy="25.75" + cx="31.1875" + transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" + id="path39153" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient21444);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> <path - id="path24861" - style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" - d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0" - sodipodi:nodetypes="cccccccsc" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" + d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 Z" + id="path21414" + sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" /> <path - sodipodi:nodetypes="ccccsscccssssccc" - style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path24863" - d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z" + id="path2478" + style="fill:#3465a4;fill-rule:evenodd;stroke:none" /> <path - sodipodi:nodetypes="csscc" - id="path24865" - d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3" - style="fill:none;stroke:url(#linearGradient24873);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc" + id="path39166" + d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 Z" + style="opacity:0.51999996;fill:url(#radialGradient21448);fill-opacity:1;fill-rule:evenodd;stroke:none" /> </g> + </g> + <g + id="g6090"> <g id="g24784" - transform="translate(114,248)" + transform="translate(116,247.5)" style="opacity:0.5"> <path sodipodi:nodetypes="ccccccssssccc" - style="fill:url(#linearGradient24809);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24809);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" id="path24789" d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" inkscape:connector-curvature="0" /> <path id="path24791" - style="opacity:0.07999998;fill:url(#linearGradient24811);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" + style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:url(#linearGradient24811);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" sodipodi:nodetypes="cccccccccccccccccccccccccccccc" inkscape:connector-curvature="0" /> @@ -19586,10 +20130,10 @@ sodipodi:nodetypes="csccsczc" id="path24793" d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" - style="fill:url(#linearGradient24813);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24813);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> <path - d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z" + d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 Z" id="path24796" style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" sodipodi:nodetypes="ccssccc" @@ -19597,25 +20141,25 @@ <path sodipodi:nodetypes="cc" d="m 840.5,89 0,4.5" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" id="path24799" inkscape:connector-curvature="0" /> <path id="path24801" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4" sodipodi:nodetypes="ccc" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="cccccccsc" d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0" - style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + style="display:inline;opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path24803" inkscape:connector-curvature="0" /> <path d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" id="path24805" - style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" sodipodi:nodetypes="ccccsscccssssccc" inkscape:connector-curvature="0" /> <path @@ -19626,33 +20170,16 @@ inkscape:connector-curvature="0" /> </g> <g - id="g44424" - style="opacity:0.4;stroke:#3d361a;filter:url(#filter44473)" - transform="translate(0,-2)"> - <path - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" - d="m 950.25,362 -5.25,0 -1,-1 0,-10" - id="path44406" - sodipodi:nodetypes="cccc" - inkscape:connector-curvature="0" /> - <path - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" - d="M 948.25,354.25 944,350.00563 939.75,354.25" - id="path44408" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> - </g> - <g - style="display:inline;enable-background:new" + style="display:inline;filter:url(#filter6078);enable-background:new" id="g44334" - transform="translate(617,273)"> + transform="translate(619,272.5)"> <rect y="73" x="320" height="16" width="16" id="rect44336" - style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;enable-background:accumulate" /> <g id="g44338" transform="translate(0,-21)"> @@ -19662,13 +20189,13 @@ id="g44342" transform="translate(0,21)"> <path - style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 333.25,87 -5.25,0 -1,-1 0,-10" id="path44344" sodipodi:nodetypes="cccc" inkscape:connector-curvature="0" /> <path - style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 331.25,79.25 327,75.005631 322.75,79.25" id="path44346" sodipodi:nodetypes="ccc" @@ -19681,13 +20208,13 @@ sodipodi:nodetypes="cccc" id="path44350" d="m 333.25,87 -5.25,0 -1,-1 0,-10" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="ccc" id="path44352" d="M 331.25,79.25 327,75.005631 322.75,79.25" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" inkscape:connector-curvature="0" /> </g> </g> @@ -19695,30 +20222,95 @@ sodipodi:nodetypes="cccccc" id="path44354" d="m 328.5,107.5 5,0 m -7,-9 0,8.5 m -4.25,-7 4.5,-4.5" - style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> </g> </g> + </g> + <g + transform="translate(68,247.5)" + id="g24818" + style="display:inline;enable-background:new"> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccssssccc" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24839);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" + id="path24821" + d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" /> + <path + inkscape:connector-curvature="0" + id="path24823" + style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:url(#linearGradient24841);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" + sodipodi:nodetypes="cccccccccccccccccccccccccccccc" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="74.800003" + inkscape:export-xdpi="74.800003" + inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" + sodipodi:nodetypes="csccsczc" + id="path24825" + d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-16 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,17 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24843);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 Z" + id="path24827" + style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + sodipodi:nodetypes="ccssccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + d="m 840.5,89 0,7.5" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="path24829" /> + <path + inkscape:connector-curvature="0" + id="path24831" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + d="m 848.5,98.75 0,14.75 c 0,1.25 0.25,3 -1.25,4" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccsc" + d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-16 34,0 m -29,-10 c 0,0.5 0.5286,1 1,1 l 20,0" + style="display:inline;opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path24833" /> + <path + inkscape:connector-curvature="0" + d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-16 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-8 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" + id="path24835" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + sodipodi:nodetypes="ccccsscccssssccc" /> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:url(#linearGradient24845);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 841.5,96.500004 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,15.999996 c 0,2.25 -1.25,3 -2.5,3" + id="path24837" + sodipodi:nodetypes="csscc" /> + </g> + <g + id="g6158"> <g - style="display:inline;enable-background:new" - id="g24818" - transform="translate(66,248)"> + transform="translate(164,247.5)" + id="g24847" + style="opacity:0.5"> <path d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" - id="path24821" - style="fill:url(#linearGradient24839);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="path24849" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24867);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" sodipodi:nodetypes="ccccccssssccc" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="cccccccccccccccccccccccccccccc" d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0" - style="opacity:0.07999998;fill:url(#linearGradient24841);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - id="path24823" + style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:url(#linearGradient24869);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="path24851" inkscape:connector-curvature="0" /> <path - style="fill:url(#linearGradient24843);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-16 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,17 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" - id="path24825" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient24871);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" + d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z" + id="path24853" sodipodi:nodetypes="csccsczc" inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png" inkscape:export-xdpi="74.800003" @@ -19727,78 +20319,46 @@ <path sodipodi:nodetypes="ccssccc" style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path24827" - d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z" + id="path24855" + d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 Z" inkscape:connector-curvature="0" /> <path - id="path24829" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - d="m 840.5,89 0,7.5" + id="path24857" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + d="m 840.5,89 0,4.5" sodipodi:nodetypes="cc" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="ccc" - d="m 848.5,98.75 0,14.75 c 0,1.25 0.25,3 -1.25,4" - style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" - id="path24831" + d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="path24859" inkscape:connector-curvature="0" /> <path - id="path24833" - style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" - d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-16 34,0 m -29,-10 c 0,0.5 0.5286,1 1,1 l 20,0" + id="path24861" + style="display:inline;opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0" sodipodi:nodetypes="cccccccsc" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="ccccsscccssssccc" - style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path24835" - d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-16 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-8 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + id="path24863" + d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="csscc" - id="path24837" - d="m 841.5,96.500004 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,15.999996 c 0,2.25 -1.25,3 -2.5,3" - style="fill:none;stroke:url(#linearGradient24845);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - inkscape:connector-curvature="0" /> - </g> - <g - id="g44455" - style="opacity:0.4;filter:url(#filter44477)"> - <path - sodipodi:nodetypes="cs" - id="path44446" - d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - transform="translate(645,252.05)" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path44449" - d="m 343,108.25 0,-4.25 4.25,0" - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - transform="translate(645,252.05)" - inkscape:connector-curvature="0" /> - <path - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - id="path44451" - sodipodi:nodetypes="cs" - transform="matrix(-1,0,0,-1,1343,456.05)" - inkscape:connector-curvature="0" /> - <path - style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 343,108.25 0,-4.25 4.25,0" - id="path44453" - sodipodi:nodetypes="ccc" - transform="matrix(-1,0,0,-1,1343,456.05)" + id="path24865" + d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3" + style="fill:none;stroke:url(#linearGradient24873);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" inkscape:connector-curvature="0" /> </g> <g - style="display:inline;enable-background:new" + style="display:inline;filter:url(#filter6146);enable-background:new" id="g44356" - transform="translate(645,273.05)"> + transform="translate(647,272.55)"> <rect - style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;enable-background:accumulate" id="rect44358" width="16" height="16" @@ -19812,13 +20372,13 @@ <g id="g44364"> <path - style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" id="path44366" sodipodi:nodetypes="cs" inkscape:connector-curvature="0" /> <path - style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="m 343,108.25 0,-4.25 4.25,0" id="path44368" sodipodi:nodetypes="ccc" @@ -19830,17 +20390,17 @@ sodipodi:nodetypes="ccc" id="path44372" d="m 343,108.25 0,-4.25 4.25,0" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="cs" id="path44374" d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> </g> <path - style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;enable-background:accumulate" d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z" id="path44376" inkscape:connector-curvature="0" /> @@ -19854,25 +20414,25 @@ sodipodi:nodetypes="cs" id="path44382" d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" - style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="ccc" id="path44384" d="m 343,108.25 0,-4.25 4.25,0" - style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> </g> <g id="g44386"> <path - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="m 343,108.25 0,-4.25 4.25,0" id="path44388" sodipodi:nodetypes="ccc" inkscape:connector-curvature="0" /> <path - style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5" id="path44390" sodipodi:nodetypes="cs" @@ -19881,409 +20441,394 @@ <path id="path44392" d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z" - style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="ccc" id="path44394" d="m 344.90625,106.59375 c 2.52573,2.51828 6.66805,2.52691 9.1875,0 l 0.5,-0.5" - style="fill:none;stroke:url(#linearGradient44402);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient44402);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> </g> <path sodipodi:nodetypes="ccc" id="path44396" d="m 350.5,99.5 4,0 0,-4" - style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="cccc" id="path44398" d="m 347.5,103.5 -4.5,0 c -0.25,0 -0.5,0.25 -0.5,0.5 l 0,4.5" - style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="ccc" id="path44400" d="m 345.59375,105.90625 c 2.07803,2.0719 5.36384,2.10325 7.53125,0.1875 L 354,105.25" - style="fill:none;stroke:url(#linearGradient44404);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient44404);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /> </g> </g> + </g> + <g + transform="translate(4,0)" + id="g34977" + style="display:inline;enable-background:new"> <g - style="display:inline;enable-background:new" - id="g34977"> - <g - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - transform="translate(856,-154)" - id="g21853-3" - style="display:inline"> - <rect - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect21855-8" - width="48" - height="48" - x="108" - y="430" - rx="2.4004419" - ry="0" /> - <g - id="g21857-6"> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21859-9" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient21875-7-1-0-1);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="cccc" - id="path21861-8" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-6-7-0-8)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path21863-6" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106-9-2-9-9)" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path21865-6" - style="fill:none;stroke:url(#linearGradient21877-3-2-7-2);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21867-2" - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011-6-7-0-8)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path21869-3" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106-9-2-9-9)" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path21871-8" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path21873-2" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> - </g> - </g> + style="display:inline" + id="g21853-3" + transform="translate(856,-154)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect21855-8" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> <g - transform="translate(63,-47)" - id="g34938"> + id="g21857-6"> <path - sodipodi:nodetypes="cssssccsscsccsc" inkscape:connector-curvature="0" - d="m 919.5,356.5067 0,-3 c 0,-1.73575 1.26424,-3 3,-3 l 5,0 c 1.73576,0 3,-1.26425 3,-3 l 0,-3.0064 2.5,0.006 c 2,0 3.5,2.5 3.5,6 0,3.5 -1.25,6 -3.5,6 -4.98134,0 -12.77318,0 -2.5,0 l 0,2.75 c 0,2.5 -2,3.24997 -5.5,3.24998 l 0,2e-5 c -3.5,0.0104 -5.5,-0.75 -5.5,-3.25 l 0,-2.7628" - style="color:#000000;fill:url(#linearGradient34959-9-2-1);fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:0.17893334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path61236" /> + style="display:inline;fill:url(#linearGradient21875-7-1-0-1);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path21859-9" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> <path - id="path61233" - style="color:#000000;fill:url(#linearGradient34961-3-6-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.17893334;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3.0064 -2.5,-0.006 c -2,0 -3.5,-2.5 -3.5,-6 0,-3.5 1.25,-6 3.5,-6 4.98134,0 12.77318,0 2.5,0 l 0,-2.75 c 0,-2.5 2,-3.24997 5.5,-3.24998 l 0,-2e-5 c 3.5,-0.0104 5.5,0.75 5.5,3.25 l 0,2.7628" inkscape:connector-curvature="0" - sodipodi:nodetypes="cssssccsscsccsc" /> + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path21861-8" + sodipodi:nodetypes="cccc" /> <path - style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-miterlimit:4;stroke-opacity:0.8627451;stroke-dasharray:none" - d="m 925,338.50002 c -3.5,10e-6 -5.5,0.74998 -5.5,3.24998 l 0,2.75 5.5,0 -8,0 c -2.25,0 -3.5,2.5 -3.5,6 0,3.5 1.5,6 3.5,6 l 2.5,0.0128 0,2.9872 c 0,2 2,3.01281 5.5,3.0128 3.5,-1e-5 5.5,-1.0128 5.5,-3.0128 l 0,-3 -5.5,0 8,0 c 2,0 3.5,-2.5 3.5,-6 0,-3.5 -1.5,-6 -3.5,-6 l -2.5,0.0128 0,-2.7628 c 0,-2.5 -2,-3.26045 -5.5,-3.25 z" - id="path61167" - sodipodi:nodetypes="cccccscccsccccsccccc" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-9-2-9-9)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21863-6" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-6-7-0-8)" /> <path - style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.78431373;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3" - id="path61169" + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient21877-3-2-7-2);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path21865-6" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" /> + id="path21867-2" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-9-2-9-9)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path21869-3" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-6-7-0-8)" /> <path - sodipodi:type="arc" - style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path61220" - sodipodi:cx="922" - sodipodi:cy="342" - sodipodi:rx="1" - sodipodi:ry="1" - d="m 923,342 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z" /> + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path21871-8" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> <path - sodipodi:type="arc" - style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path61222" - sodipodi:cx="928" - sodipodi:cy="359" - sodipodi:rx="1" - sodipodi:ry="1" - d="m 929,359 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z" /> - <g - id="g61345" - style="opacity:0.4"> - <path - sodipodi:nodetypes="cszsc" - inkscape:connector-curvature="0" - id="path61333" - d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75" - style="fill:none;stroke:url(#linearGradient34963-5-9-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cccszsc" - inkscape:connector-curvature="0" - id="path61335" - d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5 0,3 1.28917,5 2.5,5 l 1.5,0" - style="fill:none;stroke:url(#linearGradient34965-1-5-2);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> - <path - inkscape:connector-curvature="0" - id="path61337" - d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5" - style="fill:none;stroke:none" /> - <path - sodipodi:nodetypes="cssssc" - inkscape:connector-curvature="0" - id="path61339" - d="m 918.5,355.25 0,-1.75 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5" - style="fill:none;stroke:none" /> - <path - d="m 923,342 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z" - sodipodi:ry="1" - sodipodi:rx="1" - sodipodi:cy="342" - sodipodi:cx="922" - id="path61355" - style="color:#000000;fill:none;stroke:url(#linearGradient34967-4-1-8);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" - transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" /> - </g> - <g - id="g34104" - transform="matrix(-1,0,0,-1,1850,701)" - style="opacity:0.8;stroke:#ff0000"> - <path - style="fill:none;stroke:none" - d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75" - id="path34106" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cszsc" /> - <path - style="fill:none;stroke:url(#linearGradient34969-4-4-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 914.5,350.5 c 0,3 1.28917,5 2.5,5 l 1.5,0" - id="path34108" - inkscape:connector-curvature="0" - sodipodi:nodetypes="csc" /> - <path - style="fill:none;stroke:url(#linearGradient34971-5-0-9);stroke-linecap:round;stroke-linejoin:round" - d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5" - id="path34110" - inkscape:connector-curvature="0" /> - <path - style="fill:none;stroke:url(#radialGradient34973-2-5-7);stroke-linecap:round;stroke-linejoin:round" - d="m 918.5,355.5 0,-2 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5" - id="path34113" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cssssc" /> - <path - transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" - sodipodi:type="arc" - style="color:#000000;fill:none;stroke:url(#linearGradient34975-9-4-9);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path34115" - sodipodi:cx="922" - sodipodi:cy="342" - sodipodi:rx="1" - sodipodi:ry="1" - d="m 923,342 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z" /> - <path - sodipodi:nodetypes="cccsc" - inkscape:connector-curvature="0" - id="path34901" - d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5" - style="fill:none;stroke:none" /> - </g> + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path21873-2" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> </g> </g> <g - style="display:inline;enable-background:new" - id="g45475-4" - transform="translate(208,-9)"> + id="g34938" + transform="translate(63,-47)"> + <path + id="path61236" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient34959-9-2-1);fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:0.17893334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + d="m 919.5,356.5067 0,-3 c 0,-1.73575 1.26424,-3 3,-3 l 5,0 c 1.73576,0 3,-1.26425 3,-3 l 0,-3.0064 2.5,0.006 c 2,0 3.5,2.5 3.5,6 0,3.5 -1.25,6 -3.5,6 -4.98134,0 -12.77318,0 -2.5,0 l 0,2.75 c 0,2.5 -2,3.24997 -5.5,3.24998 l 0,2e-5 c -3.5,0.0104 -5.5,-0.75 -5.5,-3.25 l 0,-2.7628" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cssssccsscsccsc" /> + <path + sodipodi:nodetypes="cssssccsscsccsc" + inkscape:connector-curvature="0" + d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3.0064 -2.5,-0.006 c -2,0 -3.5,-2.5 -3.5,-6 0,-3.5 1.25,-6 3.5,-6 4.98134,0 12.77318,0 2.5,0 l 0,-2.75 c 0,-2.5 2,-3.24997 5.5,-3.24998 l 0,-2e-5 c 3.5,-0.0104 5.5,0.75 5.5,3.25 l 0,2.7628" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient34961-3-6-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.17893334;marker:none;enable-background:accumulate" + id="path61233" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccscccsccccsccccc" + id="path61167" + d="m 925,338.50002 c -3.5,10e-6 -5.5,0.74998 -5.5,3.24998 l 0,2.75 5.5,0 -8,0 c -2.25,0 -3.5,2.5 -3.5,6 0,3.5 1.5,6 3.5,6 l 2.5,0.0128 0,2.9872 c 0,2 2,3.01281 5.5,3.0128 3.5,-1e-5 5.5,-1.0128 5.5,-3.0128 l 0,-3 -5.5,0 8,0 c 2,0 3.5,-2.5 3.5,-6 0,-3.5 -1.5,-6 -3.5,-6 l -2.5,0.0128 0,-2.7628 c 0,-2.5 -2,-3.26045 -5.5,-3.25 z" + style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.8627451" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path61169" + d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.78431373;marker:none;enable-background:accumulate" /> + <circle + r="1" + cy="342" + cx="922" + id="path61220" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;enable-background:accumulate" /> + <circle + r="1" + cy="359" + cx="928" + id="path61222" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;enable-background:accumulate" /> <g - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" - transform="translate(696,-194)" - id="g22242-6" - style="display:inline"> - <rect - style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="rect22244-9" - width="48" - height="48" - x="108" - y="430" - rx="2.4004419" - ry="0" /> - <g - id="g22246-2"> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path22249-8" - d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" - style="fill:url(#linearGradient22274-8);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="cccc" - id="path22251-9" - style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-5)" - d="m 115,444 12,0 -1,-11 -11,11 z" - id="path22253-5" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106-5)" - inkscape:connector-curvature="0" /> - <path - sodipodi:nodetypes="ccc" - id="path22264-3" - style="fill:none;stroke:url(#linearGradient22276-5);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 117.5,443.75 9,-2.5 0,-6" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" - style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path22266-6" - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" /> - <path - style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011-5)" - d="m 116,443 11,1 -2,-10 -9,9 z" - id="path22268-0" - sodipodi:nodetypes="cccc" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - clip-path="url(#clipPath13106-5)" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - sodipodi:nodetypes="cccccc" - id="path22270-1" - d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" - style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" - inkscape:connector-curvature="0" /> - <path - inkscape:export-ydpi="90" - inkscape:export-xdpi="90" - inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" - d="m 147.5,435 0,38.5 -30.5,0" - style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - id="path22272-3" - sodipodi:nodetypes="ccc" - inkscape:connector-curvature="0" /> - </g> + style="opacity:0.4" + id="g61345"> + <path + style="fill:none;stroke:url(#linearGradient34963-5-9-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" + d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75" + id="path61333" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cszsc" /> + <path + style="fill:none;stroke:url(#linearGradient34965-1-5-2);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5 0,3 1.28917,5 2.5,5 l 1.5,0" + id="path61335" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccszsc" /> + <path + style="fill:none;stroke:none" + d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5" + id="path61337" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:none" + d="m 918.5,355.25 0,-1.75 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5" + id="path61339" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cssssc" /> + <circle + r="1" + cy="342" + cx="922" + transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient34967-4-1-8);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;enable-background:accumulate" + id="path61355" /> </g> <g - transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)" - inkscape:label="Layer 1" - id="g21517-6"> + style="opacity:0.8;stroke:#ff0000" + transform="matrix(-1,0,0,-1,1850,701)" + id="g34104"> <path - sodipodi:type="arc" - style="opacity:0.54857142;fill:url(#radialGradient21442-6-790);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path35486-4" - sodipodi:cx="28.019106" - sodipodi:cy="38.98439" - sodipodi:rx="15.467961" - sodipodi:ry="5.3033009" - d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z" - transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" /> + sodipodi:nodetypes="cszsc" + inkscape:connector-curvature="0" + id="path34106" + d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75" + style="fill:none;stroke:none" /> <path - style="fill:#dd6d00;fill-rule:evenodd;stroke:#993d00;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" - id="path2482-9" - d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z" - sodipodi:nodetypes="csssssssssscccsscccscccssccc" - inkscape:connector-curvature="0" /> + sodipodi:nodetypes="csc" + inkscape:connector-curvature="0" + id="path34108" + d="m 914.5,350.5 c 0,3 1.28917,5 2.5,5 l 1.5,0" + style="fill:none;stroke:url(#linearGradient34969-4-4-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> <path - sodipodi:type="arc" - style="fill:url(#linearGradient21444-0-352);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path39153-3" - sodipodi:cx="31.1875" - sodipodi:cy="25.75" - sodipodi:rx="11.5625" - sodipodi:ry="10.125" - d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z" - transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" /> + inkscape:connector-curvature="0" + id="path34110" + d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5" + style="fill:none;stroke:url(#linearGradient34971-5-0-9);stroke-linecap:round;stroke-linejoin:round" /> <path - sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" - id="path21414-5" - d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 z" - style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446-3-145);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" - inkscape:connector-curvature="0" /> + sodipodi:nodetypes="cssssc" + inkscape:connector-curvature="0" + id="path34113" + d="m 918.5,355.5 0,-2 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5" + style="fill:none;stroke:url(#radialGradient34973-2-5-7);stroke-linecap:round;stroke-linejoin:round" /> + <circle + r="1" + cy="342" + cx="922" + id="path34115" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient34975-9-4-9);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;enable-background:accumulate" + transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" /> <path - style="fill:#2f5b94;fill-rule:evenodd;stroke:none" - id="path2478-8" - d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z" - inkscape:connector-curvature="0" /> + style="fill:none;stroke:none" + d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5" + id="path34901" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccsc" /> + </g> + </g> + </g> + <g + transform="translate(212,-8)" + id="g45475-4" + style="display:inline;enable-background:new"> + <g + style="display:inline" + id="g22242-6" + transform="translate(696,-194)" + inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="0" + rx="2.4004419" + y="430" + x="108" + height="48" + width="48" + id="rect22244-9" + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;enable-background:accumulate" /> + <g + id="g22246-2"> <path - style="opacity:0.51999996;fill:url(#radialGradient21448-8-143);fill-opacity:1;fill-rule:evenodd;stroke:none" - d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 z" - id="path39166-5" - sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient22274-8);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" + d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z" + id="path22249-8" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30" + style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path22251-9" + sodipodi:nodetypes="cccc" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-5)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path22253-5" + d="m 115,444 12,0 -1,-11 -11,11 z" + style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-5)" /> + <path + inkscape:connector-curvature="0" + clip-path="none" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + d="m 117.5,443.75 9,-2.5 0,-6" + style="fill:none;stroke:url(#linearGradient22276-5);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path22264-3" + sodipodi:nodetypes="ccc" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" + id="path22266-6" + style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 z" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + clip-path="url(#clipPath13106-5)" + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + sodipodi:nodetypes="cccc" + id="path22268-0" + d="m 116,443 11,1 -2,-10 -9,9 z" + style="display:inline;opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-5)" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" + d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z" + id="path22270-1" + sodipodi:nodetypes="cccccc" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + id="path22272-3" + style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 147.5,435 0,38.5 -30.5,0" + inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> </g> </g> + <g + id="g21517-6" + inkscape:label="Layer 1" + transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)"> + <ellipse + ry="5.3033009" + rx="15.467961" + cy="38.98439" + cx="28.019106" + transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" + id="path35486-4" + style="display:inline;overflow:visible;visibility:visible;opacity:0.54857142;fill:url(#radialGradient21442-6-790);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="csssssssssscccsscccscccssccc" + d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z" + id="path2482-9" + style="fill:#dd6d00;fill-rule:evenodd;stroke:#993d00;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" /> + <ellipse + ry="10.125" + rx="11.5625" + cy="25.75" + cx="31.1875" + transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" + id="path39153-3" + style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient21444-0-352);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446-3-145);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" + d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 Z" + id="path21414-5" + sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" /> + <path + inkscape:connector-curvature="0" + d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z" + id="path2478-8" + style="fill:#2f5b94;fill-rule:evenodd;stroke:none" /> + <path + inkscape:connector-curvature="0" + sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc" + id="path39166-5" + d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 Z" + style="opacity:0.51999996;fill:url(#radialGradient21448-8-143);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + </g> </g> <g transform="translate(0,12)" @@ -20293,7 +20838,7 @@ <path sodipodi:nodetypes="cc" id="path34332" - style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="" inkscape:connector-curvature="0" /> </g> diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png Binary files differindex 4b7d83dabef..60956db2576 100644 --- a/release/datafiles/splash.png +++ b/release/datafiles/splash.png diff --git a/release/datafiles/splash_2x.png b/release/datafiles/splash_2x.png Binary files differindex a44c96938ff..3a5000c6bbc 100644 --- a/release/datafiles/splash_2x.png +++ b/release/datafiles/splash_2x.png diff --git a/release/datafiles/splash_template.xcf b/release/datafiles/splash_template.xcf Binary files differindex b3141471c51..12719b5c155 100644 --- a/release/datafiles/splash_template.xcf +++ b/release/datafiles/splash_template.xcf diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 407d0ea752b3af73d3f13ba072671bd09eefecb +Subproject 06dad53c80801e0e0919f086040e3d9c31bbd0a diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject 9f29e18707917ec5be262431d2e09dbb85332f4 +Subproject 04af69be141a5757fc60b44cc1a5b72db524af3 diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py index 082ce139a59..93305cb7c5a 100644 --- a/release/scripts/freestyle/modules/parameter_editor.py +++ b/release/scripts/freestyle/modules/parameter_editor.py @@ -914,14 +914,25 @@ class QuantitativeInvisibilityRangeUP1D(UnaryPredicate1D): return self.qi_start <= qi <= self.qi_end +def getQualifiedObjectName(ob): + if ob.library is not None: + return ob.library.filepath + '/' + ob.name + return ob.name + + class ObjectNamesUP1D(UnaryPredicate1D): def __init__(self, names, negative): UnaryPredicate1D.__init__(self) self.names = names self.negative = negative + def getViewShapeName(self, vs): + if vs.library_path is not None: + return vs.library_path + '/' + vs.name + return vs.name + def __call__(self, viewEdge): - found = viewEdge.viewshape.name in self.names + found = self.getViewShapeName(viewEdge.viewshape) in self.names if self.negative: return not found return found @@ -1256,7 +1267,7 @@ def process(layer_name, lineset_name): # prepare selection criteria by group of objects if lineset.select_by_group: if lineset.group is not None: - names = {ob.name: True for ob in lineset.group.objects} + names = {getQualifiedObjectName(ob): True for ob in lineset.group.objects} upred = ObjectNamesUP1D(names, lineset.group_negation == 'EXCLUSIVE') selection_criteria.append(upred) # prepare selection criteria by image border diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py index 5a3eda567be..3b7eff6db9c 100644 --- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py +++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py @@ -230,12 +230,13 @@ def dump_rna_messages(msgs, reports, settings, verbose=False): _rna = {getattr(bpy.types, cls) for cls in dir(bpy.types)} # Classes which are attached to collections can be skipped too, these are api access only. - for cls in _rna: - for prop in cls.bl_rna.properties: - if prop.type == 'COLLECTION': - prop_cls = prop.srna - if prop_cls is not None: - blacklist_rna_class.add(prop_cls.__class__) + # XXX This is not true, some of those show in UI, see e.g. tooltip of KeyingSets.active... + #~ for cls in _rna: + #~ for prop in cls.bl_rna.properties: + #~ if prop.type == 'COLLECTION': + #~ prop_cls = prop.srna + #~ if prop_cls is not None: + #~ blacklist_rna_class.add(prop_cls.__class__) # Now here is the *ugly* hack! # Unfortunately, all classes we want to access are not available from bpy.types (OperatorProperties subclasses @@ -375,6 +376,7 @@ def dump_rna_messages(msgs, reports, settings, verbose=False): walk_keymap_hierarchy(lvl[3], msgsrc) # Dump Messages + operator_categories = {} def process_cls_list(cls_list): if not cls_list: return @@ -391,6 +393,16 @@ def dump_rna_messages(msgs, reports, settings, verbose=False): cls_id = bl_rna.identifier + "." + cls_id bl_rna = bl_rna.base return cls_id + + def operator_category(cls): + """Extract operators' categories, as displayed in 'search' space menu.""" + # NOTE: keep in sync with C code in ui_searchbox_region_draw_cb__operator(). + if issubclass(cls, bpy.types.OperatorProperties) and "_OT_" in cls.__name__: + cat_id = cls.__name__.split("_OT_")[0] + if cat_id not in operator_categories: + cat_str = cat_id.capitalize() + ":" + operator_categories[cat_id] = cat_str + if verbose: print(cls_list) cls_list.sort(key=full_class_id) @@ -402,6 +414,7 @@ def dump_rna_messages(msgs, reports, settings, verbose=False): if (cls in blacklist_rna_class) or issubclass(cls, bpy.types.Operator): reports["rna_structs_skipped"].append(cls) else: + operator_category(cls) walk_class(cls) # Recursively process subclasses. process_cls_list(cls.__subclasses__()) @@ -409,6 +422,11 @@ def dump_rna_messages(msgs, reports, settings, verbose=False): # Parse everything (recursively parsing from bpy_struct "class"...). process_cls_list(bpy.types.ID.__base__.__subclasses__()) + # Finalize generated 'operator categories' messages. + for cat_str in operator_categories.values(): + process_msg(msgs, bpy.app.translations.contexts.operator_default, cat_str, "Generated operator category", + reports, check_ctxt_rna, settings) + # And parse keymaps! from bpy_extras.keyconfig_utils import KM_HIERARCHY walk_keymap_hierarchy(KM_HIERARCHY, "KM_HIERARCHY") diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index ba782160edd..fa42778b53f 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -153,7 +153,7 @@ class SpellChecker: "realtime", "rekey", "remesh", - "reprojection", + "reprojection", "reproject", "resize", "restpose", "retarget", "retargets", "retargeting", "retargeted", @@ -197,6 +197,7 @@ class SpellChecker: "unmute", "unpremultiply", "unprojected", + "unprotect", "unreacted", "unregister", "unselected", "unselectable", @@ -476,6 +477,12 @@ class SpellChecker: "wpaint", "uvwarp", + # UOC (Ugly Operator Categories) + "cachefile", + "paintcurve", + "ptcache", + "dpaint", + # Algorithm/library names "ashikhmin", # Ashikhmin-Shirley "beckmann", @@ -493,6 +500,7 @@ class SpellChecker: "musgrave", "nayar", "netravali", + "ogawa", "oren", "preetham", "prewitt", diff --git a/release/scripts/modules/bl_previews_utils/bl_previews_render.py b/release/scripts/modules/bl_previews_utils/bl_previews_render.py index 6c29223cf55..f7317184bd2 100644 --- a/release/scripts/modules/bl_previews_utils/bl_previews_render.py +++ b/release/scripts/modules/bl_previews_utils/bl_previews_render.py @@ -169,7 +169,7 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern): scene.objects.unlink(bpy.data.objects[render_context.camera, None]) if render_context.lamp: scene.objects.unlink(bpy.data.objects[render_context.lamp, None]) - bpy.data.scenes.remove(scene) + bpy.data.scenes.remove(scene, do_unlink=True) scene = None else: rna_backup_restore(scene, render_context.backup_scene) diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py index b225325ba27..30b9cdfaf37 100644 --- a/release/scripts/modules/sys_info.py +++ b/release/scripts/modules/sys_info.py @@ -158,6 +158,13 @@ def write_sysinfo(filepath): else: output.write("Blender was built without OpenVDB support\n") + alembic = bpy.app.alembic + output.write("Alembic: ") + if alembic.supported: + output.write("%s\n" % alembic.version_string) + else: + output.write("Blender was built without Alembic support\n") + if not bpy.app.build_options.sdl: output.write("SDL: Blender was built without SDL support\n") diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py index 5c3d95e113c..a6ee16e6b71 100644 --- a/release/scripts/startup/bl_operators/object_align.py +++ b/release/scripts/startup/bl_operators/object_align.py @@ -365,6 +365,7 @@ class AlignObjects(Operator): ) align_mode = EnumProperty( name="Align Mode:", + description="Side of object to use for alignment", items=(('OPT_1', "Negative Sides", ""), ('OPT_2', "Centers", ""), ('OPT_3', "Positive Sides", ""), @@ -373,10 +374,11 @@ class AlignObjects(Operator): ) relative_to = EnumProperty( name="Relative To:", - items=(('OPT_1', "Scene Origin", ""), - ('OPT_2', "3D Cursor", ""), - ('OPT_3', "Selection", ""), - ('OPT_4', "Active", ""), + description="Reference location to align to", + items=(('OPT_1', "Scene Origin", "Use the Scene Origin as the position for the selected objects to align to"), + ('OPT_2', "3D Cursor", "Use the 3D cursor as the position for the selected objects to align to"), + ('OPT_3', "Selection", "Use the selected objects as the position for the selected objects to align to"), + ('OPT_4', "Active", "Use the active object as the position for the selected objects to align to"), ), default='OPT_4', ) diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index 4ca2f773dcc..cb5f1595ff3 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -880,6 +880,19 @@ class ConstraintButtonsPanel: layout.operator("clip.constraint_to_fcurve") + def TRANSFORM_CACHE(self, context, layout, con): + layout.label(text="Cache File Properties:") + box = layout.box() + box.template_cache_file(con, "cache_file") + + cache_file = con.cache_file + + layout.label(text="Constraint Properties:") + box = layout.box() + + if cache_file is not None: + box.prop_search(con, "object_path", cache_file, "object_paths") + def SCRIPT(self, context, layout, con): layout.label("Blender 2.6 doesn't support python constraints yet") diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index de3e98611d7..84ee06c7d70 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -181,6 +181,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): layout.prop(md, "cache_format") layout.prop(md, "filepath") + if md.cache_format == 'ABC': + layout.prop(md, "sub_object") + layout.label(text="Evaluation:") layout.prop(md, "factor", slider=True) layout.prop(md, "deform_mode") @@ -215,6 +218,22 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): row = split.row() row.prop(md, "flip_axis") + def MESH_SEQUENCE_CACHE(self, layout, ob, md): + layout.label(text="Cache File Properties:") + box = layout.box() + box.template_cache_file(md, "cache_file") + + cache_file = md.cache_file + + layout.label(text="Modifier Properties:") + box = layout.box() + + if cache_file is not None: + box.prop_search(md, "object_path", cache_file, "object_paths") + + if ob.type == 'MESH': + box.row().prop(md, "read_data") + def CAST(self, layout, ob, md): split = layout.split(percentage=0.25) @@ -881,9 +900,13 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): split = layout.split() col = split.column() - engine = bpy.context.scene.render.engine - if engine == "CYCLES" and md == ob.modifiers[-1] and bpy.context.scene.cycles.feature_set == "EXPERIMENTAL": - col.label(text="Preview:") + scene = bpy.context.scene + engine = scene.render.engine + show_adaptive_options = (engine == "CYCLES" and md == ob.modifiers[-1] and + scene.cycles.feature_set == "EXPERIMENTAL") + + if show_adaptive_options: + col.label(text="View:") col.prop(md, "levels", text="Levels") col.label(text="Render:") col.prop(ob.cycles, "use_adaptive_subdivision", text="Adaptive") @@ -898,11 +921,26 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col = split.column() col.label(text="Options:") - col.prop(md, "use_subsurf_uv") + + sub = col.column() + sub.active = (not show_adaptive_options) or (not ob.cycles.use_adaptive_subdivision) + sub.prop(md, "use_subsurf_uv") + col.prop(md, "show_only_control_edges") if hasattr(md, "use_opensubdiv"): col.prop(md, "use_opensubdiv") + if show_adaptive_options and ob.cycles.use_adaptive_subdivision: + col = layout.column(align=True) + col.scale_y = 0.6 + col.separator() + col.label("Final Dicing Rate:") + col.separator() + + render = max(scene.cycles.dicing_rate * ob.cycles.dicing_rate, 0.1) + preview = max(scene.cycles.preview_dicing_rate * ob.cycles.dicing_rate, 0.1) + col.label("Render %.2f px, Preview %.2f px" % (render, preview)) + def SURFACE(self, layout, ob, md): layout.label(text="Settings are inside the Physics tab") diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index b3d6107ccdb..e42f7263218 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -20,6 +20,7 @@ from bpy.types import Menu, UIList +from bpy.app.translations import pgettext_iface as iface_ def gpencil_stroke_placement_settings(context, layout): @@ -52,6 +53,34 @@ def gpencil_stroke_placement_settings(context, layout): row.prop(ts, "use_gpencil_stroke_endpoints") +def gpencil_active_brush_settings_simple(context, layout): + brush = context.active_gpencil_brush + + col = layout.column() + col.label("Active Brush: ") + + row = col.row(align=True) + row.operator_context = 'EXEC_REGION_WIN' + row.operator_menu_enum("gpencil.brush_change", "brush", text="", icon='BRUSH_DATA') + row.prop(brush, "name", text="") + + col.prop(brush, "line_width", slider=True) + row = col.row(align=True) + row.prop(brush, "use_random_pressure", text='', icon='RNDCURVE') + row.prop(brush, "pen_sensitivity_factor", slider=True) + row.prop(brush, "use_pressure", text='', icon='STYLUS_PRESSURE') + row = col.row(align=True) + row.prop(brush, "use_random_strength", text='', icon='RNDCURVE') + row.prop(brush, "strength", slider=True) + row.prop(brush, "use_strength_pressure", text='', icon='STYLUS_PRESSURE') + row = col.row(align=True) + row.prop(brush, "jitter", slider=True) + row.prop(brush, "use_jitter_pressure", text='', icon='STYLUS_PRESSURE') + row = col.row() + row.prop(brush, "angle", slider=True) + row.prop(brush, "angle_factor", text="Factor", slider=True) + + class GreasePencilDrawingToolsPanel: # subclass must set # bl_space_type = 'IMAGE_EDITOR' @@ -80,6 +109,7 @@ class GreasePencilDrawingToolsPanel: sub = col.column(align=True) sub.prop(context.tool_settings, "use_gpencil_additive_drawing", text="Additive Drawing") sub.prop(context.tool_settings, "use_gpencil_continuous_drawing", text="Continuous Drawing") + sub.prop(context.tool_settings, "use_gpencil_draw_onback", text="Draw on Back") col.separator() col.separator() @@ -136,7 +166,7 @@ class GreasePencilStrokeEditPanel: def draw(self, context): layout = self.layout - is_3d_view = context.space_data.type == 'VIEW_3D' + is_3d_view = context.space_data.type == 'VIEW_3D' if not is_3d_view: layout.label(text="Select:") @@ -190,11 +220,15 @@ class GreasePencilStrokeEditPanel: col = layout.column(align=True) col.operator("gpencil.stroke_join", text="Join").type = 'JOIN' col.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY' - col.operator("gpencil.stroke_flip", text="Flip direction") + col.operator("gpencil.stroke_flip", text="Flip Direction") gpd = context.gpencil_data if gpd: - col.prop(gpd, "show_stroke_direction", text="Show drawing direction") + col.prop(gpd, "show_stroke_direction", text="Show Directions") + + if is_3d_view: + layout.separator() + layout.operator("gpencil.reproject") class GreasePencilBrushPanel: @@ -326,7 +360,7 @@ class GreasePencilStrokeSculptPanel: class GreasePencilBrushCurvesPanel: # subclass must set # bl_space_type = 'IMAGE_EDITOR' - bl_label = "Grease Pencil Curves" + bl_label = "Brush Curves" bl_category = "Grease Pencil" bl_region_type = 'TOOLS' bl_options = {'DEFAULT_CLOSED'} @@ -459,29 +493,7 @@ class GPENCIL_PIE_settings_palette(Menu): col.prop(palcolor, "fill_alpha", text="", slider=True) # S Brush settings - col = pie.column() - col.label("Active Brush: ") - - row = col.row() - row.operator_context = 'EXEC_REGION_WIN' - row.operator_menu_enum("gpencil.brush_change", "brush", text="", icon='BRUSH_DATA') - row.prop(brush, "name", text="") - - col.prop(brush, "line_width", slider=True) - row = col.row(align=True) - row.prop(brush, "use_random_pressure", text='', icon='RNDCURVE') - row.prop(brush, "pen_sensitivity_factor", slider=True) - row.prop(brush, "use_pressure", text='', icon='STYLUS_PRESSURE') - row = col.row(align=True) - row.prop(brush, "use_random_strength", text='', icon='RNDCURVE') - row.prop(brush, "strength", slider=True) - row.prop(brush, "use_strength_pressure", text='', icon='STYLUS_PRESSURE') - row = col.row(align=True) - row.prop(brush, "jitter", slider=True) - row.prop(brush, "use_jitter_pressure", text='', icon='STYLUS_PRESSURE') - row = col.row() - row.prop(brush, "angle", slider=True) - row.prop(brush, "angle_factor", text="Factor", slider=True) + gpencil_active_brush_settings_simple(context, pie) # N - Active Layer col = pie.column() @@ -658,7 +670,7 @@ class GPENCIL_UL_palettecolor(UIList): row = split.row(align=True) row.prop(palcolor, "color", text="", emboss=palcolor.is_stroke_visible) row.prop(palcolor, "fill_color", text="", emboss=palcolor.is_fill_visible) - split.prop(palcolor, "info", text="", emboss=False) + split.prop(palcolor, "name", text="", emboss=False) row = layout.row(align=True) row.prop(palcolor, "lock", text="", emboss=False) @@ -748,6 +760,10 @@ class GPENCIL_MT_palettecolor_specials(Menu): layout.operator("gpencil.palettecolor_unlock_all", icon='UNLOCKED', text="UnLock All") layout.operator("gpencil.palettecolor_copy", icon='PASTEDOWN', text="Copy Color") + layout.separator() + + layout.operator("gpencil.palettecolor_select", icon='COLOR', text="Select Strokes") + class GreasePencilDataPanel: # subclass must set @@ -821,33 +837,35 @@ class GreasePencilDataPanel: def draw_layer(self, context, layout, gpl): row = layout.row(align=True) row.prop(gpl, "opacity", text="Opacity", slider=True) - # layer settings + + # Layer options split = layout.split(percentage=0.5) split.active = not gpl.lock - # Options - split = layout.split(percentage=0.5) - col = split.column(align=True) - col.active = not gpl.lock - col.prop(gpl, "show_x_ray") - - col.label("Tint") - col.prop(gpl, "tint_color", text="") - col.prop(gpl, "tint_factor", text="Factor", slider=True) + split.prop(gpl, "show_x_ray") + split.prop(gpl, "show_points") - col = split.column(align=True) - col.active = not gpl.lock - col.prop(gpl, "show_points", text="Points") - # Full-Row - Parent - ''' - row = layout.row() - if context.area.type == 'VIEW_3D' and not gpl.lock: - row.enabled = True + # Offsets + Parenting (where available) + if context.space_data.type == 'VIEW_3D': + split = layout.split(percentage=0.5) else: - row.enabled = False - ''' + split = layout.column() # parenting is not available in 2D editors... + split.active = not gpl.lock + + # Offsets - Color Tint + col = split.column() + subcol = col.column(align=True) + subcol.label("Tint") + subcol.prop(gpl, "tint_color", text="") + subcol.prop(gpl, "tint_factor", text="Factor", slider=True) - # col = row.column() + # Offsets - Thickness + row = col.row(align=True) + row.prop(gpl, "line_change", text="Thickness Change", slider=True) + row.operator("gpencil.stroke_apply_thickness", icon='STYLUS_PRESSURE', text="") + + # Parenting if context.space_data.type == 'VIEW_3D': + col = split.column(align=True) col.label(text="Parent:") col.prop(gpl, "parent", text="") @@ -857,24 +875,22 @@ class GreasePencilDataPanel: if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE': sub.prop_search(gpl, "parent_bone", parent.data, "bones", text="") - # Full-Row - Thickness - row = layout.row(align=True) - row.active = not gpl.lock - row.prop(gpl, "line_change", text="Thickness change", slider=True) - row.operator("gpencil.stroke_apply_thickness", icon='STYLUS_PRESSURE', text="") + layout.separator() # Full-Row - Frame Locking (and Delete Frame) row = layout.row(align=True) row.active = not gpl.lock if gpl.active_frame: - lock_status = "Locked" if gpl.lock_frame else "Unlocked" - lock_label = "Frame: %d (%s)" % (gpl.active_frame.frame_number, lock_status) + lock_status = iface_("Locked") if gpl.lock_frame else iface_("Unlocked") + lock_label = iface_("Frame: %d (%s)") % (gpl.active_frame.frame_number, lock_status) else: - lock_label = "Lock Frame" + lock_label = iface_("Lock Frame") row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED') row.operator("gpencil.active_frame_delete", text="", icon='X') + layout.separator() + # Onion skinning col = layout.column(align=True) col.active = not gpl.lock @@ -925,7 +941,7 @@ class GreasePencilPaletteColorPanel: row.operator_menu_enum("gpencil.palette_change", "palette", text="", icon='COLOR') row.prop(palette, "name", text="") row.operator("gpencil.palette_add", icon='ZOOMIN', text="") - row.operator("gpencil.palette_remove", icon='ZOOMOUT', text="") + row.operator("gpencil.palette_remove", icon='X', text="") # Palette colors row = layout.row() @@ -954,10 +970,13 @@ class GreasePencilPaletteColorPanel: sub.operator("gpencil.palettecolor_move", icon='TRIA_UP', text="").direction = 'UP' sub.operator("gpencil.palettecolor_move", icon='TRIA_DOWN', text="").direction = 'DOWN' - col.separator() - sub = col.column(align=True) + row = layout.row() + sub = row.row(align=True) + sub.label(text="Isolate:") # based on active color only sub.operator("gpencil.palettecolor_isolate", icon='LOCKED', text="").affect_visibility = False sub.operator("gpencil.palettecolor_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True + sub = row.row(align=True) + sub.label(text="Lock:") # based on other stuff... sub.operator("gpencil.stroke_lock_color", icon='BORDER_RECT', text="") sub.operator("gpencil.palette_lock_layer", icon='COLOR', text="") @@ -965,9 +984,7 @@ class GreasePencilPaletteColorPanel: if pcolor: self.draw_palettecolors(layout, pcolor) - # ---------------------------------------------- # Draw palette colors - # ---------------------------------------------- def draw_palettecolors(self, layout, pcolor): # color settings split = layout.split(percentage=0.5) @@ -1000,6 +1017,7 @@ class GreasePencilPaletteColorPanel: class GreasePencilToolsPanel: + # For use in "2D" Editors without their own toolbar # subclass must set # bl_space_type = 'IMAGE_EDITOR' # bl_options = {'DEFAULT_CLOSED'} @@ -1029,4 +1047,8 @@ class GreasePencilToolsPanel: layout.separator() layout.separator() + gpencil_active_brush_settings_simple(context, layout) + + layout.separator() + gpencil_stroke_placement_settings(context, layout) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index c2580d4ac71..89ea9dff69b 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -716,6 +716,8 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel): col.prop(boids, "land_personal_space") col.prop(boids, "land_stick_force") + layout.prop(part, "collision_group") + split = layout.split() col = split.column(align=True) diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 794ef5189d6..152d4e96d5d 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -345,7 +345,9 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel): layout.prop(rd, "use_stamp") col = layout.column() col.active = rd.use_stamp - col.prop(rd, "stamp_font_size", text="Font Size") + row = col.row() + row.prop(rd, "stamp_font_size", text="Font Size") + row.prop(rd, "use_stamp_labels", text="Draw labels") row = col.row() row.column().prop(rd, "stamp_foreground", slider=True) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 799f1e20dc6..5cc135392c1 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -621,6 +621,7 @@ class CLIP_PT_track(CLIP_PT_tracking_panel, Panel): text="", toggle=True, icon='IMAGE_ALPHA') layout.prop(act_track, "weight") + layout.prop(act_track, "weight_stab") if act_track.has_bundle: label_text = "Average Error: %.4f" % (act_track.average_error) @@ -907,44 +908,78 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel): self.layout.prop(stab, "use_2d_stabilization", text="") def draw(self, context): - layout = self.layout - tracking = context.space_data.clip.tracking stab = tracking.stabilization + layout = self.layout layout.active = stab.use_2d_stabilization - row = layout.row() - row.template_list("UI_UL_list", "stabilization_tracks", stab, "tracks", - stab, "active_track_index", rows=2) + layout.prop(stab, "anchor_frame") - sub = row.column(align=True) + row = layout.row(align=True) + row.prop(stab, "use_stabilize_rotation", text="Rotation", toggle=True) + sub = row.row(align=True) + sub.active = stab.use_stabilize_rotation + sub.prop(stab, "use_stabilize_scale", text="Scale", toggle=True) + + box = layout.box() + row = box.row(align=True) + row.prop(stab, "show_tracks_expanded", text="", emboss=False) - sub.operator("clip.stabilize_2d_add", icon='ZOOMIN', text="") - sub.operator("clip.stabilize_2d_remove", icon='ZOOMOUT', text="") + if not stab.show_tracks_expanded: + row.label(text="Tracks For Stabilization") + else: + row.label(text="Tracks For Location") + row = box.row() + row.template_list("UI_UL_list", "stabilization_tracks", stab, "tracks", + stab, "active_track_index", rows=2) - sub.menu('CLIP_MT_stabilize_2d_specials', text="", - icon='DOWNARROW_HLT') + sub = row.column(align=True) - layout.prop(stab, "influence_location") + sub.operator("clip.stabilize_2d_add", icon='ZOOMIN', text="") + sub.operator("clip.stabilize_2d_remove", icon='ZOOMOUT', text="") - layout.prop(stab, "use_autoscale") - col = layout.column() - col.active = stab.use_autoscale - col.prop(stab, "scale_max") - col.prop(stab, "influence_scale") + sub.menu('CLIP_MT_stabilize_2d_specials', text="", + icon='DOWNARROW_HLT') - layout.prop(stab, "use_stabilize_rotation") - col = layout.column() - col.active = stab.use_stabilize_rotation + # Usually we don't hide things from iterface, but here every pixel of + # vertical space is precious. + if stab.use_stabilize_rotation: + box.label(text="Tracks For Rotation / Scale") + row = box.row() + row.template_list("UI_UL_list", "stabilization_rotation_tracks", + stab, "rotation_tracks", + stab, "active_rotation_track_index", rows=2) + + sub = row.column(align=True) + + sub.operator("clip.stabilize_2d_rotation_add", icon='ZOOMIN', text="") + sub.operator("clip.stabilize_2d_rotation_remove", icon='ZOOMOUT', text="") + + sub.menu('CLIP_MT_stabilize_2d_rotation_specials', text="", + icon='DOWNARROW_HLT') + row = layout.row() + row.prop(stab, "use_autoscale") + sub = row.row() + sub.active = stab.use_autoscale + sub.prop(stab, "scale_max", text="Max") + + col = layout.column(align=True) row = col.row(align=True) - row.prop_search(stab, "rotation_track", tracking, "tracks", text="") - row.operator("clip.stabilize_2d_set_rotation", text="", icon='ZOOMIN') + # Hrm, how to make it more obvious label? + row.prop(stab, "target_position", text="") + col.prop(stab, "target_rotation") + row = col.row(align=True) + row.prop(stab, "target_scale") + row.active = not stab.use_autoscale - row = col.row() - row.active = stab.rotation_track is not None - row.prop(stab, "influence_rotation") + col = layout.column(align=True) + col.prop(stab, "influence_location") + sub = col.column(align=True) + sub.active = stab.use_stabilize_rotation + sub.prop(stab, "influence_rotation") + sub.prop(stab, "influence_scale") layout.prop(stab, "filter_type") @@ -1434,7 +1469,7 @@ class CLIP_MT_track_color_specials(Menu): class CLIP_MT_stabilize_2d_specials(Menu): - bl_label = "Track Color Specials" + bl_label = "Translation Track Specials" def draw(self, context): layout = self.layout @@ -1442,5 +1477,14 @@ class CLIP_MT_stabilize_2d_specials(Menu): layout.operator("clip.stabilize_2d_select") +class CLIP_MT_stabilize_2d_rotation_specials(Menu): + bl_label = "Rotation Track Specials" + + def draw(self, context): + layout = self.layout + + layout.operator("clip.stabilize_2d_rotation_select") + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index 97ef37fa5e0..780dc4cf982 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -158,6 +158,8 @@ class INFO_MT_file_import(Menu): def draw(self, context): if bpy.app.build_options.collada: self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)") + if bpy.app.build_options.alembic: + self.layout.operator("wm.alembic_import", text="Alembic (.abc)") class INFO_MT_file_export(Menu): @@ -167,6 +169,8 @@ class INFO_MT_file_export(Menu): def draw(self, context): if bpy.app.build_options.collada: self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)") + if bpy.app.build_options.alembic: + self.layout.operator("wm.alembic_export", text="Alembic (.abc)") class INFO_MT_file_external_data(Menu): diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 1512f4f4600..dcafac66fca 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1177,15 +1177,16 @@ class USERPREF_PT_input(Panel): sub.prop(walk, "view_height") sub.prop(walk, "jump_height") - col.separator() - col.label(text="NDOF Device:") - sub = col.column(align=True) - sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity") - sub.prop(inputs, "ndof_orbit_sensitivity", text="NDOF Orbit Sensitivity") - sub.prop(inputs, "ndof_deadzone", text="NDOF Deadzone") - sub = col.column(align=True) - sub.row().prop(inputs, "ndof_view_navigate_method", expand=True) - sub.row().prop(inputs, "ndof_view_rotate_method", expand=True) + if inputs.use_ndof: + col.separator() + col.label(text="NDOF Device:") + sub = col.column(align=True) + sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity") + sub.prop(inputs, "ndof_orbit_sensitivity", text="NDOF Orbit Sensitivity") + sub.prop(inputs, "ndof_deadzone", text="NDOF Deadzone") + sub = col.column(align=True) + sub.row().prop(inputs, "ndof_view_navigate_method", expand=True) + sub.row().prop(inputs, "ndof_view_rotate_method", expand=True) row.separator() diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 53790946f9d..0f969511d9d 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -411,6 +411,20 @@ class VIEW3D_MT_uv_map(Menu): layout.operator("uv.reset") +class VIEW3D_MT_edit_proportional(Menu): + bl_label = "Proportional Editing" + + def draw(self, context): + layout = self.layout + + layout.props_enum(context.tool_settings,"proportional_edit") + + layout.separator() + + layout.label("Falloff:") + layout.props_enum(context.tool_settings,"proportional_edit_falloff") + + # ********** View menus ********** @@ -1000,8 +1014,7 @@ class VIEW3D_MT_select_gpencil(Menu): layout.operator("gpencil.select_all", text="(De)select All").action = 'TOGGLE' layout.operator("gpencil.select_all", text="Inverse").action = 'INVERT' layout.operator("gpencil.select_linked", text="Linked") - #layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped") - layout.operator("gpencil.select_grouped", text="Grouped") + layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped") layout.separator() @@ -2312,8 +2325,7 @@ class VIEW3D_MT_edit_mesh(Menu): layout.separator() layout.prop(toolsettings, "use_mesh_automerge") - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") layout.separator() @@ -2428,6 +2440,8 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' + with_bullet = bpy.app.build_options.bullet + layout.operator("mesh.merge") layout.operator("mesh.rip_move") layout.operator("mesh.rip_move_fill") @@ -2448,7 +2462,8 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout.separator() layout.operator("mesh.bevel").vertex_only = True - layout.operator("mesh.convex_hull") + if with_bullet: + layout.operator("mesh.convex_hull") layout.operator("mesh.vertices_smooth") layout.operator("mesh.remove_doubles") @@ -2682,8 +2697,7 @@ def draw_curve(self, context): layout.separator() - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") layout.separator() @@ -2842,8 +2856,7 @@ class VIEW3D_MT_edit_meta(Menu): layout.separator() - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") layout.separator() @@ -2880,8 +2893,7 @@ class VIEW3D_MT_edit_lattice(Menu): layout.separator() - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") class VIEW3D_MT_edit_armature(Menu): @@ -3041,8 +3053,7 @@ class VIEW3D_MT_edit_gpencil(Menu): layout.separator() - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") layout.separator() diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index e36f9e2b43e..6f2b78e0845 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -31,6 +31,7 @@ set(SRC_DNA_INC ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_armature_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_boid_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_cachefile_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_camera_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_cloth_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_color_types.h @@ -153,3 +154,6 @@ if(WITH_FREESTYLE) add_subdirectory(freestyle) endif() +if(WITH_ALEMBIC) + add_subdirectory(alembic) +endif() diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h new file mode 100644 index 00000000000..cf121f8488c --- /dev/null +++ b/source/blender/alembic/ABC_alembic.h @@ -0,0 +1,110 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_ALEMBIC_H__ +#define __ABC_ALEMBIC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct bContext; +struct DerivedMesh; +struct ListBase; +struct Object; +struct Scene; + +typedef struct AbcArchiveHandle AbcArchiveHandle; + +enum { + ABC_ARCHIVE_OGAWA = 0, + ABC_ARCHIVE_HDF5 = 1, +}; + +int ABC_get_version(void); + +struct AlembicExportParams { + double frame_start; + double frame_end; + + double frame_step_xform; + double frame_step_shape; + + double shutter_open; + double shutter_close; + + /* bools */ + unsigned int selected_only : 1; + unsigned int uvs : 1; + unsigned int normals : 1; + unsigned int vcolors : 1; + unsigned int apply_subdiv : 1; + unsigned int flatten_hierarchy : 1; + unsigned int visible_layers_only : 1; + unsigned int renderable_only : 1; + unsigned int face_sets : 1; + unsigned int use_subdiv_schema : 1; + unsigned int packuv : 1; + + unsigned int compression_type : 1; + float global_scale; +}; + +void ABC_export( + struct Scene *scene, + struct bContext *C, + const char *filepath, + const struct AlembicExportParams *params); + +void ABC_import(struct bContext *C, + const char *filepath, + float scale, + bool is_sequence, + bool set_frame_range, + int sequence_len, + int offset, + bool validate_meshes); + +AbcArchiveHandle *ABC_create_handle(const char *filename, struct ListBase *object_paths); + +void ABC_free_handle(AbcArchiveHandle *handle); + +void ABC_get_transform(AbcArchiveHandle *handle, + struct Object *ob, + const char *object_path, + float r_mat[4][4], + float time, + float scale); + +struct DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle, + struct Object *ob, + struct DerivedMesh *dm, + const char *object_path, + const float time, + const char **err_str, + int flags); + +#ifdef __cplusplus +} +#endif + +#endif /* __ABC_ALEMBIC_H__ */ diff --git a/source/blender/alembic/CMakeLists.txt b/source/blender/alembic/CMakeLists.txt new file mode 100644 index 00000000000..0b6b2433bd0 --- /dev/null +++ b/source/blender/alembic/CMakeLists.txt @@ -0,0 +1,82 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Kevin Dietrich. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + ../blenkernel + ../blenlib + ../blenloader + ../editors/include + ../makesdna + ../makesrna + ../windowmanager + ../../../intern/guardedalloc + ../../../intern/utfconv +) + +set(INC_SYS + ${ALEMBIC_INCLUDE_DIRS} + ${HDF5_INCLUDE_DIRS} + ${OPENEXR_INCLUDE_DIRS} +) +if(APPLE OR WIN32) + list(APPEND INC_SYS + ${BOOST_INCLUDE_DIR} + ) +endif() + +set(SRC + intern/abc_camera.cc + intern/abc_customdata.cc + intern/abc_curves.cc + intern/abc_exporter.cc + intern/abc_hair.cc + intern/abc_mesh.cc + intern/abc_nurbs.cc + intern/abc_object.cc + intern/abc_points.cc + intern/abc_transform.cc + intern/abc_util.cc + intern/alembic_capi.cc + + ABC_alembic.h + intern/abc_camera.h + intern/abc_customdata.h + intern/abc_curves.h + intern/abc_exporter.h + intern/abc_hair.h + intern/abc_mesh.h + intern/abc_nurbs.h + intern/abc_object.h + intern/abc_points.h + intern/abc_transform.h + intern/abc_util.h +) + +if(WITH_ALEMBIC_HDF5) + add_definitions(-DWITH_ALEMBIC_HDF5) +endif() + +blender_add_lib(bf_alembic "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_camera.cc new file mode 100644 index 00000000000..5c34ec1391f --- /dev/null +++ b/source/blender/alembic/intern/abc_camera.cc @@ -0,0 +1,162 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "abc_camera.h" + +#include "abc_transform.h" +#include "abc_util.h" + +extern "C" { +#include "DNA_camera_types.h" +#include "DNA_object_types.h" + +#include "BKE_camera.h" +#include "BKE_object.h" + +#include "BLI_math.h" +#include "BLI_string.h" +} + +using Alembic::AbcGeom::ICamera; +using Alembic::AbcGeom::ICompoundProperty; +using Alembic::AbcGeom::IFloatProperty; +using Alembic::AbcGeom::ISampleSelector; + +using Alembic::AbcGeom::OCamera; +using Alembic::AbcGeom::OFloatProperty; + +using Alembic::AbcGeom::CameraSample; +using Alembic::AbcGeom::kWrapExisting; + +/* ************************************************************************** */ + +AbcCameraWriter::AbcCameraWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings) + : AbcObjectWriter(scene, ob, time_sampling, settings, parent) +{ + OCamera camera(parent->alembicXform(), m_name, m_time_sampling); + m_camera_schema = camera.getSchema(); + + m_custom_data_container = m_camera_schema.getUserProperties(); + m_stereo_distance = OFloatProperty(m_custom_data_container, "stereoDistance", m_time_sampling); + m_eye_separation = OFloatProperty(m_custom_data_container, "eyeSeparation", m_time_sampling); +} + +void AbcCameraWriter::do_write() +{ + Camera *cam = static_cast<Camera *>(m_object->data); + + m_stereo_distance.set(cam->stereo.convergence_distance); + m_eye_separation.set(cam->stereo.interocular_distance); + + const double apperture_x = cam->sensor_x / 10.0; + const double apperture_y = cam->sensor_y / 10.0; + const double film_aspect = apperture_x / apperture_y; + + m_camera_sample.setFocalLength(cam->lens); + m_camera_sample.setHorizontalAperture(apperture_x); + m_camera_sample.setVerticalAperture(apperture_y); + m_camera_sample.setHorizontalFilmOffset(apperture_x * cam->shiftx); + m_camera_sample.setVerticalFilmOffset(apperture_y * cam->shifty * film_aspect); + m_camera_sample.setNearClippingPlane(cam->clipsta); + m_camera_sample.setFarClippingPlane(cam->clipend); + + if (cam->dof_ob) { + Imath::V3f v(m_object->loc[0] - cam->dof_ob->loc[0], + m_object->loc[1] - cam->dof_ob->loc[1], + m_object->loc[2] - cam->dof_ob->loc[2]); + m_camera_sample.setFocusDistance(v.length()); + } + else { + m_camera_sample.setFocusDistance(cam->gpu_dof.focus_distance); + } + + /* Blender camera does not have an fstop param, so try to find a custom prop + * instead. */ + m_camera_sample.setFStop(cam->gpu_dof.fstop); + + m_camera_sample.setLensSqueezeRatio(1.0); + m_camera_schema.set(m_camera_sample); +} + +/* ************************************************************************** */ + +AbcCameraReader::AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings) + : AbcObjectReader(object, settings) +{ + ICamera abc_cam(m_iobject, kWrapExisting); + m_schema = abc_cam.getSchema(); + + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); +} + +bool AbcCameraReader::valid() const +{ + return m_schema.valid(); +} + +void AbcCameraReader::readObjectData(Main *bmain, float time) +{ + Camera *bcam = static_cast<Camera *>(BKE_camera_add(bmain, "abc_camera")); + + ISampleSelector sample_sel(time); + CameraSample cam_sample; + m_schema.get(cam_sample, sample_sel); + + ICompoundProperty customDataContainer = m_schema.getUserProperties(); + + if (customDataContainer.valid() && + customDataContainer.getPropertyHeader("stereoDistance") && + customDataContainer.getPropertyHeader("eyeSeparation")) + { + IFloatProperty convergence_plane(customDataContainer, "stereoDistance"); + IFloatProperty eye_separation(customDataContainer, "eyeSeparation"); + + bcam->stereo.interocular_distance = eye_separation.getValue(sample_sel); + bcam->stereo.convergence_distance = convergence_plane.getValue(sample_sel); + } + + const float lens = cam_sample.getFocalLength(); + const float apperture_x = cam_sample.getHorizontalAperture(); + const float apperture_y = cam_sample.getVerticalAperture(); + const float h_film_offset = cam_sample.getHorizontalFilmOffset(); + const float v_film_offset = cam_sample.getVerticalFilmOffset(); + const float film_aspect = apperture_x / apperture_y; + + bcam->lens = lens; + bcam->sensor_x = apperture_x * 10; + bcam->sensor_y = apperture_y * 10; + bcam->shiftx = h_film_offset / apperture_x; + bcam->shifty = v_film_offset / apperture_y / film_aspect; + bcam->clipsta = max_ff(0.1f, cam_sample.getNearClippingPlane()); + bcam->clipend = cam_sample.getFarClippingPlane(); + bcam->gpu_dof.focus_distance = cam_sample.getFocusDistance(); + bcam->gpu_dof.fstop = cam_sample.getFStop(); + + BLI_strncpy(bcam->id.name + 2, m_data_name.c_str(), m_data_name.size() + 1); + + m_object = BKE_object_add_only_object(bmain, OB_CAMERA, m_object_name.c_str()); + m_object->data = bcam; +} diff --git a/source/blender/alembic/intern/abc_camera.h b/source/blender/alembic/intern/abc_camera.h new file mode 100644 index 00000000000..fafb4d3eb39 --- /dev/null +++ b/source/blender/alembic/intern/abc_camera.h @@ -0,0 +1,61 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_CAMERA_H__ +#define __ABC_CAMERA_H__ + +#include "abc_object.h" + +/* ************************************************************************** */ + +class AbcCameraWriter : public AbcObjectWriter { + Alembic::AbcGeom::OCameraSchema m_camera_schema; + Alembic::AbcGeom::CameraSample m_camera_sample; + Alembic::AbcGeom::OCompoundProperty m_custom_data_container; + Alembic::AbcGeom::OFloatProperty m_stereo_distance; + Alembic::AbcGeom::OFloatProperty m_eye_separation; + +public: + AbcCameraWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings); + +private: + virtual void do_write(); +}; + +/* ************************************************************************** */ + +class AbcCameraReader : public AbcObjectReader { + Alembic::AbcGeom::ICameraSchema m_schema; + +public: + AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings); + + bool valid() const; + + void readObjectData(Main *bmain, float time); +}; + +#endif /* __ABC_CAMERA_H__ */
\ No newline at end of file diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc new file mode 100644 index 00000000000..2b54741a5c5 --- /dev/null +++ b/source/blender/alembic/intern/abc_curves.cc @@ -0,0 +1,355 @@ +/* + * ***** 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) 2016 Kévin Dietrich. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include "abc_curves.h" + +#include <cstdio> + +#include "abc_transform.h" +#include "abc_util.h" + +extern "C" { +#include "MEM_guardedalloc.h" + +#include "DNA_curve_types.h" +#include "DNA_object_types.h" + +#include "BLI_listbase.h" + +#include "BKE_curve.h" +#include "BKE_object.h" + +#include "ED_curve.h" +} + +using Alembic::Abc::IInt32ArrayProperty; +using Alembic::Abc::Int32ArraySamplePtr; +using Alembic::Abc::FloatArraySamplePtr; +using Alembic::Abc::P3fArraySamplePtr; +using Alembic::Abc::UcharArraySamplePtr; + +using Alembic::AbcGeom::ICurves; +using Alembic::AbcGeom::ICurvesSchema; +using Alembic::AbcGeom::IFloatGeomParam; +using Alembic::AbcGeom::ISampleSelector; +using Alembic::AbcGeom::kWrapExisting; +using Alembic::AbcGeom::CurvePeriodicity; + +using Alembic::AbcGeom::OCurves; +using Alembic::AbcGeom::OCurvesSchema; +using Alembic::AbcGeom::ON3fGeomParam; +using Alembic::AbcGeom::OV2fGeomParam; + +/* ************************************************************************** */ + +AbcCurveWriter::AbcCurveWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings) + : AbcObjectWriter(scene, ob, time_sampling, settings, parent) +{ + OCurves curves(parent->alembicXform(), m_name, m_time_sampling); + m_schema = curves.getSchema(); +} + +void AbcCurveWriter::do_write() +{ + Curve *curve = static_cast<Curve *>(m_object->data); + + std::vector<Imath::V3f> verts; + std::vector<int32_t> vert_counts; + std::vector<float> widths; + std::vector<float> weights; + std::vector<float> knots; + std::vector<uint8_t> orders; + Imath::V3f temp_vert; + + Alembic::AbcGeom::BasisType curve_basis; + Alembic::AbcGeom::CurveType curve_type; + Alembic::AbcGeom::CurvePeriodicity periodicity; + + Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first); + for (; nurbs; nurbs = nurbs->next) { + if (nurbs->bp) { + curve_basis = Alembic::AbcGeom::kNoBasis; + curve_type = Alembic::AbcGeom::kLinear; + + const int totpoint = nurbs->pntsu * nurbs->pntsv; + + const BPoint *point = nurbs->bp; + + for (int i = 0; i < totpoint; ++i, ++point) { + copy_zup_yup(temp_vert.getValue(), point->vec); + verts.push_back(temp_vert); + weights.push_back(point->vec[3]); + widths.push_back(point->radius); + } + } + else if (nurbs->bezt) { + curve_basis = Alembic::AbcGeom::kBezierBasis; + curve_type = Alembic::AbcGeom::kCubic; + + const int totpoint = nurbs->pntsu; + + const BezTriple *bezier = nurbs->bezt; + + /* TODO(kevin): store info about handles, Alembic doesn't have this. */ + for (int i = 0; i < totpoint; ++i, ++bezier) { + copy_zup_yup(temp_vert.getValue(), bezier->vec[1]); + verts.push_back(temp_vert); + widths.push_back(bezier->radius); + } + } + + if ((nurbs->flagu & CU_NURB_ENDPOINT) != 0) { + periodicity = Alembic::AbcGeom::kNonPeriodic; + } + else if ((nurbs->flagu & CU_NURB_CYCLIC) != 0) { + periodicity = Alembic::AbcGeom::kPeriodic; + + /* Duplicate the start points to indicate that the curve is actually + * cyclic since other software need those. + */ + + for (int i = 0; i < nurbs->orderu; ++i) { + verts.push_back(verts[i]); + } + } + + if (nurbs->knotsu != NULL) { + const size_t num_knots = KNOTSU(nurbs); + + /* Add an extra knot at the beggining and end of the array since most apps + * require/expect them. */ + knots.resize(num_knots + 2); + + for (int i = 0; i < num_knots; ++i) { + knots[i + 1] = nurbs->knotsu[i]; + } + + if ((nurbs->flagu & CU_NURB_CYCLIC) != 0) { + knots[0] = nurbs->knotsu[0]; + knots[num_knots - 1] = nurbs->knotsu[num_knots - 1]; + } + else { + knots[0] = (2.0f * nurbs->knotsu[0] - nurbs->knotsu[1]); + knots[num_knots - 1] = (2.0f * nurbs->knotsu[num_knots - 1] - nurbs->knotsu[num_knots - 2]); + } + } + + orders.push_back(nurbs->orderu + 1); + vert_counts.push_back(verts.size()); + } + + Alembic::AbcGeom::OFloatGeomParam::Sample width_sample; + width_sample.setVals(widths); + + m_sample = OCurvesSchema::Sample(verts, + vert_counts, + curve_type, + periodicity, + width_sample, + OV2fGeomParam::Sample(), /* UVs */ + ON3fGeomParam::Sample(), /* normals */ + curve_basis, + weights, + orders, + knots); + + m_sample.setSelfBounds(bounds()); + m_schema.set(m_sample); +} + +/* ************************************************************************** */ + +AbcCurveReader::AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettings &settings) + : AbcObjectReader(object, settings) +{ + ICurves abc_curves(object, kWrapExisting); + m_curves_schema = abc_curves.getSchema(); + + get_min_max_time(m_iobject, m_curves_schema, m_min_time, m_max_time); +} + +bool AbcCurveReader::valid() const +{ + return m_curves_schema.valid(); +} + +void AbcCurveReader::readObjectData(Main *bmain, float time) +{ + Curve *cu = BKE_curve_add(bmain, m_data_name.c_str(), OB_CURVE); + + cu->flag |= CU_DEFORM_FILL | CU_3D; + cu->actvert = CU_ACT_NONE; + + m_object = BKE_object_add_only_object(bmain, OB_CURVE, m_object_name.c_str()); + m_object->data = cu; + + read_curve_sample(cu, m_curves_schema, time); + + if (has_animations(m_curves_schema, m_settings)) { + addCacheModifier(); + } +} + +/* ************************************************************************** */ + +void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) +{ + const ISampleSelector sample_sel(time); + ICurvesSchema::Sample smp = schema.getValue(sample_sel); + const Int32ArraySamplePtr num_vertices = smp.getCurvesNumVertices(); + const P3fArraySamplePtr positions = smp.getPositions(); + const FloatArraySamplePtr weights = smp.getPositionWeights(); + const FloatArraySamplePtr knots = smp.getKnots(); + const CurvePeriodicity periodicity = smp.getWrap(); + const UcharArraySamplePtr orders = smp.getOrders(); + + const IFloatGeomParam widths_param = schema.getWidthsParam(); + FloatArraySamplePtr radiuses; + + if (widths_param.valid()) { + IFloatGeomParam::Sample wsample = widths_param.getExpandedValue(sample_sel); + radiuses = wsample.getVals(); + } + + int knot_offset = 0; + + size_t idx = 0; + for (size_t i = 0; i < num_vertices->size(); ++i) { + const int num_verts = (*num_vertices)[i]; + + Nurb *nu = static_cast<Nurb *>(MEM_callocN(sizeof(Nurb), "abc_getnurb")); + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->pntsu = num_verts; + nu->pntsv = 1; + nu->flag |= CU_SMOOTH; + + nu->orderu = num_verts; + + if (smp.getType() == Alembic::AbcGeom::kCubic) { + nu->orderu = 3; + } + else if (orders && orders->size() > i) { + nu->orderu = static_cast<short>((*orders)[i] - 1); + } + + if (periodicity == Alembic::AbcGeom::kNonPeriodic) { + nu->flagu |= CU_NURB_ENDPOINT; + } + else if (periodicity == Alembic::AbcGeom::kPeriodic) { + nu->flagu |= CU_NURB_CYCLIC; + + /* Check the number of points which overlap, we don't have + * overlapping points in Blender, but other software do use them to + * indicate that a curve is actually cyclic. Usually the number of + * overlapping points is equal to the order/degree of the curve. + */ + + const int start = idx; + const int end = idx + num_verts; + int overlap = 0; + + for (int j = start, k = end - nu->orderu; j < nu->orderu; ++j, ++k) { + const Imath::V3f &p1 = (*positions)[j]; + const Imath::V3f &p2 = (*positions)[k]; + + if (p1 != p2) { + break; + } + + ++overlap; + } + + /* TODO: Special case, need to figure out how it coincides with knots. */ + if (overlap == 0 && num_verts > 2 && (*positions)[start] == (*positions)[end - 1]) { + overlap = 1; + } + + /* There is no real cycles. */ + if (overlap == 0) { + nu->flagu &= ~CU_NURB_CYCLIC; + nu->flagu |= CU_NURB_ENDPOINT; + } + + nu->pntsu -= overlap; + } + + const bool do_weights = (weights != NULL) && (weights->size() > 1); + float weight = 1.0f; + + const bool do_radius = (radiuses != NULL) && (radiuses->size() > 1); + float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] : 1.0f; + + nu->type = CU_NURBS; + + nu->bp = static_cast<BPoint *>(MEM_callocN(sizeof(BPoint) * nu->pntsu, "abc_getnurb")); + BPoint *bp = nu->bp; + + for (int j = 0; j < nu->pntsu; ++j, ++bp, ++idx) { + const Imath::V3f &pos = (*positions)[idx]; + + if (do_radius) { + radius = (*radiuses)[idx]; + } + + if (do_weights) { + weight = (*weights)[idx]; + } + + copy_yup_zup(bp->vec, pos.getValue()); + bp->vec[3] = weight; + bp->f1 = SELECT; + bp->radius = radius; + bp->weight = 1.0f; + } + + if (knots && knots->size() != 0) { + nu->knotsu = static_cast<float *>(MEM_callocN(KNOTSU(nu) * sizeof(float), "abc_setsplineknotsu")); + + /* TODO: second check is temporary, for until the check for cycles is rock solid. */ + if (periodicity == Alembic::AbcGeom::kPeriodic && (KNOTSU(nu) == knots->size() - 2)) { + /* Skip first and last knots. */ + for (size_t i = 1; i < knots->size() - 1; ++i) { + nu->knotsu[i - 1] = (*knots)[knot_offset + i]; + } + } + else { + /* TODO: figure out how to use the knots array from other + * software in this case. */ + BKE_nurb_knot_calc_u(nu); + } + + knot_offset += knots->size(); + } + else { + BKE_nurb_knot_calc_u(nu); + } + + BLI_addtail(BKE_curve_nurbs_get(cu), nu); + } +} diff --git a/source/blender/alembic/intern/abc_curves.h b/source/blender/alembic/intern/abc_curves.h new file mode 100644 index 00000000000..ee47f1931ea --- /dev/null +++ b/source/blender/alembic/intern/abc_curves.h @@ -0,0 +1,65 @@ +/* + * ***** 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) 2016 Kévin Dietrich. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef __ABC_CURVES_H__ +#define __ABC_CURVES_H__ + +#include "abc_object.h" + +struct Curve; + +/* ************************************************************************** */ + +class AbcCurveWriter : public AbcObjectWriter { + Alembic::AbcGeom::OCurvesSchema m_schema; + Alembic::AbcGeom::OCurvesSchema::Sample m_sample; + +public: + AbcCurveWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings); + + void do_write(); +}; + +/* ************************************************************************** */ + +class AbcCurveReader : public AbcObjectReader { + Alembic::AbcGeom::ICurvesSchema m_curves_schema; + +public: + AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettings &settings); + + bool valid() const; + + void readObjectData(Main *bmain, float time); +}; + +/* ************************************************************************** */ + +void read_curve_sample(Curve *cu, const Alembic::AbcGeom::ICurvesSchema &schema, const float time); + +#endif /* __ABC_CURVES_H__ */
\ No newline at end of file diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc new file mode 100644 index 00000000000..ebf1b2ba96e --- /dev/null +++ b/source/blender/alembic/intern/abc_customdata.cc @@ -0,0 +1,379 @@ +/* + * ***** 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) 2016 Kévin Dietrich. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include "abc_customdata.h" + +#include <Alembic/AbcGeom/All.h> +#include <algorithm> + +extern "C" { +#include "DNA_customdata_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_customdata.h" +} + +/* NOTE: for now only UVs and Vertex Colors are supported for streaming. + * Although Alembic only allows for a single UV layer per {I|O}Schema, and does + * not have a vertex color concept, there is a convention between DCCs to write + * such data in a way that lets other DCC know what they are for. See comments + * in the write code for the conventions. */ + +using Alembic::AbcGeom::kVertexScope; +using Alembic::AbcGeom::kFacevaryingScope; + +using Alembic::Abc::C4fArraySample; +using Alembic::Abc::UInt32ArraySample; +using Alembic::Abc::V2fArraySample; + +using Alembic::AbcGeom::OV2fGeomParam; +using Alembic::AbcGeom::OC4fGeomParam; + +static void get_uvs(const CDStreamConfig &config, + std::vector<Imath::V2f> &uvs, + std::vector<uint32_t> &uvidx, + void *cd_data) +{ + MLoopUV *mloopuv_array = static_cast<MLoopUV *>(cd_data); + + if (!mloopuv_array) { + return; + } + + const int num_poly = config.totpoly; + MPoly *polygons = config.mpoly; + + if (!config.pack_uvs) { + int cnt = 0; + uvidx.resize(config.totloop); + uvs.resize(config.totloop); + + for (int i = 0; i < num_poly; ++i) { + MPoly ¤t_poly = polygons[i]; + MLoopUV *loopuvpoly = mloopuv_array + current_poly.loopstart + current_poly.totloop; + + for (int j = 0; j < current_poly.totloop; ++j, ++cnt) { + --loopuvpoly; + + uvidx[cnt] = cnt; + uvs[cnt][0] = loopuvpoly->uv[0]; + uvs[cnt][1] = loopuvpoly->uv[1]; + } + } + } + else { + for (int i = 0; i < num_poly; ++i) { + MPoly ¤t_poly = polygons[i]; + MLoopUV *loopuvpoly = mloopuv_array + current_poly.loopstart + current_poly.totloop; + + for (int j = 0; j < current_poly.totloop; ++j) { + loopuvpoly--; + Imath::V2f uv(loopuvpoly->uv[0], loopuvpoly->uv[1]); + + std::vector<Imath::V2f>::iterator it = std::find(uvs.begin(), uvs.end(), uv); + + if (it == uvs.end()) { + uvidx.push_back(uvs.size()); + uvs.push_back(uv); + } + else { + uvidx.push_back(std::distance(uvs.begin(), it)); + } + } + } + } +} + +const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data) +{ + const int active_uvlayer = CustomData_get_active_layer(data, CD_MLOOPUV); + + if (active_uvlayer < 0) { + return ""; + } + + void *cd_data = CustomData_get_layer_n(data, CD_MLOOPUV, active_uvlayer); + + get_uvs(config, sample.uvs, sample.indices, cd_data); + + return CustomData_get_layer_name(data, CD_MLOOPUV, active_uvlayer); +} + +/* Convention to write UVs: + * - V2fGeomParam on the arbGeomParam + * - set scope as face varying + * - (optional due to its behaviour) tag as UV using Alembic::AbcGeom::SetIsUV + */ +static void write_uv(const OCompoundProperty &prop, const CDStreamConfig &config, void *data, const char *name) +{ + std::vector<uint32_t> indices; + std::vector<Imath::V2f> uvs; + + get_uvs(config, uvs, indices, data); + + if (indices.empty() || uvs.empty()) { + return; + } + + OV2fGeomParam param(prop, name, true, kFacevaryingScope, 1); + + OV2fGeomParam::Sample sample( + V2fArraySample(&uvs.front(), uvs.size()), + UInt32ArraySample(&indices.front(), indices.size()), + kFacevaryingScope); + + param.set(sample); +} + +/* Convention to write Vertex Colors: + * - C3fGeomParam/C4fGeomParam on the arbGeomParam + * - set scope as vertex varying + */ +static void write_mcol(const OCompoundProperty &prop, const CDStreamConfig &config, void *data, const char *name) +{ + const float cscale = 1.0f / 255.0f; + MPoly *polys = config.mpoly; + MLoop *mloops = config.mloop; + MCol *cfaces = static_cast<MCol *>(data); + + std::vector<Imath::C4f> buffer(config.totvert); + + Imath::C4f col; + + for (int i = 0; i < config.totpoly; ++i) { + MPoly *p = &polys[i]; + MCol *cface = &cfaces[p->loopstart + p->totloop]; + MLoop *mloop = &mloops[p->loopstart + p->totloop]; + + for (int j = 0; j < p->totloop; ++j) { + cface--; + mloop--; + + col[0] = cface->a * cscale; + col[1] = cface->r * cscale; + col[2] = cface->g * cscale; + col[3] = cface->b * cscale; + + buffer[mloop->v] = col; + } + } + + OC4fGeomParam param(prop, name, true, kFacevaryingScope, 1); + + OC4fGeomParam::Sample sample( + C4fArraySample(&buffer.front(), buffer.size()), + kVertexScope); + + param.set(sample); +} + +void write_custom_data(const OCompoundProperty &prop, const CDStreamConfig &config, CustomData *data, int data_type) +{ + CustomDataType cd_data_type = static_cast<CustomDataType>(data_type); + + if (!CustomData_has_layer(data, cd_data_type)) { + return; + } + + const int active_layer = CustomData_get_active_layer(data, cd_data_type); + const int tot_layers = CustomData_number_of_layers(data, cd_data_type); + + for (int i = 0; i < tot_layers; ++i) { + void *cd_data = CustomData_get_layer_n(data, cd_data_type, i); + const char *name = CustomData_get_layer_name(data, cd_data_type, i); + + if (cd_data_type == CD_MLOOPUV) { + /* Already exported. */ + if (i == active_layer) { + continue; + } + + write_uv(prop, config, cd_data, name); + } + else if (cd_data_type == CD_MLOOPCOL) { + write_mcol(prop, config, cd_data, name); + } + } +} + +/* ************************************************************************** */ + +using Alembic::Abc::C3fArraySamplePtr; +using Alembic::Abc::C4fArraySamplePtr; +using Alembic::Abc::PropertyHeader; + +using Alembic::AbcGeom::IC3fGeomParam; +using Alembic::AbcGeom::IC4fGeomParam; +using Alembic::AbcGeom::IV2fGeomParam; + +static void read_mcols(const CDStreamConfig &config, void *data, + const C3fArraySamplePtr &c3f_ptr, const C4fArraySamplePtr &c4f_ptr) +{ + MCol *cfaces = static_cast<MCol *>(data); + MPoly *polys = config.mpoly; + MLoop *mloops = config.mloop; + + if (c3f_ptr) { + for (int i = 0; i < config.totpoly; ++i) { + MPoly *p = &polys[i]; + MCol *cface = &cfaces[p->loopstart + p->totloop]; + MLoop *mloop = &mloops[p->loopstart + p->totloop]; + + for (int j = 0; j < p->totloop; ++j) { + cface--; + mloop--; + const Imath::C3f &color = (*c3f_ptr)[mloop->v]; + cface->a = FTOCHAR(color[0]); + cface->r = FTOCHAR(color[1]); + cface->g = FTOCHAR(color[2]); + cface->b = 255; + } + } + } + else if (c4f_ptr) { + for (int i = 0; i < config.totpoly; ++i) { + MPoly *p = &polys[i]; + MCol *cface = &cfaces[p->loopstart + p->totloop]; + MLoop *mloop = &mloops[p->loopstart + p->totloop]; + + for (int j = 0; j < p->totloop; ++j) { + cface--; + mloop--; + const Imath::C4f &color = (*c4f_ptr)[mloop->v]; + cface->a = FTOCHAR(color[0]); + cface->r = FTOCHAR(color[1]); + cface->g = FTOCHAR(color[2]); + cface->b = FTOCHAR(color[3]); + } + } + } +} + +static void read_uvs(const CDStreamConfig &config, void *data, + const Alembic::AbcGeom::V2fArraySamplePtr &uvs, + const Alembic::AbcGeom::UInt32ArraySamplePtr &indices) +{ + MPoly *mpolys = config.mpoly; + MLoopUV *mloopuvs = static_cast<MLoopUV *>(data); + + unsigned int uv_index, loop_index; + + for (int i = 0; i < config.totpoly; ++i) { + MPoly &poly = mpolys[i]; + + for (int f = 0; f < poly.totloop; ++f) { + loop_index = poly.loopstart + f; + uv_index = (*indices)[loop_index]; + const Imath::V2f &uv = (*uvs)[uv_index]; + + MLoopUV &loopuv = mloopuvs[loop_index]; + loopuv.uv[0] = uv[0]; + loopuv.uv[1] = uv[1]; + } + } +} + +static void read_custom_data_ex(const ICompoundProperty &prop, + const PropertyHeader &prop_header, + const CDStreamConfig &config, + const Alembic::Abc::ISampleSelector &iss, + int data_type) +{ + if (data_type == CD_MLOOPCOL) { + C3fArraySamplePtr c3f_ptr = C3fArraySamplePtr(); + C4fArraySamplePtr c4f_ptr = C4fArraySamplePtr(); + + if (IC3fGeomParam::matches(prop_header)) { + IC3fGeomParam color_param(prop, prop_header.getName()); + IC3fGeomParam::Sample sample; + color_param.getIndexed(sample, iss); + + c3f_ptr = sample.getVals(); + } + else if (IC4fGeomParam::matches(prop_header)) { + IC4fGeomParam color_param(prop, prop_header.getName()); + IC4fGeomParam::Sample sample; + color_param.getIndexed(sample, iss); + + c4f_ptr = sample.getVals(); + } + + void *cd_data = config.add_customdata_cb(config.user_data, + prop_header.getName().c_str(), + data_type); + + read_mcols(config, cd_data, c3f_ptr, c4f_ptr); + } + else if (data_type == CD_MLOOPUV) { + IV2fGeomParam uv_param(prop, prop_header.getName()); + IV2fGeomParam::Sample sample; + uv_param.getIndexed(sample, iss); + + if (uv_param.getScope() != kFacevaryingScope) { + return; + } + + void *cd_data = config.add_customdata_cb(config.user_data, + prop_header.getName().c_str(), + data_type); + + read_uvs(config, cd_data, sample.getVals(), sample.getIndices()); + } +} + +void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss) +{ + if (!prop.valid()) { + return; + } + + int num_uvs = 0; + int num_colors = 0; + + const size_t num_props = prop.getNumProperties(); + + for (size_t i = 0; i < num_props; ++i) { + const Alembic::Abc::PropertyHeader &prop_header = prop.getPropertyHeader(i); + + /* Read UVs according to convention. */ + if (IV2fGeomParam::matches(prop_header) && Alembic::AbcGeom::isUV(prop_header)) { + if (++num_uvs > MAX_MTFACE) { + continue; + } + + read_custom_data_ex(prop, prop_header, config, iss, CD_MLOOPUV); + continue; + } + + /* Read vertex colors according to convention. */ + if (IC3fGeomParam::matches(prop_header) || IC4fGeomParam::matches(prop_header)) { + if (++num_colors > MAX_MCOL) { + continue; + } + + read_custom_data_ex(prop, prop_header, config, iss, CD_MLOOPCOL); + continue; + } + } +} diff --git a/source/blender/alembic/intern/abc_customdata.h b/source/blender/alembic/intern/abc_customdata.h new file mode 100644 index 00000000000..3b16c0d9796 --- /dev/null +++ b/source/blender/alembic/intern/abc_customdata.h @@ -0,0 +1,93 @@ +/* + * ***** 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) 2016 Kévin Dietrich. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef __ABC_CUSTOMDATA_H__ +#define __ABC_CUSTOMDATA_H__ + +#include <Alembic/Abc/All.h> + +struct CustomData; +struct MLoop; +struct MLoopUV; +struct MPoly; +struct MVert; + +using Alembic::Abc::ICompoundProperty; +using Alembic::Abc::OCompoundProperty; + +struct UVSample { + std::vector<Imath::V2f> uvs; + std::vector<uint32_t> indices; +}; + +struct CDStreamConfig { + MLoop *mloop; + int totloop; + + MPoly *mpoly; + int totpoly; + + MVert *mvert; + int totvert; + + MLoopUV *mloopuv; + + CustomData *loopdata; + + bool pack_uvs; + + /* TODO(kevin): might need a better way to handle adding and/or updating + * custom datas such that it updates the custom data holder and its pointers + * properly. */ + void *user_data; + void *(*add_customdata_cb)(void *user_data, const char *name, int data_type); + + CDStreamConfig() + : mloop(NULL) + , totloop(0) + , mpoly(NULL) + , totpoly(0) + , totvert(0) + , pack_uvs(false) + , user_data(NULL) + , add_customdata_cb(NULL) + {} +}; + +/* Get the UVs for the main UV property on a OSchema. + * Returns the name of the UV layer. + * + * For now the active layer is used, maybe needs a better way to choose this. */ +const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data); + +void write_custom_data(const OCompoundProperty &prop, + const CDStreamConfig &config, + CustomData *data, + int data_type); + +void read_custom_data(const ICompoundProperty &prop, + const CDStreamConfig &config, + const Alembic::Abc::ISampleSelector &iss); + +#endif /* __ABC_CUSTOMDATA_H__ */ diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc new file mode 100644 index 00000000000..764b1533309 --- /dev/null +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -0,0 +1,654 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "abc_exporter.h" + +#include <cmath> + +#ifdef WITH_ALEMBIC_HDF5 +# include <Alembic/AbcCoreHDF5/All.h> +#endif + +#include <Alembic/AbcCoreOgawa/All.h> + +#ifdef WIN32 +# include "utfconv.h" +#endif + +#include "abc_camera.h" +#include "abc_curves.h" +#include "abc_hair.h" +#include "abc_mesh.h" +#include "abc_nurbs.h" +#include "abc_points.h" +#include "abc_transform.h" +#include "abc_util.h" + +extern "C" { +#include "DNA_camera_types.h" +#include "DNA_curve_types.h" +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" /* for FILE_MAX */ + +#include "BLI_string.h" + +#ifdef WIN32 +/* needed for MSCV because of snprintf from BLI_string */ +# include "BLI_winstuff.h" +#endif + +#include "BKE_anim.h" +#include "BKE_global.h" +#include "BKE_idprop.h" +#include "BKE_main.h" +#include "BKE_modifier.h" +#include "BKE_particle.h" +#include "BKE_scene.h" +} + +using Alembic::Abc::TimeSamplingPtr; +using Alembic::Abc::OBox3dProperty; + + +/* ************************************************************************** */ + +/* This kinda duplicates CreateArchiveWithInfo, but Alembic does not seem to + * have a version supporting streams. */ +static Alembic::Abc::OArchive create_archive(std::ostream *ostream, + const std::string &filename, + const std::string &scene_name, + const Alembic::Abc::Argument &arg0, + const Alembic::Abc::Argument &arg1, + bool ogawa) +{ + Alembic::Abc::MetaData md = GetMetaData(arg0, arg1); + md.set(Alembic::Abc::kApplicationNameKey, "Blender"); + md.set(Alembic::Abc::kUserDescriptionKey, scene_name); + + time_t raw_time; + time(&raw_time); + char buffer[128]; + +#if defined _WIN32 || defined _WIN64 + ctime_s(buffer, 128, &raw_time); +#else + ctime_r(&raw_time, buffer); +#endif + + const std::size_t buffer_len = strlen(buffer); + if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') { + buffer[buffer_len - 1] = '\0'; + } + + md.set(Alembic::Abc::kDateWrittenKey, buffer); + + Alembic::Abc::ErrorHandler::Policy policy = GetErrorHandlerPolicyFromArgs(arg0, arg1); + +#ifdef WITH_ALEMBIC_HDF5 + if (!ogawa) { + return Alembic::Abc::OArchive(Alembic::AbcCoreHDF5::WriteArchive(), filename, md, policy); + } +#else + static_cast<void>(filename); + static_cast<void>(ogawa); +#endif + + Alembic::AbcCoreOgawa::WriteArchive archive_writer; + return Alembic::Abc::OArchive(archive_writer(ostream, md), Alembic::Abc::kWrapExisting, policy); +} + +/* ************************************************************************** */ + +ExportSettings::ExportSettings() + : scene(NULL) + , selected_only(false) + , visible_layers_only(false) + , renderable_only(false) + , frame_start(1) + , frame_end(1) + , frame_step_xform(1) + , frame_step_shape(1) + , shutter_open(0.0) + , shutter_close(1.0) + , global_scale(1.0f) + , flatten_hierarchy(false) + , export_normals(false) + , export_uvs(false) + , export_vcols(false) + , export_face_sets(false) + , export_vweigths(false) + , apply_subdiv(false) + , use_subdiv_schema(false) + , export_child_hairs(true) + , export_ogawa(true) + , pack_uv(false) + , do_convert_axis(false) +{} + +static bool object_is_smoke_sim(Object *ob) +{ + ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke); + + if (md) { + SmokeModifierData *smd = reinterpret_cast<SmokeModifierData *>(md); + return (smd->type == MOD_SMOKE_TYPE_DOMAIN); + } + + return false; +} + +static bool object_is_shape(Object *ob) +{ + switch (ob->type) { + case OB_MESH: + if (object_is_smoke_sim(ob)) { + return false; + } + + return true; + case OB_CURVE: + case OB_SURF: + case OB_CAMERA: + return true; + default: + return false; + } +} + +static bool export_object(const ExportSettings * const settings, Object *ob) +{ + if (settings->selected_only && !parent_selected(ob)) { + return false; + } + + if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) { + return false; + } + + if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) { + return false; + } + + return true; +} + +/* ************************************************************************** */ + +AbcExporter::AbcExporter(Scene *scene, const char *filename, ExportSettings &settings) + : m_settings(settings) + , m_filename(filename) + , m_trans_sampling_index(0) + , m_shape_sampling_index(0) + , m_scene(scene) +{} + +AbcExporter::~AbcExporter() +{ + std::map<std::string, AbcTransformWriter*>::iterator it, e; + for (it = m_xforms.begin(), e = m_xforms.end(); it != e; ++it) { + delete it->second; + } + + for (int i = 0, e = m_shapes.size(); i != e; ++i) { + delete m_shapes[i]; + } +} + +void AbcExporter::getShutterSamples(double step, bool time_relative, + std::vector<double> &samples) +{ + samples.clear(); + + const double time_factor = time_relative ? m_scene->r.frs_sec : 1.0; + const double shutter_open = m_settings.shutter_open; + const double shutter_close = m_settings.shutter_close; + + /* sample all frame */ + if (shutter_open == 0.0 && shutter_close == 1.0) { + for (double t = 0; t < 1.0; t += step) { + samples.push_back((t + m_settings.frame_start) / time_factor); + } + } + else { + /* sample between shutter open & close */ + const int nsamples = std::max((1.0 / step) - 1.0, 1.0); + const double time_inc = (shutter_close - shutter_open) / nsamples; + + for (double t = shutter_open; t <= shutter_close; t += time_inc) { + samples.push_back((t + m_settings.frame_start) / time_factor); + } + } +} + +Alembic::Abc::TimeSamplingPtr AbcExporter::createTimeSampling(double step) +{ + TimeSamplingPtr time_sampling; + std::vector<double> samples; + + if (m_settings.frame_start == m_settings.frame_end) { + time_sampling.reset(new Alembic::Abc::TimeSampling()); + return time_sampling; + } + + getShutterSamples(step, true, samples); + + Alembic::Abc::TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / m_scene->r.frs_sec); + time_sampling.reset(new Alembic::Abc::TimeSampling(ts, samples)); + + return time_sampling; +} + +void AbcExporter::getFrameSet(double step, std::set<double> &frames) +{ + frames.clear(); + + std::vector<double> shutter_samples; + + getShutterSamples(step, false, shutter_samples); + + for (int frame = m_settings.frame_start; frame <= m_settings.frame_end; ++frame) { + for (int j = 0, e = shutter_samples.size(); j < e; ++j) { + frames.insert(frame + shutter_samples[j]); + } + } +} + +void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) +{ + std::string scene_name; + + if (bmain->name[0] != '\0') { + char scene_file_name[FILE_MAX]; + BLI_strncpy(scene_file_name, bmain->name, FILE_MAX); + scene_name = scene_file_name; + } + else { + scene_name = "untitled"; + } + + Scene *scene = m_scene; + const int fps = FPS; + char buf[16]; + snprintf(buf, 15, "%d", fps); + const std::string str_fps = buf; + + Alembic::AbcCoreAbstract::MetaData md; + md.set("FramesPerTimeUnit", str_fps); + + Alembic::Abc::Argument arg(md); + + /* Use stream to support unicode character paths on Windows. */ + if (m_settings.export_ogawa) { +#ifdef WIN32 + UTF16_ENCODE(m_filename); + std::wstring wstr(m_filename_16); + m_out_file.open(wstr.c_str(), std::ios::out | std::ios::binary); + UTF16_UN_ENCODE(m_filename); +#else + m_out_file.open(m_filename, std::ios::out | std::ios::binary); +#endif + } + + m_archive = create_archive(&m_out_file, + m_filename, + scene_name, + Alembic::Abc::ErrorHandler::kThrowPolicy, + arg, + m_settings.export_ogawa); + + /* Create time samplings for transforms and shapes. */ + + TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform); + + m_trans_sampling_index = m_archive.addTimeSampling(*trans_time); + + TimeSamplingPtr shape_time; + + if ((m_settings.frame_step_shape == m_settings.frame_step_xform) || + (m_settings.frame_start == m_settings.frame_end)) + { + shape_time = trans_time; + m_shape_sampling_index = m_trans_sampling_index; + } + else { + shape_time = createTimeSampling(m_settings.frame_step_shape); + m_shape_sampling_index = m_archive.addTimeSampling(*shape_time); + } + + OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_archive, m_trans_sampling_index); + + if (m_settings.flatten_hierarchy) { + createTransformWritersFlat(); + } + else { + createTransformWritersHierarchy(bmain->eval_ctx); + } + + createShapeWriters(bmain->eval_ctx); + + /* Make a list of frames to export. */ + + std::set<double> xform_frames; + getFrameSet(m_settings.frame_step_xform, xform_frames); + + std::set<double> shape_frames; + getFrameSet(m_settings.frame_step_shape, shape_frames); + + /* Merge all frames needed. */ + + std::set<double> frames(xform_frames); + frames.insert(shape_frames.begin(), shape_frames.end()); + + /* Export all frames. */ + + std::set<double>::const_iterator begin = frames.begin(); + std::set<double>::const_iterator end = frames.end(); + + const float size = static_cast<float>(frames.size()); + size_t i = 0; + + for (; begin != end; ++begin) { + progress = (++i / size); + + if (G.is_break) { + was_canceled = true; + break; + } + + const double frame = *begin; + + /* 'frame' is offset by start frame, so need to cancel the offset. */ + setCurrentFrame(bmain, frame - m_settings.frame_start); + + if (shape_frames.count(frame) != 0) { + for (int i = 0, e = m_shapes.size(); i != e; ++i) { + m_shapes[i]->write(); + } + } + + if (xform_frames.count(frame) == 0) { + continue; + } + + std::map<std::string, AbcTransformWriter *>::iterator xit, xe; + for (xit = m_xforms.begin(), xe = m_xforms.end(); xit != xe; ++xit) { + xit->second->write(); + } + + /* Save the archive 's bounding box. */ + Imath::Box3d bounds; + + for (xit = m_xforms.begin(), xe = m_xforms.end(); xit != xe; ++xit) { + Imath::Box3d box = xit->second->bounds(); + bounds.extendBy(box); + } + + archive_bounds_prop.set(bounds); + } +} + +void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx) +{ + Base *base = static_cast<Base *>(m_scene->base.first); + + while (base) { + Object *ob = base->object; + + if (export_object(&m_settings, ob)) { + switch(ob->type) { + case OB_LAMP: + case OB_LATTICE: + case OB_MBALL: + case OB_SPEAKER: + /* We do not export transforms for objects of these classes. */ + break; + + default: + exploreTransform(eval_ctx, ob, ob->parent, NULL); + } + } + + base = base->next; + } +} + +void AbcExporter::createTransformWritersFlat() +{ + Base *base = static_cast<Base *>(m_scene->base.first); + + while (base) { + Object *ob = base->object; + + if (export_object(&m_settings, ob) && object_is_shape(ob)) { + std::string name = get_id_name(ob); + m_xforms[name] = new AbcTransformWriter(ob, m_archive.getTop(), 0, m_trans_sampling_index, m_settings); + } + + base = base->next; + } +} + +void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent) +{ + createTransformWriter(ob, parent, dupliObParent); + + ListBase *lb = object_duplilist(eval_ctx, m_scene, ob); + + if (lb) { + DupliObject *link = static_cast<DupliObject *>(lb->first); + Object *dupli_ob = NULL; + Object *dupli_parent = NULL; + + while (link) { + if (link->type == OB_DUPLIGROUP) { + dupli_ob = link->ob; + dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob; + + exploreTransform(eval_ctx, dupli_ob, dupli_parent, ob); + } + + link = link->next; + } + } + + free_object_duplilist(lb); +} + +void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent) +{ + const std::string name = get_object_dag_path_name(ob, dupliObParent); + + /* check if we have already created a transform writer for this object */ + if (m_xforms.find(name) != m_xforms.end()){ + std::cerr << "xform " << name << " already exists\n"; + return; + } + + AbcTransformWriter *parent_xform = NULL; + + if (parent) { + const std::string parentname = get_object_dag_path_name(parent, dupliObParent); + parent_xform = getXForm(parentname); + + if (!parent_xform) { + if (parent->parent) { + createTransformWriter(parent, parent->parent, dupliObParent); + } + else { + createTransformWriter(parent, dupliObParent, dupliObParent); + } + + parent_xform = getXForm(parentname); + } + } + + if (parent_xform) { + m_xforms[name] = new AbcTransformWriter(ob, parent_xform->alembicXform(), parent_xform, m_trans_sampling_index, m_settings); + m_xforms[name]->setParent(parent); + } + else { + m_xforms[name] = new AbcTransformWriter(ob, m_archive.getTop(), NULL, m_trans_sampling_index, m_settings); + } +} + +void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx) +{ + Base *base = static_cast<Base *>(m_scene->base.first); + + while (base) { + Object *ob = base->object; + exploreObject(eval_ctx, ob, NULL); + + base = base->next; + } +} + +void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent) +{ + ListBase *lb = object_duplilist(eval_ctx, m_scene, ob); + + createShapeWriter(ob, dupliObParent); + + if (lb) { + DupliObject *dupliob = static_cast<DupliObject *>(lb->first); + + while (dupliob) { + if (dupliob->type == OB_DUPLIGROUP) { + exploreObject(eval_ctx, dupliob->ob, ob); + } + + dupliob = dupliob->next; + } + } + + free_object_duplilist(lb); +} + +void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent) +{ + if (!object_is_shape(ob)) { + return; + } + + if (!export_object(&m_settings, ob)) { + return; + } + + std::string name; + + if (m_settings.flatten_hierarchy) { + name = get_id_name(ob); + } + else { + name = get_object_dag_path_name(ob, dupliObParent); + } + + AbcTransformWriter *xform = getXForm(name); + + if (!xform) { + std::cerr << __func__ << ": xform " << name << " is NULL\n"; + return; + } + + ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first); + + for (; psys; psys = psys->next) { + if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) { + continue; + } + + if (psys->part->type == PART_HAIR) { + m_settings.export_child_hairs = true; + m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys)); + } + else if (psys->part->type == PART_EMITTER) { + m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys)); + } + } + + switch(ob->type) { + case OB_MESH: + { + Mesh *me = static_cast<Mesh *>(ob->data); + + if (!me || me->totvert == 0) { + return; + } + + m_shapes.push_back(new AbcMeshWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings)); + break; + } + case OB_SURF: + { + Curve *cu = static_cast<Curve *>(ob->data); + + if (!cu) { + return; + } + + m_shapes.push_back(new AbcNurbsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings)); + break; + } + case OB_CURVE: + { + Curve *cu = static_cast<Curve *>(ob->data); + + if (!cu) { + return; + } + + m_shapes.push_back(new AbcCurveWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings)); + break; + } + case OB_CAMERA: + { + Camera *cam = static_cast<Camera *>(ob->data); + + if (cam->type == CAM_PERSP) { + m_shapes.push_back(new AbcCameraWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings)); + } + + break; + } + } +} + +AbcTransformWriter *AbcExporter::getXForm(const std::string &name) +{ + std::map<std::string, AbcTransformWriter *>::iterator it = m_xforms.find(name); + + if (it == m_xforms.end()) { + return NULL; + } + + return it->second; +} + +void AbcExporter::setCurrentFrame(Main *bmain, double t) +{ + m_scene->r.cfra = std::floor(t); + m_scene->r.subframe = t - m_scene->r.cfra; + BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, m_scene, m_scene->lay); +} diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h new file mode 100644 index 00000000000..6c242f973c4 --- /dev/null +++ b/source/blender/alembic/intern/abc_exporter.h @@ -0,0 +1,114 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_EXPORTER_H__ +#define __ABC_EXPORTER_H__ + +#include <Alembic/Abc/All.h> +#include <fstream> +#include <map> +#include <set> +#include <vector> + +class AbcObjectWriter; +class AbcTransformWriter; + +struct EvaluationContext; +struct Main; +struct Object; +struct Scene; + +struct ExportSettings { + ExportSettings(); + + Scene *scene; + + bool selected_only; + bool visible_layers_only; + bool renderable_only; + + double frame_start, frame_end; + double frame_step_xform; + double frame_step_shape; + double shutter_open; + double shutter_close; + float global_scale; + + bool flatten_hierarchy; + + bool export_normals; + bool export_uvs; + bool export_vcols; + bool export_face_sets; + bool export_vweigths; + + bool apply_subdiv; + bool use_subdiv_schema; + bool export_child_hairs; + bool export_ogawa; + bool pack_uv; + + bool do_convert_axis; + float convert_matrix[3][3]; +}; + +class AbcExporter { + ExportSettings &m_settings; + + const char *m_filename; + + std::ofstream m_out_file; + Alembic::Abc::OArchive m_archive; + unsigned int m_trans_sampling_index, m_shape_sampling_index; + + Scene *m_scene; + + std::map<std::string, AbcTransformWriter *> m_xforms; + std::vector<AbcObjectWriter *> m_shapes; + +public: + AbcExporter(Scene *scene, const char *filename, ExportSettings &settings); + ~AbcExporter(); + + void operator()(Main *bmain, float &progress, bool &was_canceled); + +private: + void getShutterSamples(double step, bool time_relative, std::vector<double> &samples); + + Alembic::Abc::TimeSamplingPtr createTimeSampling(double step); + + void getFrameSet(double step, std::set<double> &frames); + + void createTransformWritersHierarchy(EvaluationContext *eval_ctx); + void createTransformWritersFlat(); + void createTransformWriter(Object *ob, Object *parent, Object *dupliObParent); + void exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent = NULL); + void exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent); + void createShapeWriters(EvaluationContext *eval_ctx); + void createShapeWriter(Object *ob, Object *dupliObParent); + + AbcTransformWriter *getXForm(const std::string &name); + + void setCurrentFrame(Main *bmain, double t); +}; + +#endif /* __ABC_EXPORTER_H__ */ diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc new file mode 100644 index 00000000000..45bf9b7ab8a --- /dev/null +++ b/source/blender/alembic/intern/abc_hair.cc @@ -0,0 +1,290 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "abc_hair.h" + +#include <cstdio> + +#include "abc_transform.h" +#include "abc_util.h" + +extern "C" { +#include "MEM_guardedalloc.h" + +#include "DNA_modifier_types.h" + +#include "BLI_listbase.h" +#include "BLI_math_geom.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_object.h" +#include "BKE_particle.h" +} + +using Alembic::Abc::P3fArraySamplePtr; + +using Alembic::AbcGeom::OCurves; +using Alembic::AbcGeom::OCurvesSchema; +using Alembic::AbcGeom::ON3fGeomParam; +using Alembic::AbcGeom::OV2fGeomParam; + +/* ************************************************************************** */ + +AbcHairWriter::AbcHairWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings, + ParticleSystem *psys) + : AbcObjectWriter(scene, ob, time_sampling, settings, parent) +{ + m_psys = psys; + + OCurves curves(parent->alembicXform(), m_name, m_time_sampling); + m_schema = curves.getSchema(); +} + +void AbcHairWriter::do_write() +{ + if (!m_psys) { + return; + } + + ParticleSystemModifierData *psmd = psys_get_modifier(m_object, m_psys); + + if (!psmd->dm_final) { + return; + } + + DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH); + DM_ensure_tessface(dm); + DM_update_tessface_data(dm); + + std::vector<Imath::V3f> verts; + std::vector<int32_t> hvertices; + std::vector<Imath::V2f> uv_values; + std::vector<Imath::V3f> norm_values; + + if (m_psys->pathcache) { + ParticleSettings *part = m_psys->part; + + write_hair_sample(dm, part, verts, norm_values, uv_values, hvertices); + + if (m_settings.export_child_hairs && m_psys->childcache) { + write_hair_child_sample(dm, part, verts, norm_values, uv_values, hvertices); + } + } + + dm->release(dm); + + Alembic::Abc::P3fArraySample iPos(verts); + m_sample = OCurvesSchema::Sample(iPos, hvertices); + m_sample.setBasis(Alembic::AbcGeom::kNoBasis); + m_sample.setType(Alembic::AbcGeom::kLinear); + m_sample.setWrap(Alembic::AbcGeom::kNonPeriodic); + + if (!uv_values.empty()) { + OV2fGeomParam::Sample uv_smp; + uv_smp.setVals(uv_values); + m_sample.setUVs(uv_smp); + } + + if (!norm_values.empty()) { + ON3fGeomParam::Sample norm_smp; + norm_smp.setVals(norm_values); + m_sample.setNormals(norm_smp); + } + + m_sample.setSelfBounds(bounds()); + m_schema.set(m_sample); +} + +void AbcHairWriter::write_hair_sample(DerivedMesh *dm, + ParticleSettings *part, + std::vector<Imath::V3f> &verts, + std::vector<Imath::V3f> &norm_values, + std::vector<Imath::V2f> &uv_values, + std::vector<int32_t> &hvertices) +{ + /* Get untransformed vertices, there's a xform under the hair. */ + float inv_mat[4][4]; + invert_m4_m4_safe(inv_mat, m_object->obmat); + + MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer(&dm->faceData, CD_MTFACE)); + MFace *mface = dm->getTessFaceArray(dm); + MVert *mverts = dm->getVertArray(dm); + + if (!mtface || !mface) { + std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n"); + } + + ParticleData * pa = m_psys->particles; + int k; + + ParticleCacheKey **cache = m_psys->pathcache; + ParticleCacheKey *path; + float normal[3]; + Imath::V3f tmp_nor; + + for (int p = 0; p < m_psys->totpart; ++p, ++pa) { + /* underlying info for faces-only emission */ + path = cache[p]; + + if (part->from == PART_FROM_FACE && mtface) { + const int num = pa->num_dmcache >= 0 ? pa->num_dmcache : pa->num; + + if (num < dm->getNumTessFaces(dm)) { + MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE)); + MTFace *tface = mtface + num; + + if (mface) { + float r_uv[2], mapfw[4], vec[3]; + + psys_interpolate_uvs(tface, face->v4, pa->fuv, r_uv); + uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1])); + + psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, normal, NULL, NULL, NULL, NULL); + + copy_zup_yup(tmp_nor.getValue(), normal); + norm_values.push_back(tmp_nor); + } + } + else { + std::fprintf(stderr, "Particle to faces overflow (%d/%d)\n", num, dm->getNumTessFaces(dm)); + } + } + else if (part->from == PART_FROM_VERT && mtface) { + /* vertex id */ + const int num = (pa->num_dmcache >= 0) ? pa->num_dmcache : pa->num; + + /* iterate over all faces to find a corresponding underlying UV */ + for (int n = 0; n < dm->getNumTessFaces(dm); ++n) { + MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, n, CD_MFACE)); + MTFace *tface = mtface + n; + unsigned int vtx[4]; + vtx[0] = face->v1; + vtx[1] = face->v2; + vtx[2] = face->v3; + vtx[3] = face->v4; + bool found = false; + + for (int o = 0; o < 4; ++o) { + if (o > 2 && vtx[o] == 0) { + break; + } + + if (vtx[o] == num) { + uv_values.push_back(Imath::V2f(tface->uv[o][0], tface->uv[o][1])); + + MVert *mv = mverts + vtx[o]; + + normal_short_to_float_v3(normal, mv->no); + copy_zup_yup(tmp_nor.getValue(), normal); + norm_values.push_back(tmp_nor); + found = true; + break; + } + } + + if (found) { + break; + } + } + } + + int steps = path->segments + 1; + hvertices.push_back(steps); + + for (k = 0; k < steps; ++k) { + float vert[3]; + copy_v3_v3(vert, path->co); + mul_m4_v3(inv_mat, vert); + + /* Convert Z-up to Y-up. */ + verts.push_back(Imath::V3f(vert[0], vert[2], -vert[1])); + + ++path; + } + } +} + +void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm, + ParticleSettings *part, + std::vector<Imath::V3f> &verts, + std::vector<Imath::V3f> &norm_values, + std::vector<Imath::V2f> &uv_values, + std::vector<int32_t> &hvertices) +{ + /* Get untransformed vertices, there's a xform under the hair. */ + float inv_mat[4][4]; + invert_m4_m4_safe(inv_mat, m_object->obmat); + + MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer(&dm->faceData, CD_MTFACE)); + MFace *mface = dm->getTessFaceArray(dm); + MVert *mverts = dm->getVertArray(dm); + + if (!mtface || !mface) { + std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n"); + } + + ParticleCacheKey **cache = m_psys->childcache; + ParticleCacheKey *path; + + ChildParticle *pc = m_psys->child; + + for (int p = 0; p < m_psys->totchild; ++p, ++pc) { + path = cache[p]; + + if (part->from == PART_FROM_FACE) { + const int num = pc->num; + + MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE)); + MTFace *tface = mtface + num; + + if (mface && mtface) { + float r_uv[2], tmpnor[3], mapfw[4], vec[3]; + + psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv); + uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1])); + + psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, tmpnor, NULL, NULL, NULL, NULL); + + /* Convert Z-up to Y-up. */ + norm_values.push_back(Imath::V3f(tmpnor[0], tmpnor[2], -tmpnor[1])); + } + } + + int steps = path->segments + 1; + hvertices.push_back(steps); + + for (int k = 0; k < steps; ++k) { + float vert[3]; + copy_v3_v3(vert, path->co); + mul_m4_v3(inv_mat, vert); + + /* Convert Z-up to Y-up. */ + verts.push_back(Imath::V3f(vert[0], vert[2], -vert[1])); + + ++path; + } + } +} diff --git a/source/blender/alembic/intern/abc_hair.h b/source/blender/alembic/intern/abc_hair.h new file mode 100644 index 00000000000..d132b60be12 --- /dev/null +++ b/source/blender/alembic/intern/abc_hair.h @@ -0,0 +1,66 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_HAIR_H__ +#define __ABC_HAIR_H__ + +#include "abc_object.h" + +struct DerivedMesh; +struct ParticleSettings; +struct ParticleSystem; + +/* ************************************************************************** */ + +class AbcHairWriter : public AbcObjectWriter { + ParticleSystem *m_psys; + + Alembic::AbcGeom::OCurvesSchema m_schema; + Alembic::AbcGeom::OCurvesSchema::Sample m_sample; + +public: + AbcHairWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings, + ParticleSystem *psys); + +private: + virtual void do_write(); + + void write_hair_sample(DerivedMesh *dm, + ParticleSettings *part, + std::vector<Imath::V3f> &verts, + std::vector<Imath::V3f> &norm_values, + std::vector<Imath::V2f> &uv_values, + std::vector<int32_t> &hvertices); + + void write_hair_child_sample(DerivedMesh *dm, + ParticleSettings *part, + std::vector<Imath::V3f> &verts, + std::vector<Imath::V3f> &norm_values, + std::vector<Imath::V2f> &uv_values, + std::vector<int32_t> &hvertices); +}; + +#endif /* __ABC_HAIR_H__ */ diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc new file mode 100644 index 00000000000..b80b7c0c4c8 --- /dev/null +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -0,0 +1,1215 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "abc_mesh.h" + +#include <algorithm> + +#include "abc_transform.h" +#include "abc_util.h" + +extern "C" { +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_fluidsim.h" +#include "DNA_object_types.h" + +#include "BLI_math_geom.h" +#include "BLI_string.h" + +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_object.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_mesh.h" +} + +using Alembic::Abc::FloatArraySample; +using Alembic::Abc::ICompoundProperty; +using Alembic::Abc::Int32ArraySample; +using Alembic::Abc::Int32ArraySamplePtr; +using Alembic::Abc::P3fArraySamplePtr; +using Alembic::Abc::V2fArraySample; +using Alembic::Abc::V3fArraySample; +using Alembic::Abc::C4fArraySample; + +using Alembic::AbcGeom::IFaceSet; +using Alembic::AbcGeom::IFaceSetSchema; +using Alembic::AbcGeom::IObject; +using Alembic::AbcGeom::IPolyMesh; +using Alembic::AbcGeom::IPolyMeshSchema; +using Alembic::AbcGeom::ISampleSelector; +using Alembic::AbcGeom::ISubD; +using Alembic::AbcGeom::ISubDSchema; +using Alembic::AbcGeom::IV2fGeomParam; + +using Alembic::AbcGeom::OArrayProperty; +using Alembic::AbcGeom::OBoolProperty; +using Alembic::AbcGeom::OC3fArrayProperty; +using Alembic::AbcGeom::OC3fGeomParam; +using Alembic::AbcGeom::OC4fGeomParam; +using Alembic::AbcGeom::OCompoundProperty; +using Alembic::AbcGeom::OFaceSet; +using Alembic::AbcGeom::OFaceSetSchema; +using Alembic::AbcGeom::OFloatGeomParam; +using Alembic::AbcGeom::OInt32GeomParam; +using Alembic::AbcGeom::ON3fArrayProperty; +using Alembic::AbcGeom::ON3fGeomParam; +using Alembic::AbcGeom::OPolyMesh; +using Alembic::AbcGeom::OPolyMeshSchema; +using Alembic::AbcGeom::OSubD; +using Alembic::AbcGeom::OSubDSchema; +using Alembic::AbcGeom::OV2fGeomParam; +using Alembic::AbcGeom::OV3fGeomParam; + +using Alembic::AbcGeom::kFacevaryingScope; +using Alembic::AbcGeom::kVaryingScope; +using Alembic::AbcGeom::kVertexScope; +using Alembic::AbcGeom::kWrapExisting; +using Alembic::AbcGeom::UInt32ArraySample; +using Alembic::AbcGeom::N3fArraySamplePtr; +using Alembic::AbcGeom::IN3fGeomParam; + +/* ************************************************************************** */ + +/* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */ + +static void get_vertices(DerivedMesh *dm, std::vector<Imath::V3f> &points) +{ + points.clear(); + points.resize(dm->getNumVerts(dm)); + + MVert *verts = dm->getVertArray(dm); + + for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) { + copy_zup_yup(points[i].getValue(), verts[i].co); + } +} + +static void get_topology(DerivedMesh *dm, + std::vector<int32_t> &poly_verts, + std::vector<int32_t> &loop_counts, + bool &smooth_normal) +{ + const int num_poly = dm->getNumPolys(dm); + const int num_loops = dm->getNumLoops(dm); + MLoop *mloop = dm->getLoopArray(dm); + MPoly *mpoly = dm->getPolyArray(dm); + + poly_verts.clear(); + loop_counts.clear(); + poly_verts.reserve(num_loops); + loop_counts.reserve(num_poly); + + /* NOTE: data needs to be written in the reverse order. */ + for (int i = 0; i < num_poly; ++i) { + MPoly &poly = mpoly[i]; + loop_counts.push_back(poly.totloop); + + smooth_normal |= ((poly.flag & ME_SMOOTH) != 0); + + MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1); + + for (int j = 0; j < poly.totloop; ++j, --loop) { + poly_verts.push_back(loop->v); + } + } +} + +static void get_material_indices(DerivedMesh *dm, std::vector<int32_t> &indices) +{ + indices.clear(); + indices.reserve(dm->getNumTessFaces(dm)); + + MPoly *mpolys = dm->getPolyArray(dm); + + for (int i = 1, e = dm->getNumPolys(dm); i < e; ++i) { + MPoly *mpoly = &mpolys[i]; + indices.push_back(mpoly->mat_nr); + } +} + +static void get_creases(DerivedMesh *dm, + std::vector<int32_t> &indices, + std::vector<int32_t> &lengths, + std::vector<float> &sharpnesses) +{ + const float factor = 1.0f / 255.0f; + + indices.clear(); + lengths.clear(); + sharpnesses.clear(); + + MEdge *edge = dm->getEdgeArray(dm); + + for (int i = 0, e = dm->getNumEdges(dm); i < e; ++i) { + const float sharpness = static_cast<float>(edge[i].crease) * factor; + + if (sharpness != 0.0f) { + indices.push_back(edge[i].v1); + indices.push_back(edge[i].v2); + sharpnesses.push_back(sharpness); + } + } + + lengths.resize(sharpnesses.size(), 2); +} + +static void get_vertex_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals) +{ + normals.clear(); + normals.resize(dm->getNumVerts(dm)); + + MVert *verts = dm->getVertArray(dm); + float no[3]; + + for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) { + normal_short_to_float_v3(no, verts[i].no); + copy_zup_yup(normals[i].getValue(), no); + } +} + +static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals) +{ + MPoly *mpoly = dm->getPolyArray(dm); + MPoly *mp = mpoly; + + MLoop *mloop = dm->getLoopArray(dm); + MLoop *ml = mloop; + + MVert *verts = dm->getVertArray(dm); + + const float (*lnors)[3] = static_cast<float(*)[3]>(dm->getLoopDataArray(dm, CD_NORMAL)); + + normals.clear(); + normals.resize(dm->getNumLoops(dm)); + + unsigned loop_index = 0; + + /* NOTE: data needs to be written in the reverse order. */ + + if (lnors) { + for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i, ++mp) { + ml = mloop + mp->loopstart + (mp->totloop - 1); + + for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { + const int index = ml->v; + copy_zup_yup(normals[loop_index].getValue(), lnors[index]); + } + } + } + else { + float no[3]; + + for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i, ++mp) { + ml = mloop + mp->loopstart + (mp->totloop - 1); + + /* Flat shaded, use common normal for all verts. */ + if ((mp->flag & ME_SMOOTH) == 0) { + BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no); + + for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { + copy_zup_yup(normals[loop_index].getValue(), no); + } + } + else { + /* Smooth shaded, use individual vert normals. */ + for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { + normal_short_to_float_v3(no, verts[ml->v].no); + copy_zup_yup(normals[loop_index].getValue(), no); + } + } + } + } +} + +/* *************** Modifiers *************** */ + +/* check if the mesh is a subsurf, ignoring disabled modifiers and + * displace if it's after subsurf. */ +static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob) +{ + ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last); + + for (; md; md = md->prev) { + if (!modifier_isEnabled(scene, md, eModifierMode_Render)) { + continue; + } + + if (md->type == eModifierType_Subsurf) { + SubsurfModifierData *smd = reinterpret_cast<SubsurfModifierData*>(md); + + if (smd->subdivType == ME_CC_SUBSURF) { + return md; + } + } + + /* mesh is not a subsurf. break */ + if ((md->type != eModifierType_Displace) && (md->type != eModifierType_ParticleSystem)) { + return NULL; + } + } + + return NULL; +} + +static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob) +{ + ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim); + + if (md && (modifier_isEnabled(scene, md, eModifierMode_Render))) { + FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md); + + if (fsmd->fss && fsmd->fss->type == OB_FLUIDSIM_DOMAIN) { + return md; + } + } + + return NULL; +} + +/* ************************************************************************** */ + +AbcMeshWriter::AbcMeshWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings) + : AbcObjectWriter(scene, ob, time_sampling, settings, parent) +{ + m_is_animated = isAnimated(); + m_subsurf_mod = NULL; + m_has_per_face_materials = false; + m_is_subd = false; + + /* If the object is static, use the default static time sampling. */ + if (!m_is_animated) { + time_sampling = 0; + } + + if (!m_settings.apply_subdiv) { + m_subsurf_mod = get_subsurf_modifier(m_scene, m_object); + m_is_subd = (m_subsurf_mod != NULL); + } + + m_is_liquid = (get_liquid_sim_modifier(m_scene, m_object) != NULL); + + while (parent->alembicXform().getChildHeader(m_name)) { + m_name.append("_"); + } + + if (m_settings.use_subdiv_schema && m_is_subd) { + OSubD subd(parent->alembicXform(), m_name, m_time_sampling); + m_subdiv_schema = subd.getSchema(); + } + else { + OPolyMesh mesh(parent->alembicXform(), m_name, m_time_sampling); + m_mesh_schema = mesh.getSchema(); + + OCompoundProperty typeContainer = m_mesh_schema.getUserProperties(); + OBoolProperty type(typeContainer, "meshtype"); + type.set(m_is_subd); + } +} + +AbcMeshWriter::~AbcMeshWriter() +{ + if (m_subsurf_mod) { + m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary; + } +} + +bool AbcMeshWriter::isAnimated() const +{ + /* Check if object has shape keys. */ + Mesh *me = static_cast<Mesh *>(m_object->data); + + if (me->key) { + return true; + } + + /* Test modifiers. */ + ModifierData *md = static_cast<ModifierData *>(m_object->modifiers.first); + + while (md) { + if (md->type != eModifierType_Subsurf) { + return true; + } + + md = md->next; + } + + return false; +} + +void AbcMeshWriter::do_write() +{ + /* We have already stored a sample for this object. */ + if (!m_first_frame && !m_is_animated) + return; + + DerivedMesh *dm = getFinalMesh(); + + try { + if (m_settings.use_subdiv_schema && m_subdiv_schema.valid()) { + writeSubD(dm); + } + else { + writeMesh(dm); + } + + freeMesh(dm); + } + catch (...) { + freeMesh(dm); + throw; + } +} + +void AbcMeshWriter::writeMesh(DerivedMesh *dm) +{ + std::vector<Imath::V3f> points, normals; + std::vector<int32_t> poly_verts, loop_counts; + + bool smooth_normal = false; + + get_vertices(dm, points); + get_topology(dm, poly_verts, loop_counts, smooth_normal); + + if (m_first_frame) { + writeCommonData(dm, m_mesh_schema); + } + + m_mesh_sample = OPolyMeshSchema::Sample(V3fArraySample(points), + Int32ArraySample(poly_verts), + Int32ArraySample(loop_counts)); + + UVSample sample; + if (m_settings.export_uvs) { + const char *name = get_uv_sample(sample, m_custom_data_config, &dm->loopData); + + if (!sample.indices.empty() && !sample.uvs.empty()) { + OV2fGeomParam::Sample uv_sample; + uv_sample.setVals(V2fArraySample(sample.uvs)); + uv_sample.setIndices(UInt32ArraySample(sample.indices)); + uv_sample.setScope(kFacevaryingScope); + + m_mesh_schema.setUVSourceName(name); + m_mesh_sample.setUVs(uv_sample); + } + + write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPUV); + } + + if (m_settings.export_normals) { + if (smooth_normal) { + get_loop_normals(dm, normals); + } + else { + get_vertex_normals(dm, normals); + } + + ON3fGeomParam::Sample normals_sample; + if (!normals.empty()) { + normals_sample.setScope((smooth_normal) ? kFacevaryingScope : kVertexScope); + normals_sample.setVals(V3fArraySample(normals)); + } + + m_mesh_sample.setNormals(normals_sample); + } + + if (m_is_liquid) { + std::vector<Imath::V3f> velocities; + getVelocities(dm, velocities); + + m_mesh_sample.setVelocities(V3fArraySample(velocities)); + } + + m_mesh_sample.setSelfBounds(bounds()); + + m_mesh_schema.set(m_mesh_sample); + + writeArbGeoParams(dm); +} + +void AbcMeshWriter::writeSubD(DerivedMesh *dm) +{ + std::vector<float> crease_sharpness; + std::vector<Imath::V3f> points; + std::vector<int32_t> poly_verts, loop_counts; + std::vector<int32_t> crease_indices, crease_lengths; + + bool smooth_normal = false; + + get_vertices(dm, points); + get_topology(dm, poly_verts, loop_counts, smooth_normal); + get_creases(dm, crease_indices, crease_lengths, crease_sharpness); + + if (m_first_frame) { + /* create materials' face_sets */ + writeCommonData(dm, m_subdiv_schema); + } + + m_subdiv_sample = OSubDSchema::Sample(V3fArraySample(points), + Int32ArraySample(poly_verts), + Int32ArraySample(loop_counts)); + + UVSample sample; + if (m_settings.export_uvs) { + const char *name = get_uv_sample(sample, m_custom_data_config, &dm->loopData); + + if (!sample.indices.empty() && !sample.uvs.empty()) { + OV2fGeomParam::Sample uv_sample; + uv_sample.setVals(V2fArraySample(sample.uvs)); + uv_sample.setIndices(UInt32ArraySample(sample.indices)); + uv_sample.setScope(kFacevaryingScope); + + m_subdiv_schema.setUVSourceName(name); + m_subdiv_sample.setUVs(uv_sample); + } + + write_custom_data(m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPUV); + } + + if (!crease_indices.empty()) { + m_subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices)); + m_subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths)); + m_subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness)); + } + + m_subdiv_sample.setSelfBounds(bounds()); + m_subdiv_schema.set(m_subdiv_sample); + + writeArbGeoParams(dm); +} + +template <typename Schema> +void AbcMeshWriter::writeCommonData(DerivedMesh *dm, Schema &schema) +{ + std::map< std::string, std::vector<int32_t> > geo_groups; + getGeoGroups(dm, geo_groups); + + std::map< std::string, std::vector<int32_t> >::iterator it; + for (it = geo_groups.begin(); it != geo_groups.end(); ++it) { + OFaceSet face_set = schema.createFaceSet(it->first); + OFaceSetSchema::Sample samp; + samp.setFaces(Int32ArraySample(it->second)); + face_set.getSchema().set(samp); + } +} + +DerivedMesh *AbcMeshWriter::getFinalMesh() +{ + /* We don't want subdivided mesh data */ + if (m_subsurf_mod) { + m_subsurf_mod->mode |= eModifierMode_DisableTemporary; + } + + DerivedMesh *dm = mesh_create_derived_render(m_scene, m_object, CD_MASK_MESH); + + if (m_subsurf_mod) { + m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary; + } + + m_custom_data_config.pack_uvs = m_settings.pack_uv; + m_custom_data_config.mpoly = dm->getPolyArray(dm); + m_custom_data_config.mloop = dm->getLoopArray(dm); + m_custom_data_config.totpoly = dm->getNumPolys(dm); + m_custom_data_config.totloop = dm->getNumLoops(dm); + m_custom_data_config.totvert = dm->getNumVerts(dm); + + return dm; +} + +void AbcMeshWriter::freeMesh(DerivedMesh *dm) +{ + dm->release(dm); +} + +void AbcMeshWriter::writeArbGeoParams(DerivedMesh *dm) +{ + if (m_is_liquid) { + /* We don't need anything more for liquid meshes. */ + return; + } + + if (m_settings.export_vcols) { + if (m_subdiv_schema.valid()) { + write_custom_data(m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPCOL); + } + else { + write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPCOL); + } + } + + if (m_first_frame && m_has_per_face_materials) { + std::vector<int32_t> material_indices; + + if (m_settings.export_face_sets) { + get_material_indices(dm, material_indices); + + OFaceSetSchema::Sample samp; + samp.setFaces(Int32ArraySample(material_indices)); + m_face_set.getSchema().set(samp); + } + } +} + +void AbcMeshWriter::getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels) +{ + const int totverts = dm->getNumVerts(dm); + + vels.clear(); + vels.resize(totverts); + + ModifierData *md = get_liquid_sim_modifier(m_scene, m_object); + FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(md); + FluidsimSettings *fss = fmd->fss; + + if (fss->meshVelocities) { + float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities); + + for (int i = 0; i < totverts; ++i) { + copy_zup_yup(vels[i].getValue(), mesh_vels); + mesh_vels += 3; + } + } + else { + std::fill(vels.begin(), vels.end(), Imath::V3f(0.0f)); + } +} + +void AbcMeshWriter::getGeoGroups( + DerivedMesh *dm, + std::map<std::string, std::vector<int32_t> > &geo_groups) +{ + const int num_poly = dm->getNumPolys(dm); + MPoly *polygons = dm->getPolyArray(dm); + + for (int i = 0; i < num_poly; ++i) { + MPoly ¤t_poly = polygons[i]; + short mnr = current_poly.mat_nr; + + Material *mat = give_current_material(m_object, mnr + 1); + + if (!mat) { + continue; + } + + std::string name = get_id_name(&mat->id); + + if (geo_groups.find(name) == geo_groups.end()) { + std::vector<int32_t> faceArray; + geo_groups[name] = faceArray; + } + + geo_groups[name].push_back(i); + } + + if (geo_groups.size() == 0) { + Material *mat = give_current_material(m_object, 1); + + std::string name = (mat) ? get_id_name(&mat->id) : "default"; + + std::vector<int32_t> faceArray; + + for (int i = 0, e = dm->getNumTessFaces(dm); i < e; ++i) { + faceArray.push_back(i); + } + + geo_groups[name] = faceArray; + } +} + +/* ************************************************************************** */ + +/* Some helpers for mesh generation */ +namespace utils { + +void mesh_add_verts(Mesh *mesh, size_t len) +{ + if (len == 0) { + return; + } + + const int totvert = mesh->totvert + len; + CustomData vdata; + CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); + CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert); + + if (!CustomData_has_layer(&vdata, CD_MVERT)) { + CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); + } + + CustomData_free(&mesh->vdata, mesh->totvert); + mesh->vdata = vdata; + BKE_mesh_update_customdata_pointers(mesh, false); + + mesh->totvert = totvert; +} + +static void mesh_add_mloops(Mesh *mesh, size_t len) +{ + if (len == 0) { + return; + } + + /* new face count */ + const int totloops = mesh->totloop + len; + + CustomData ldata; + CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloops); + CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop); + + if (!CustomData_has_layer(&ldata, CD_MLOOP)) { + CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloops); + } + + CustomData_free(&mesh->ldata, mesh->totloop); + mesh->ldata = ldata; + BKE_mesh_update_customdata_pointers(mesh, false); + + mesh->totloop = totloops; +} + +static void mesh_add_mpolygons(Mesh *mesh, size_t len) +{ + if (len == 0) { + return; + } + + const int totpolys = mesh->totpoly + len; + + CustomData pdata; + CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpolys); + CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly); + + if (!CustomData_has_layer(&pdata, CD_MPOLY)) { + CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpolys); + } + + CustomData_free(&mesh->pdata, mesh->totpoly); + mesh->pdata = pdata; + BKE_mesh_update_customdata_pointers(mesh, false); + + mesh->totpoly = totpolys; +} + +static void build_mat_map(const Main *bmain, std::map<std::string, Material *> &mat_map) +{ + Material *material = static_cast<Material *>(bmain->mat.first); + + for (; material; material = static_cast<Material *>(material->id.next)) { + mat_map[material->id.name + 2] = material; + } +} + +static void assign_materials(Main *bmain, Object *ob, const std::map<std::string, int> &mat_index_map) +{ + bool can_assign = true; + std::map<std::string, int>::const_iterator it = mat_index_map.begin(); + + int matcount = 0; + for (; it != mat_index_map.end(); ++it, ++matcount) { + if (!BKE_object_material_slot_add(ob)) { + can_assign = false; + break; + } + } + + /* TODO(kevin): use global map? */ + std::map<std::string, Material *> mat_map; + build_mat_map(bmain, mat_map); + + std::map<std::string, Material *>::iterator mat_iter; + + if (can_assign) { + it = mat_index_map.begin(); + + for (; it != mat_index_map.end(); ++it) { + std::string mat_name = it->first; + mat_iter = mat_map.find(mat_name.c_str()); + + Material *assigned_name; + + if (mat_iter == mat_map.end()) { + assigned_name = BKE_material_add(bmain, mat_name.c_str()); + mat_map[mat_name] = assigned_name; + } + else { + assigned_name = mat_iter->second; + } + + assign_material(ob, assigned_name, it->second, BKE_MAT_ASSIGN_OBJECT); + } + } +} + +} /* namespace utils */ + +/* ************************************************************************** */ + +using Alembic::AbcGeom::UInt32ArraySamplePtr; +using Alembic::AbcGeom::V2fArraySamplePtr; + +struct AbcMeshData { + Int32ArraySamplePtr face_indices; + Int32ArraySamplePtr face_counts; + + P3fArraySamplePtr positions; + + N3fArraySamplePtr vertex_normals; + N3fArraySamplePtr face_normals; + + V2fArraySamplePtr uvs; + UInt32ArraySamplePtr uvs_indices; +}; + +static void *add_customdata_cb(void *user_data, const char *name, int data_type) +{ + Mesh *mesh = static_cast<Mesh *>(user_data); + CustomDataType cd_data_type = static_cast<CustomDataType>(data_type); + void *cd_ptr = NULL; + + int index = -1; + if (cd_data_type == CD_MLOOPUV) { + index = ED_mesh_uv_texture_add(mesh, name, true); + cd_ptr = CustomData_get_layer(&mesh->ldata, cd_data_type); + } + else if (cd_data_type == CD_MLOOPCOL) { + index = ED_mesh_color_add(mesh, name, true); + cd_ptr = CustomData_get_layer(&mesh->ldata, cd_data_type); + } + + if (index == -1) { + return NULL; + } + + return cd_ptr; +} + +CDStreamConfig create_config(Mesh *mesh) +{ + CDStreamConfig config; + + config.mvert = mesh->mvert; + config.mpoly = mesh->mpoly; + config.mloop = mesh->mloop; + config.totpoly = mesh->totpoly; + config.totloop = mesh->totloop; + config.user_data = mesh; + config.loopdata = &mesh->ldata; + config.add_customdata_cb = add_customdata_cb; + + return config; +} + +static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data) +{ + MVert *mverts = config.mvert; + const P3fArraySamplePtr &positions = mesh_data.positions; + const N3fArraySamplePtr &normals = mesh_data.vertex_normals; + + read_mverts(mverts, positions, normals); +} + +void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArraySamplePtr &normals) +{ + for (int i = 0; i < positions->size(); ++i) { + MVert &mvert = mverts[i]; + Imath::V3f pos_in = (*positions)[i]; + + copy_yup_zup(mvert.co, pos_in.getValue()); + + mvert.bweight = 0; + + if (normals) { + Imath::V3f nor_in = (*normals)[i]; + + short no[3]; + normal_float_to_short_v3(no, nor_in.getValue()); + + copy_yup_zup(mvert.no, no); + } + } +} + +static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) +{ + MPoly *mpolys = config.mpoly; + MLoop *mloops = config.mloop; + MLoopUV *mloopuvs = config.mloopuv; + + const Int32ArraySamplePtr &face_indices = mesh_data.face_indices; + const Int32ArraySamplePtr &face_counts = mesh_data.face_counts; + const V2fArraySamplePtr &uvs = mesh_data.uvs; + const UInt32ArraySamplePtr &uvs_indices = mesh_data.uvs_indices; + const N3fArraySamplePtr &normals = mesh_data.face_normals; + + const bool do_uvs = (mloopuvs && uvs && uvs_indices) && (uvs_indices->size() == face_indices->size()); + unsigned int loop_index = 0; + unsigned int rev_loop_index = 0; + unsigned int uv_index = 0; + + for (int i = 0; i < face_counts->size(); ++i) { + const int face_size = (*face_counts)[i]; + + MPoly &poly = mpolys[i]; + poly.loopstart = loop_index; + poly.totloop = face_size; + + if (normals != NULL) { + poly.flag |= ME_SMOOTH; + } + + /* NOTE: Alembic data is stored in the reverse order. */ + rev_loop_index = loop_index + (face_size - 1); + + for (int f = 0; f < face_size; ++f, ++loop_index, --rev_loop_index) { + MLoop &loop = mloops[rev_loop_index]; + loop.v = (*face_indices)[loop_index]; + + if (do_uvs) { + MLoopUV &loopuv = mloopuvs[rev_loop_index]; + + uv_index = (*uvs_indices)[loop_index]; + loopuv.uv[0] = (*uvs)[uv_index][0]; + loopuv.uv[1] = (*uvs)[uv_index][1]; + } + } + } +} + +ABC_INLINE void read_uvs_params(CDStreamConfig &config, + AbcMeshData &abc_data, + const IV2fGeomParam &uv, + const ISampleSelector &selector) +{ + if (!uv.valid()) { + return; + } + + IV2fGeomParam::Sample uvsamp; + uv.getIndexed(uvsamp, selector); + + abc_data.uvs = uvsamp.getVals(); + abc_data.uvs_indices = uvsamp.getIndices(); + + if (abc_data.uvs_indices->size() == config.totloop) { + std::string name = Alembic::Abc::GetSourceName(uv.getMetaData()); + + /* According to the convention, primary UVs should have had their name + * set using Alembic::Abc::SetSourceName, but you can't expect everyone + * to follow it! :) */ + if (name.empty()) { + name = uv.getName(); + } + + void *cd_ptr = config.add_customdata_cb(config.user_data, name.c_str(), CD_MLOOPUV); + config.mloopuv = static_cast<MLoopUV *>(cd_ptr); + } +} + +/* TODO(kevin): normals from Alembic files are not read in anymore, this is due + * to the fact that there are many issues that are not so easy to solve, mainly + * regarding the way normals are handled in Blender (MPoly.flag vs loop normals). + */ +ABC_INLINE void read_normals_params(AbcMeshData &abc_data, + const IN3fGeomParam &normals, + const ISampleSelector &selector) +{ + if (!normals.valid()) { + return; + } + + IN3fGeomParam::Sample normsamp = normals.getExpandedValue(selector); + + if (normals.getScope() == kFacevaryingScope) { + abc_data.face_normals = normsamp.getVals(); + } + else if ((normals.getScope() == kVertexScope) || (normals.getScope() == kVaryingScope)) { + abc_data.vertex_normals = N3fArraySamplePtr(); + } +} + +/* ************************************************************************** */ + +AbcMeshReader::AbcMeshReader(const IObject &object, ImportSettings &settings) + : AbcObjectReader(object, settings) +{ + m_settings->read_flag |= MOD_MESHSEQ_READ_ALL; + + IPolyMesh ipoly_mesh(m_iobject, kWrapExisting); + m_schema = ipoly_mesh.getSchema(); + + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); +} + +bool AbcMeshReader::valid() const +{ + return m_schema.valid(); +} + +void AbcMeshReader::readObjectData(Main *bmain, float time) +{ + Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str()); + + m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str()); + m_object->data = mesh; + + const ISampleSelector sample_sel(time); + const IPolyMeshSchema::Sample sample = m_schema.getValue(sample_sel); + + const P3fArraySamplePtr &positions = sample.getPositions(); + const Int32ArraySamplePtr &face_indices = sample.getFaceIndices(); + const Int32ArraySamplePtr &face_counts = sample.getFaceCounts(); + + utils::mesh_add_verts(mesh, positions->size()); + utils::mesh_add_mpolygons(mesh, face_counts->size()); + utils::mesh_add_mloops(mesh, face_indices->size()); + + m_mesh_data = create_config(mesh); + + bool has_smooth_normals = false; + read_mesh_sample(m_settings, m_schema, sample_sel, m_mesh_data, has_smooth_normals); + + BKE_mesh_calc_normals(mesh); + BKE_mesh_calc_edges(mesh, false, false); + + if (m_settings->validate_meshes) { + BKE_mesh_validate(mesh, false, false); + } + + readFaceSetsSample(bmain, mesh, 0, sample_sel); + + if (has_animations(m_schema, m_settings)) { + addCacheModifier(); + } +} + +void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start, + const ISampleSelector &sample_sel) +{ + std::vector<std::string> face_sets; + m_schema.getFaceSetNames(face_sets); + + if (face_sets.empty()) { + return; + } + + std::map<std::string, int> mat_map; + int current_mat = 0; + + for (int i = 0; i < face_sets.size(); ++i) { + const std::string &grp_name = face_sets[i]; + + if (mat_map.find(grp_name) == mat_map.end()) { + mat_map[grp_name] = 1 + current_mat++; + } + + const int assigned_mat = mat_map[grp_name]; + + const IFaceSet faceset = m_schema.getFaceSet(grp_name); + + if (!faceset.valid()) { + continue; + } + + const IFaceSetSchema face_schem = faceset.getSchema(); + const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel); + const Int32ArraySamplePtr group_faces = face_sample.getFaces(); + const size_t num_group_faces = group_faces->size(); + + for (size_t l = 0; l < num_group_faces; l++) { + size_t pos = (*group_faces)[l] + poly_start; + + if (pos >= mesh->totpoly) { + std::cerr << "Faceset overflow on " << faceset.getName() << '\n'; + break; + } + + MPoly &poly = mesh->mpoly[pos]; + poly.mat_nr = assigned_mat - 1; + } + } + + utils::assign_materials(bmain, m_object, mat_map); +} + +void read_mesh_sample(ImportSettings *settings, + const IPolyMeshSchema &schema, + const ISampleSelector &selector, + CDStreamConfig &config, + bool &do_normals) +{ + const IPolyMeshSchema::Sample sample = schema.getValue(selector); + + AbcMeshData abc_mesh_data; + abc_mesh_data.face_counts = sample.getFaceCounts(); + abc_mesh_data.face_indices = sample.getFaceIndices(); + abc_mesh_data.positions = sample.getPositions(); + + read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector); + + do_normals = (abc_mesh_data.face_normals != NULL); + + if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { + read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); + } + + if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { + read_mverts(config, abc_mesh_data); + } + + if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { + read_mpolys(config, abc_mesh_data); + } + + if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { + read_custom_data(schema.getArbGeomParams(), config, selector); + } + + /* TODO: face sets */ +} + +/* ************************************************************************** */ + +ABC_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2) +{ + for (int i = 0, e = totedge; i < e; ++i) { + MEdge &edge = edges[i]; + + if (edge.v1 == v1 && edge.v2 == v2) { + return &edge; + } + } + + return NULL; +} + +AbcSubDReader::AbcSubDReader(const IObject &object, ImportSettings &settings) + : AbcObjectReader(object, settings) +{ + m_settings->read_flag |= MOD_MESHSEQ_READ_ALL; + + ISubD isubd_mesh(m_iobject, kWrapExisting); + m_schema = isubd_mesh.getSchema(); + + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); +} + +bool AbcSubDReader::valid() const +{ + return m_schema.valid(); +} + +void AbcSubDReader::readObjectData(Main *bmain, float time) +{ + Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str()); + + m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str()); + m_object->data = mesh; + + const ISampleSelector sample_sel(time); + const ISubDSchema::Sample sample = m_schema.getValue(sample_sel); + + const P3fArraySamplePtr &positions = sample.getPositions(); + const Int32ArraySamplePtr &face_indices = sample.getFaceIndices(); + const Int32ArraySamplePtr &face_counts = sample.getFaceCounts(); + + utils::mesh_add_verts(mesh, positions->size()); + utils::mesh_add_mpolygons(mesh, face_counts->size()); + utils::mesh_add_mloops(mesh, face_indices->size()); + + m_mesh_data = create_config(mesh); + + read_subd_sample(m_settings, m_schema, sample_sel, m_mesh_data); + + Int32ArraySamplePtr indices = sample.getCreaseIndices(); + Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses(); + + MEdge *edges = mesh->medge; + + if (indices && sharpnesses) { + for (int i = 0, s = 0, e = indices->size(); i < e; i += 2, ++s) { + MEdge *edge = find_edge(edges, mesh->totedge, (*indices)[i], (*indices)[i + 1]); + + if (edge) { + edge->crease = FTOCHAR((*sharpnesses)[s]); + } + } + + mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; + } + + BKE_mesh_calc_normals(mesh); + BKE_mesh_calc_edges(mesh, false, false); + + if (m_settings->validate_meshes) { + BKE_mesh_validate(mesh, false, false); + } + + if (has_animations(m_schema, m_settings)) { + addCacheModifier(); + } +} + +void read_subd_sample(ImportSettings *settings, + const ISubDSchema &schema, + const ISampleSelector &selector, + CDStreamConfig &config) +{ + const ISubDSchema::Sample sample = schema.getValue(selector); + + AbcMeshData abc_mesh_data; + abc_mesh_data.face_counts = sample.getFaceCounts(); + abc_mesh_data.face_indices = sample.getFaceIndices(); + abc_mesh_data.vertex_normals = N3fArraySamplePtr(); + abc_mesh_data.face_normals = N3fArraySamplePtr(); + abc_mesh_data.positions = sample.getPositions(); + + if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { + read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); + } + + if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { + read_mverts(config, abc_mesh_data); + } + + if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { + read_mpolys(config, abc_mesh_data); + } + + if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { + read_custom_data(schema.getArbGeomParams(), config, selector); + } + + /* TODO: face sets */ +} diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h new file mode 100644 index 00000000000..9dc222e5206 --- /dev/null +++ b/source/blender/alembic/intern/abc_mesh.h @@ -0,0 +1,152 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_MESH_H__ +#define __ABC_MESH_H__ + +#include "abc_customdata.h" +#include "abc_object.h" + +struct DerivedMesh; +struct Mesh; +struct ModifierData; + +/* ************************************************************************** */ + +class AbcMeshWriter : public AbcObjectWriter { + Alembic::AbcGeom::OPolyMeshSchema m_mesh_schema; + Alembic::AbcGeom::OPolyMeshSchema::Sample m_mesh_sample; + + Alembic::AbcGeom::OSubDSchema m_subdiv_schema; + Alembic::AbcGeom::OSubDSchema::Sample m_subdiv_sample; + + bool m_has_per_face_materials; + Alembic::AbcGeom::OFaceSet m_face_set; + Alembic::Abc::OArrayProperty m_mat_indices; + + bool m_is_animated; + ModifierData *m_subsurf_mod; + + CDStreamConfig m_custom_data_config; + + bool m_is_liquid; + bool m_is_subd; + +public: + AbcMeshWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings); + + ~AbcMeshWriter(); + +private: + virtual void do_write(); + + bool isAnimated() const; + + void writeMesh(DerivedMesh *dm); + void writeSubD(DerivedMesh *dm); + + void getMeshInfo(DerivedMesh *dm, std::vector<float> &points, + std::vector<int32_t> &facePoints, + std::vector<int32_t> &faceCounts, + std::vector<int32_t> &creaseIndices, + std::vector<int32_t> &creaseLengths, + std::vector<float> &creaseSharpness); + + DerivedMesh *getFinalMesh(); + void freeMesh(DerivedMesh *dm); + + void getMaterialIndices(DerivedMesh *dm, std::vector<int32_t> &indices); + + void writeArbGeoParams(DerivedMesh *dm); + void getGeoGroups(DerivedMesh *dm, std::map<std::string, std::vector<int32_t> > &geoGroups); + + /* fluid surfaces support */ + void getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels); + + template <typename Schema> + void writeCommonData(DerivedMesh *dm, Schema &schema); +}; + +/* ************************************************************************** */ + +class AbcMeshReader : public AbcObjectReader { + Alembic::AbcGeom::IPolyMeshSchema m_schema; + + CDStreamConfig m_mesh_data; + +public: + AbcMeshReader(const Alembic::Abc::IObject &object, ImportSettings &settings); + + bool valid() const; + + void readObjectData(Main *bmain, float time); + +private: + void readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start, + const Alembic::AbcGeom::ISampleSelector &sample_sel); +}; + +void read_mesh_sample(ImportSettings *settings, + const Alembic::AbcGeom::IPolyMeshSchema &schema, + const Alembic::AbcGeom::ISampleSelector &selector, + CDStreamConfig &config, + bool &do_normals); + +/* ************************************************************************** */ + +class AbcSubDReader : public AbcObjectReader { + Alembic::AbcGeom::ISubDSchema m_schema; + + CDStreamConfig m_mesh_data; + +public: + AbcSubDReader(const Alembic::Abc::IObject &object, ImportSettings &settings); + + bool valid() const; + + void readObjectData(Main *bmain, float time); +}; + +void read_subd_sample(ImportSettings *settings, + const Alembic::AbcGeom::ISubDSchema &schema, + const Alembic::AbcGeom::ISampleSelector &selector, + CDStreamConfig &config); + +/* ************************************************************************** */ + +namespace utils { + +void mesh_add_verts(struct Mesh *mesh, size_t len); + +} + +void read_mverts(MVert *mverts, + const Alembic::AbcGeom::P3fArraySamplePtr &positions, + const Alembic::AbcGeom::N3fArraySamplePtr &normals); + +CDStreamConfig create_config(Mesh *mesh); + +#endif /* __ABC_MESH_H__ */ diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc new file mode 100644 index 00000000000..4f57dfdae9e --- /dev/null +++ b/source/blender/alembic/intern/abc_nurbs.cc @@ -0,0 +1,367 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "abc_nurbs.h" + +#include "abc_transform.h" +#include "abc_util.h" + +extern "C" { +#include "MEM_guardedalloc.h" + +#include "DNA_curve_types.h" +#include "DNA_object_types.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_string.h" + +#include "BKE_curve.h" +#include "BKE_object.h" +} + +using Alembic::AbcGeom::bool_t; +using Alembic::AbcGeom::FloatArraySample; +using Alembic::AbcGeom::FloatArraySamplePtr; +using Alembic::AbcGeom::MetaData; +using Alembic::AbcGeom::P3fArraySamplePtr; +using Alembic::AbcGeom::kWrapExisting; + +using Alembic::AbcGeom::IBoolProperty; +using Alembic::AbcGeom::ICompoundProperty; +using Alembic::AbcGeom::INuPatch; +using Alembic::AbcGeom::INuPatchSchema; +using Alembic::AbcGeom::IObject; +using Alembic::AbcGeom::ISampleSelector; + +using Alembic::AbcGeom::OBoolProperty; +using Alembic::AbcGeom::OCompoundProperty; +using Alembic::AbcGeom::ONuPatch; +using Alembic::AbcGeom::ONuPatchSchema; + +/* ************************************************************************** */ + +AbcNurbsWriter::AbcNurbsWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings) + : AbcObjectWriter(scene, ob, time_sampling, settings, parent) +{ + m_is_animated = isAnimated(); + + /* if the object is static, use the default static time sampling */ + if (!m_is_animated) { + m_time_sampling = 0; + } + + Curve *curve = static_cast<Curve *>(m_object->data); + size_t numNurbs = BLI_listbase_count(&curve->nurb); + + for (size_t i = 0; i < numNurbs; ++i) { + std::stringstream str; + str << m_name << '_' << i; + + while (parent->alembicXform().getChildHeader(str.str())) { + str << "_"; + } + + ONuPatch nurbs(parent->alembicXform(), str.str().c_str(), m_time_sampling); + m_nurbs_schema.push_back(nurbs.getSchema()); + } +} + +bool AbcNurbsWriter::isAnimated() const +{ + /* check if object has shape keys */ + Curve *cu = static_cast<Curve *>(m_object->data); + return (cu->key != NULL); +} + +static void get_knots(std::vector<float> &knots, const int num_knots, float *nu_knots) +{ + if (num_knots <= 1) { + return; + } + + /* Add an extra knot at the beggining and end of the array since most apps + * require/expect them. */ + knots.reserve(num_knots + 2); + + knots.push_back(0.0f); + + for (int i = 0; i < num_knots; ++i) { + knots.push_back(nu_knots[i]); + } + + knots[0] = 2.0f * knots[1] - knots[2]; + knots.push_back(2.0f * knots[num_knots] - knots[num_knots - 1]); +} + +void AbcNurbsWriter::do_write() +{ + /* we have already stored a sample for this object. */ + if (!m_first_frame && !m_is_animated) { + return; + } + + if (!ELEM(m_object->type, OB_SURF, OB_CURVE)) { + return; + } + + Curve *curve = static_cast<Curve *>(m_object->data); + ListBase *nulb; + + if (m_object->curve_cache->deformed_nurbs.first != NULL) { + nulb = &m_object->curve_cache->deformed_nurbs; + } + else { + nulb = BKE_curve_nurbs_get(curve); + } + + size_t count = 0; + for (Nurb *nu = static_cast<Nurb *>(nulb->first); nu; nu = nu->next, ++count) { + std::vector<float> knotsU; + get_knots(knotsU, KNOTSU(nu), nu->knotsu); + + std::vector<float> knotsV; + get_knots(knotsV, KNOTSV(nu), nu->knotsv); + + const int size = nu->pntsu * nu->pntsv; + std::vector<Imath::V3f> positions(size); + std::vector<float> weights(size); + + const BPoint *bp = nu->bp; + + for (int i = 0; i < size; ++i, ++bp) { + copy_zup_yup(positions[i].getValue(), bp->vec); + weights[i] = bp->vec[3]; + } + + ONuPatchSchema::Sample sample; + sample.setUOrder(nu->orderu + 1); + sample.setVOrder(nu->orderv + 1); + sample.setPositions(positions); + sample.setPositionWeights(weights); + sample.setUKnot(FloatArraySample(knotsU)); + sample.setVKnot(FloatArraySample(knotsV)); + sample.setNu(nu->pntsu); + sample.setNv(nu->pntsv); + + /* TODO(kevin): to accomodate other software we should duplicate control + * points to indicate that a NURBS is cyclic. */ + OCompoundProperty user_props = m_nurbs_schema[count].getUserProperties(); + + if ((nu->flagu & CU_NURB_ENDPOINT) != 0) { + OBoolProperty prop(user_props, "endpoint_u"); + prop.set(true); + } + + if ((nu->flagv & CU_NURB_ENDPOINT) != 0) { + OBoolProperty prop(user_props, "endpoint_v"); + prop.set(true); + } + + if ((nu->flagu & CU_NURB_CYCLIC) != 0) { + OBoolProperty prop(user_props, "cyclic_u"); + prop.set(true); + } + + if ((nu->flagv & CU_NURB_CYCLIC) != 0) { + OBoolProperty prop(user_props, "cyclic_v"); + prop.set(true); + } + + m_nurbs_schema[count].set(sample); + } +} + +/* ************************************************************************** */ + +AbcNurbsReader::AbcNurbsReader(const IObject &object, ImportSettings &settings) + : AbcObjectReader(object, settings) +{ + getNurbsPatches(m_iobject); + get_min_max_time(m_iobject, m_schemas[0].first, m_min_time, m_max_time); +} + +bool AbcNurbsReader::valid() const +{ + if (m_schemas.empty()) { + return false; + } + + std::vector< std::pair<INuPatchSchema, IObject> >::const_iterator it; + for (it = m_schemas.begin(); it != m_schemas.end(); ++it) { + const INuPatchSchema &schema = it->first; + + if (!schema.valid()) { + return false; + } + } + + return true; +} + +static bool set_knots(const FloatArraySamplePtr &knots, float *&nu_knots) +{ + if (!knots || knots->size() == 0) { + return false; + } + + /* Skip first and last knots, as they are used for padding. */ + const size_t num_knots = knots->size() - 2; + nu_knots = static_cast<float *>(MEM_callocN(num_knots * sizeof(float), "abc_setsplineknotsu")); + + for (size_t i = 0; i < num_knots; ++i) { + nu_knots[i] = (*knots)[i + 1]; + } + + return true; +} + +void AbcNurbsReader::readObjectData(Main *bmain, float time) +{ + Curve *cu = static_cast<Curve *>(BKE_curve_add(bmain, "abc_curve", OB_SURF)); + cu->actvert = CU_ACT_NONE; + + std::vector< std::pair<INuPatchSchema, IObject> >::iterator it; + + for (it = m_schemas.begin(); it != m_schemas.end(); ++it) { + Nurb *nu = static_cast<Nurb *>(MEM_callocN(sizeof(Nurb), "abc_getnurb")); + nu->flag = CU_SMOOTH; + nu->type = CU_NURBS; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + + const ISampleSelector sample_sel(time); + const INuPatchSchema &schema = it->first; + const INuPatchSchema::Sample smp = schema.getValue(sample_sel); + + nu->orderu = smp.getUOrder() - 1; + nu->orderv = smp.getVOrder() - 1; + nu->pntsu = smp.getNumU(); + nu->pntsv = smp.getNumV(); + + /* Read positions and weights. */ + + const P3fArraySamplePtr positions = smp.getPositions(); + const FloatArraySamplePtr weights = smp.getPositionWeights(); + + const size_t num_points = positions->size(); + + nu->bp = static_cast<BPoint *>(MEM_callocN(num_points * sizeof(BPoint), "abc_setsplinetype")); + + BPoint *bp = nu->bp; + float posw_in = 1.0f; + + for (int i = 0; i < num_points; ++i, ++bp) { + const Imath::V3f &pos_in = (*positions)[i]; + + if (weights) { + posw_in = (*weights)[i]; + } + + copy_yup_zup(bp->vec, pos_in.getValue()); + bp->vec[3] = posw_in; + bp->f1 = SELECT; + bp->radius = 1.0f; + bp->weight = 1.0f; + } + + /* Read knots. */ + + if (!set_knots(smp.getUKnot(), nu->knotsu)) { + BKE_nurb_knot_calc_u(nu); + } + + if (!set_knots(smp.getVKnot(), nu->knotsv)) { + BKE_nurb_knot_calc_v(nu); + } + + /* Read flags. */ + + ICompoundProperty user_props = schema.getUserProperties(); + + if (has_property(user_props, "enpoint_u")) { + nu->flagu |= CU_NURB_ENDPOINT; + } + + if (has_property(user_props, "enpoint_v")) { + nu->flagv |= CU_NURB_ENDPOINT; + } + + if (has_property(user_props, "cyclic_u")) { + nu->flagu |= CU_NURB_CYCLIC; + } + + if (has_property(user_props, "cyclic_v")) { + nu->flagv |= CU_NURB_CYCLIC; + } + + BLI_addtail(BKE_curve_nurbs_get(cu), nu); + } + + BLI_strncpy(cu->id.name + 2, m_data_name.c_str(), m_data_name.size() + 1); + + m_object = BKE_object_add_only_object(bmain, OB_SURF, m_object_name.c_str()); + m_object->data = cu; +} + +void AbcNurbsReader::getNurbsPatches(const IObject &obj) +{ + if (!obj.valid()) { + return; + } + + const int num_children = obj.getNumChildren(); + + if (num_children == 0) { + INuPatch abc_nurb(obj, kWrapExisting); + INuPatchSchema schem = abc_nurb.getSchema(); + m_schemas.push_back(std::pair<INuPatchSchema, IObject>(schem, obj)); + return; + } + + for (int i = 0; i < num_children; ++i) { + bool ok = true; + IObject child(obj, obj.getChildHeader(i).getName()); + + if (!m_name.empty() && child.valid() && !begins_with(child.getFullName(), m_name)) { + ok = false; + } + + if (!child.valid()) { + continue; + } + + const MetaData &md = child.getMetaData(); + + if (INuPatch::matches(md) && ok) { + INuPatch abc_nurb(child, kWrapExisting); + INuPatchSchema schem = abc_nurb.getSchema(); + m_schemas.push_back(std::pair<INuPatchSchema, IObject>(schem, child)); + } + + getNurbsPatches(child); + } +} diff --git a/source/blender/alembic/intern/abc_nurbs.h b/source/blender/alembic/intern/abc_nurbs.h new file mode 100644 index 00000000000..1b2e7a8391f --- /dev/null +++ b/source/blender/alembic/intern/abc_nurbs.h @@ -0,0 +1,63 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_NURBS_H__ +#define __ABC_NURBS_H__ + +#include "abc_object.h" + +/* ************************************************************************** */ + +class AbcNurbsWriter : public AbcObjectWriter { + std::vector<Alembic::AbcGeom::ONuPatchSchema> m_nurbs_schema; + bool m_is_animated; + +public: + AbcNurbsWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings); + +private: + virtual void do_write(); + + bool isAnimated() const; +}; + +/* ************************************************************************** */ + +class AbcNurbsReader : public AbcObjectReader { + std::vector< std::pair<Alembic::AbcGeom::INuPatchSchema, Alembic::Abc::IObject> > m_schemas; + +public: + AbcNurbsReader(const Alembic::Abc::IObject &object, ImportSettings &settings); + + bool valid() const; + + void readObjectData(Main *bmain, float time); + +private: + void getNurbsPatches(const Alembic::Abc::IObject &obj); +}; + +#endif /* __ABC_NURBS_H__ */ diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc new file mode 100644 index 00000000000..5b7b85f10ea --- /dev/null +++ b/source/blender/alembic/intern/abc_object.cc @@ -0,0 +1,238 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "abc_object.h" + +#include "abc_util.h" + +extern "C" { +#include "DNA_cachefile_types.h" +#include "DNA_constraint_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_space_types.h" /* for FILE_MAX */ + +#include "BKE_constraint.h" +#include "BKE_depsgraph.h" +#include "BKE_idprop.h" +#include "BKE_library.h" +#include "BKE_modifier.h" +#include "BKE_object.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_string.h" +} + +using Alembic::AbcGeom::IObject; +using Alembic::AbcGeom::IXform; +using Alembic::AbcGeom::IXformSchema; + +using Alembic::AbcGeom::OCompoundProperty; +using Alembic::AbcGeom::ODoubleArrayProperty; +using Alembic::AbcGeom::ODoubleProperty; +using Alembic::AbcGeom::OFloatArrayProperty; +using Alembic::AbcGeom::OFloatProperty; +using Alembic::AbcGeom::OInt32ArrayProperty; +using Alembic::AbcGeom::OInt32Property; +using Alembic::AbcGeom::OStringArrayProperty; +using Alembic::AbcGeom::OStringProperty; + +/* ************************************************************************** */ + +AbcObjectWriter::AbcObjectWriter(Scene *scene, + Object *ob, + uint32_t time_sampling, + ExportSettings &settings, + AbcObjectWriter *parent) + : m_object(ob) + , m_settings(settings) + , m_scene(scene) + , m_time_sampling(time_sampling) + , m_first_frame(true) +{ + m_name = get_id_name(m_object) + "Shape"; + + if (parent) { + parent->addChild(this); + } +} + +AbcObjectWriter::~AbcObjectWriter() +{} + +void AbcObjectWriter::addChild(AbcObjectWriter *child) +{ + m_children.push_back(child); +} + +Imath::Box3d AbcObjectWriter::bounds() +{ + BoundBox *bb = BKE_object_boundbox_get(this->m_object); + + if (!bb) { + if (this->m_object->type != OB_CAMERA) { + std::cerr << "Boundbox is null!\n"; + } + + return Imath::Box3d(); + } + + /* Convert Z-up to Y-up. */ + this->m_bounds.min.x = bb->vec[0][0]; + this->m_bounds.min.y = bb->vec[0][2]; + this->m_bounds.min.z = -bb->vec[0][1]; + + this->m_bounds.max.x = bb->vec[6][0]; + this->m_bounds.max.y = bb->vec[6][2]; + this->m_bounds.max.z = -bb->vec[6][1]; + + return this->m_bounds; +} + +void AbcObjectWriter::write() +{ + do_write(); + m_first_frame = false; +} + +/* ************************************************************************** */ + +AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings) + : m_name("") + , m_object_name("") + , m_data_name("") + , m_object(NULL) + , m_iobject(object) + , m_settings(&settings) + , m_min_time(std::numeric_limits<chrono_t>::max()) + , m_max_time(std::numeric_limits<chrono_t>::min()) +{ + m_name = object.getFullName(); + std::vector<std::string> parts; + split(m_name, '/', parts); + + if (parts.size() >= 2) { + m_object_name = parts[parts.size() - 2]; + m_data_name = parts[parts.size() - 1]; + } + else { + m_object_name = m_data_name = parts[parts.size() - 1]; + } +} + +AbcObjectReader::~AbcObjectReader() +{} + +const IObject &AbcObjectReader::iobject() const +{ + return m_iobject; +} + +Object *AbcObjectReader::object() const +{ + return m_object; +} + +void AbcObjectReader::readObjectMatrix(const float time) +{ + IXform ixform; + bool has_alembic_parent = false; + + /* Check that we have an empty object (locator, bone head/tail...). */ + if (IXform::matches(m_iobject.getMetaData())) { + ixform = IXform(m_iobject, Alembic::AbcGeom::kWrapExisting); + + /* See comment below. */ + has_alembic_parent = m_iobject.getParent().getParent().valid(); + } + /* Check that we have an object with actual data. */ + else if (IXform::matches(m_iobject.getParent().getMetaData())) { + ixform = IXform(m_iobject.getParent(), Alembic::AbcGeom::kWrapExisting); + + /* This is a bit hackish, but we need to make sure that extra + * transformations added to the matrix (rotation/scale) are only applied + * to root objects. The way objects and their hierarchy are created will + * need to be revisited at some point but for now this seems to do the + * trick. + * + * Explanation of the trick: + * The first getParent() will return this object's transformation matrix. + * The second getParent() will get the parent of the transform, but this + * might be the archive root ('/') which is valid, so we go passed it to + * make sure that there is no parent. + */ + has_alembic_parent = m_iobject.getParent().getParent().getParent().valid(); + } + /* Should not happen. */ + else { + return; + } + + const IXformSchema &schema(ixform.getSchema()); + + if (!schema.valid()) { + return; + } + + Alembic::AbcGeom::ISampleSelector sample_sel(time); + Alembic::AbcGeom::XformSample xs; + schema.get(xs, sample_sel); + + create_input_transform(sample_sel, ixform, m_object, m_object->obmat, m_settings->scale, has_alembic_parent); + + invert_m4_m4(m_object->imat, m_object->obmat); + + BKE_object_apply_mat4(m_object, m_object->obmat, false, false); + + if (!schema.isConstant()) { + bConstraint *con = BKE_constraint_add_for_object(m_object, NULL, CONSTRAINT_TYPE_TRANSFORM_CACHE); + bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data); + BLI_strncpy(data->object_path, m_iobject.getFullName().c_str(), FILE_MAX); + + data->cache_file = m_settings->cache_file; + id_us_plus(&data->cache_file->id); + } +} + +void AbcObjectReader::addCacheModifier() const +{ + ModifierData *md = modifier_new(eModifierType_MeshSequenceCache); + BLI_addtail(&m_object->modifiers, md); + + MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md); + + mcmd->cache_file = m_settings->cache_file; + id_us_plus(&mcmd->cache_file->id); + + BLI_strncpy(mcmd->object_path, m_iobject.getFullName().c_str(), FILE_MAX); +} + +chrono_t AbcObjectReader::minTime() const +{ + return m_min_time; +} + +chrono_t AbcObjectReader::maxTime() const +{ + return m_max_time; +} diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h new file mode 100644 index 00000000000..2e885f296b1 --- /dev/null +++ b/source/blender/alembic/intern/abc_object.h @@ -0,0 +1,169 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_OBJECT_H__ +#define __ABC_OBJECT_H__ + +#include <Alembic/Abc/All.h> +#include <Alembic/AbcGeom/All.h> + +#include "abc_exporter.h" + +extern "C" { +#include "DNA_ID.h" +} + +class AbcTransformWriter; + +struct Main; +struct Object; + +/* ************************************************************************** */ + +class AbcObjectWriter { +protected: + Object *m_object; + ExportSettings &m_settings; + + Scene *m_scene; + uint32_t m_time_sampling; + + Imath::Box3d m_bounds; + std::vector<AbcObjectWriter *> m_children; + + std::vector< std::pair<std::string, IDProperty *> > m_props; + + bool m_first_frame; + std::string m_name; + +public: + AbcObjectWriter(Scene *scene, + Object *ob, + uint32_t time_sampling, + ExportSettings &settings, + AbcObjectWriter *parent = NULL); + + virtual ~AbcObjectWriter(); + + void addChild(AbcObjectWriter *child); + + virtual Imath::Box3d bounds(); + + void write(); + +private: + virtual void do_write() = 0; +}; + +/* ************************************************************************** */ + +class CacheFile; + +struct ImportSettings { + bool do_convert_mat; + float conversion_mat[4][4]; + + int from_up; + int from_forward; + float scale; + bool is_sequence; + bool set_frame_range; + + /* Length and frame offset of file sequences. */ + int sequence_len; + int offset; + + /* From MeshSeqCacheModifierData.read_flag */ + int read_flag; + + bool validate_meshes; + + CacheFile *cache_file; + + ImportSettings() + : do_convert_mat(false) + , from_up(0) + , from_forward(0) + , scale(1.0f) + , is_sequence(false) + , set_frame_range(false) + , sequence_len(1) + , offset(0) + , read_flag(0) + , validate_meshes(false) + , cache_file(NULL) + {} +}; + +template <typename Schema> +static bool has_animations(Schema &schema, ImportSettings *settings) +{ + if (settings->is_sequence) { + return true; + } + + if (!schema.isConstant()) { + return true; + } + + return false; +} + +/* ************************************************************************** */ + +using Alembic::AbcCoreAbstract::chrono_t; + +class AbcObjectReader { +protected: + std::string m_name; + std::string m_object_name; + std::string m_data_name; + Object *m_object; + Alembic::Abc::IObject m_iobject; + + ImportSettings *m_settings; + + chrono_t m_min_time; + chrono_t m_max_time; + +public: + explicit AbcObjectReader(const Alembic::Abc::IObject &object, ImportSettings &settings); + + virtual ~AbcObjectReader(); + + const Alembic::Abc::IObject &iobject() const; + + Object *object() const; + + virtual bool valid() const = 0; + + virtual void readObjectData(Main *bmain, float time) = 0; + + void readObjectMatrix(const float time); + + void addCacheModifier() const; + + chrono_t minTime() const; + chrono_t maxTime() const; +}; + +#endif /* __ABC_OBJECT_H__ */ diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc new file mode 100644 index 00000000000..322bb906bf5 --- /dev/null +++ b/source/blender/alembic/intern/abc_points.cc @@ -0,0 +1,199 @@ +/* + * ***** 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) 2016 Kévin Dietrich. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include "abc_points.h" + +#include "abc_mesh.h" +#include "abc_transform.h" +#include "abc_util.h" + +extern "C" { +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "BKE_lattice.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_scene.h" + +#include "BLI_math.h" +} + +using Alembic::AbcGeom::kVertexScope; +using Alembic::AbcGeom::kWrapExisting; +using Alembic::AbcGeom::P3fArraySamplePtr; +using Alembic::AbcGeom::N3fArraySamplePtr; + +using Alembic::AbcGeom::ICompoundProperty; +using Alembic::AbcGeom::IN3fArrayProperty; +using Alembic::AbcGeom::IPoints; +using Alembic::AbcGeom::IPointsSchema; +using Alembic::AbcGeom::ISampleSelector; + +using Alembic::AbcGeom::OPoints; +using Alembic::AbcGeom::OPointsSchema; + +/* ************************************************************************** */ + +AbcPointsWriter::AbcPointsWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings, + ParticleSystem *psys) + : AbcObjectWriter(scene, ob, time_sampling, settings, parent) +{ + m_psys = psys; + + OPoints points(parent->alembicXform(), m_name, m_time_sampling); + m_schema = points.getSchema(); +} + +void AbcPointsWriter::do_write() +{ + if (!m_psys) { + return; + } + + std::vector<Imath::V3f> points; + std::vector<Imath::V3f> velocities; + std::vector<float> widths; + std::vector<uint64_t> ids; + + ParticleKey state; + + ParticleSimulationData sim; + sim.scene = m_scene; + sim.ob = m_object; + sim.psys = m_psys; + + m_psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + + uint64_t index = 0; + for (int p = 0; p < m_psys->totpart; p++) { + float pos[3], vel[3]; + + if (m_psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) { + continue; + } + + state.time = BKE_scene_frame_get(m_scene); + + if (psys_get_particle_state(&sim, p, &state, 0) == 0) { + continue; + } + + /* location */ + mul_v3_m4v3(pos, m_object->imat, state.co); + + /* velocity */ + sub_v3_v3v3(vel, state.co, m_psys->particles[p].prev_state.co); + + /* Convert Z-up to Y-up. */ + points.push_back(Imath::V3f(pos[0], pos[2], -pos[1])); + velocities.push_back(Imath::V3f(vel[0], vel[2], -vel[1])); + widths.push_back(m_psys->particles[p].size); + ids.push_back(index++); + } + + if (m_psys->lattice_deform_data) { + end_latt_deform(m_psys->lattice_deform_data); + m_psys->lattice_deform_data = NULL; + } + + Alembic::Abc::P3fArraySample psample(points); + Alembic::Abc::UInt64ArraySample idsample(ids); + Alembic::Abc::V3fArraySample vsample(velocities); + Alembic::Abc::FloatArraySample wsample_array(widths); + Alembic::AbcGeom::OFloatGeomParam::Sample wsample(wsample_array, kVertexScope); + + m_sample = OPointsSchema::Sample(psample, idsample, vsample, wsample); + m_sample.setSelfBounds(bounds()); + + m_schema.set(m_sample); +} + +/* ************************************************************************** */ + +AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings) + : AbcObjectReader(object, settings) +{ + IPoints ipoints(m_iobject, kWrapExisting); + m_schema = ipoints.getSchema(); + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); +} + +bool AbcPointsReader::valid() const +{ + return m_schema.valid(); +} + +void AbcPointsReader::readObjectData(Main *bmain, float time) +{ + Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str()); + + const ISampleSelector sample_sel(time); + m_sample = m_schema.getValue(sample_sel); + + const P3fArraySamplePtr &positions = m_sample.getPositions(); + utils::mesh_add_verts(mesh, positions->size()); + + CDStreamConfig config = create_config(mesh); + read_points_sample(m_schema, sample_sel, config, time); + + if (m_settings->validate_meshes) { + BKE_mesh_validate(mesh, false, false); + } + + m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str()); + m_object->data = mesh; + + if (has_animations(m_schema, m_settings)) { + addCacheModifier(); + } +} + +void read_points_sample(const IPointsSchema &schema, + const ISampleSelector &selector, + CDStreamConfig &config, + float time) +{ + Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector); + + const P3fArraySamplePtr &positions = sample.getPositions(); + + ICompoundProperty prop = schema.getArbGeomParams(); + N3fArraySamplePtr vnormals; + + if (has_property(prop, "N")) { + const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", time); + + if (normals_prop) { + vnormals = normals_prop.getValue(selector); + } + } + + read_mverts(config.mvert, positions, vnormals); +} diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_points.h new file mode 100644 index 00000000000..51f3103bd8b --- /dev/null +++ b/source/blender/alembic/intern/abc_points.h @@ -0,0 +1,70 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 Kévin Dietrich. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef __ABC_POINTS_H__ +#define __ABC_POINTS_H__ + +#include "abc_object.h" +#include "abc_customdata.h" + +class ParticleSystem; + +/* ************************************************************************** */ + +class AbcPointsWriter : public AbcObjectWriter { + Alembic::AbcGeom::OPointsSchema m_schema; + Alembic::AbcGeom::OPointsSchema::Sample m_sample; + ParticleSystem *m_psys; + +public: + AbcPointsWriter(Scene *scene, + Object *ob, + AbcTransformWriter *parent, + uint32_t time_sampling, + ExportSettings &settings, + ParticleSystem *psys); + + void do_write(); +}; + +/* ************************************************************************** */ + +class AbcPointsReader : public AbcObjectReader { + Alembic::AbcGeom::IPointsSchema m_schema; + Alembic::AbcGeom::IPointsSchema::Sample m_sample; + +public: + AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings); + + bool valid() const; + + void readObjectData(Main *bmain, float time); +}; + +void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema, + const Alembic::AbcGeom::ISampleSelector &selector, + CDStreamConfig &config, + float time); + +#endif /* __ABC_POINTS_H__ */ diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc new file mode 100644 index 00000000000..7f8984f9970 --- /dev/null +++ b/source/blender/alembic/intern/abc_transform.cc @@ -0,0 +1,152 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "abc_transform.h" + +#include <OpenEXR/ImathBoxAlgo.h> + +#include "abc_util.h" + +extern "C" { +#include "DNA_object_types.h" + +#include "BLI_math.h" + +#include "BKE_object.h" +} + +using Alembic::AbcGeom::OObject; +using Alembic::AbcGeom::OXform; + +/* ************************************************************************** */ + +static bool has_parent_camera(Object *ob) +{ + if (!ob->parent) { + return false; + } + + Object *parent = ob->parent; + + if (parent->type == OB_CAMERA) { + return true; + } + + return has_parent_camera(parent); +} + +/* ************************************************************************** */ + +AbcTransformWriter::AbcTransformWriter(Object *ob, + const OObject &abc_parent, + AbcTransformWriter *parent, + unsigned int time_sampling, + ExportSettings &settings) + : AbcObjectWriter(NULL, ob, time_sampling, settings, parent) +{ + m_is_animated = hasAnimation(m_object); + m_parent = NULL; + + if (!m_is_animated) { + time_sampling = 0; + } + + m_xform = OXform(abc_parent, get_id_name(m_object), time_sampling); + m_schema = m_xform.getSchema(); +} + +void AbcTransformWriter::do_write() +{ + if (m_first_frame) { + m_visibility = Alembic::AbcGeom::CreateVisibilityProperty(m_xform, m_xform.getSchema().getTimeSampling()); + } + + m_visibility.set(!(m_object->restrictflag & OB_RESTRICT_VIEW)); + + if (!m_first_frame && !m_is_animated) { + return; + } + + float mat[4][4]; + create_transform_matrix(m_object, mat); + + /* Only apply rotation to root camera, parenting will propagate it. */ + if (m_object->type == OB_CAMERA && !has_parent_camera(m_object)) { + float rot_mat[4][4]; + unit_m4(rot_mat); + rotate_m4(rot_mat, 'X', -M_PI_2); + mul_m4_m4m4(mat, mat, rot_mat); + } + + if (!m_object->parent) { + /* Only apply scaling to root objects, parenting will propagate it. */ + float scale_mat[4][4]; + scale_m4_fl(scale_mat, m_settings.global_scale); + mul_m4_m4m4(mat, mat, scale_mat); + mul_v3_fl(mat[3], m_settings.global_scale); + } + + m_matrix = convert_matrix(mat); + + m_sample.setMatrix(m_matrix); + m_schema.set(m_sample); +} + +Imath::Box3d AbcTransformWriter::bounds() +{ + Imath::Box3d bounds; + + for (int i = 0; i < m_children.size(); ++i) { + Imath::Box3d box(m_children[i]->bounds()); + bounds.extendBy(box); + } + + return Imath::transform(bounds, m_matrix); +} + +bool AbcTransformWriter::hasAnimation(Object */*ob*/) const +{ + /* TODO(kevin): implement this. */ + return true; +} + +/* ************************************************************************** */ + +AbcEmptyReader::AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings) + : AbcObjectReader(object, settings) +{ + Alembic::AbcGeom::IXform xform(object, Alembic::AbcGeom::kWrapExisting); + m_schema = xform.getSchema(); + + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); +} + +bool AbcEmptyReader::valid() const +{ + return m_schema.valid(); +} + +void AbcEmptyReader::readObjectData(Main *bmain, float /*time*/) +{ + m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str()); + m_object->data = NULL; +} diff --git a/source/blender/alembic/intern/abc_transform.h b/source/blender/alembic/intern/abc_transform.h new file mode 100644 index 00000000000..6a3aae216f2 --- /dev/null +++ b/source/blender/alembic/intern/abc_transform.h @@ -0,0 +1,73 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_TRANSFORM_H__ +#define __ABC_TRANSFORM_H__ + +#include "abc_object.h" + +#include <Alembic/AbcGeom/All.h> + +/* ************************************************************************** */ + +class AbcTransformWriter : public AbcObjectWriter { + Alembic::AbcGeom::OXform m_xform; + Alembic::AbcGeom::OXformSchema m_schema; + Alembic::AbcGeom::XformSample m_sample; + Alembic::AbcGeom::OVisibilityProperty m_visibility; + Alembic::Abc::M44d m_matrix; + + bool m_is_animated; + Object *m_parent; + bool m_visible; + +public: + AbcTransformWriter(Object *ob, + const Alembic::AbcGeom::OObject &abc_parent, + AbcTransformWriter *parent, + unsigned int time_sampling, + ExportSettings &settings); + + Alembic::AbcGeom::OXform &alembicXform() { return m_xform;} + virtual Imath::Box3d bounds(); + void setParent(Object *p) { m_parent = p; } + +private: + virtual void do_write(); + + bool hasAnimation(Object *ob) const; +}; + +/* ************************************************************************** */ + +class AbcEmptyReader : public AbcObjectReader { + Alembic::AbcGeom::IXformSchema m_schema; + +public: + AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings); + + bool valid() const; + + void readObjectData(Main *bmain, float time); +}; + +#endif /* __ABC_TRANSFORM_H__ */ diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc new file mode 100644 index 00000000000..fbab0bcdf34 --- /dev/null +++ b/source/blender/alembic/intern/abc_util.cc @@ -0,0 +1,437 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "abc_util.h" + +#include <algorithm> + +extern "C" { +#include "DNA_object_types.h" + +#include "BLI_math.h" +} + +std::string get_id_name(Object *ob) +{ + if (!ob) { + return ""; + } + + return get_id_name(&ob->id); +} + +std::string get_id_name(ID *id) +{ + std::string name(id->name + 2); + std::replace(name.begin(), name.end(), ' ', '_'); + std::replace(name.begin(), name.end(), '.', '_'); + std::replace(name.begin(), name.end(), ':', '_'); + + return name; +} + +std::string get_object_dag_path_name(Object *ob, Object *dupli_parent) +{ + std::string name = get_id_name(ob); + + Object *p = ob->parent; + + while (p) { + name = get_id_name(p) + "/" + name; + p = p->parent; + } + + if (dupli_parent && (ob != dupli_parent)) { + name = get_id_name(dupli_parent) + "/" + name; + } + + return name; +} + +bool object_selected(Object *ob) +{ + return ob->flag & SELECT; +} + +bool parent_selected(Object *ob) +{ + if (object_selected(ob)) { + return true; + } + + bool do_export = false; + + Object *parent = ob->parent; + + while (parent != NULL) { + if (object_selected(parent)) { + do_export = true; + break; + } + + parent = parent->parent; + } + + return do_export; +} + +Imath::M44d convert_matrix(float mat[4][4]) +{ + Imath::M44d m; + + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + m[i][j] = mat[i][j]; + } + } + + return m; +} + +void split(const std::string &s, const char delim, std::vector<std::string> &tokens) +{ + tokens.clear(); + + std::stringstream ss(s); + std::string item; + + while (std::getline(ss, item, delim)) { + if (!item.empty()) { + tokens.push_back(item); + } + } +} + +/* Create a rotation matrix for each axis from euler angles. + * Euler angles are swaped to change coordinate system. */ +static void create_rotation_matrix( + float rot_x_mat[3][3], float rot_y_mat[3][3], + float rot_z_mat[3][3], const float euler[3], const bool to_yup) +{ + const float rx = euler[0]; + const float ry = (to_yup) ? euler[2] : -euler[2]; + const float rz = (to_yup) ? -euler[1] : euler[1]; + + unit_m3(rot_x_mat); + unit_m3(rot_y_mat); + unit_m3(rot_z_mat); + + rot_x_mat[1][1] = cos(rx); + rot_x_mat[2][1] = -sin(rx); + rot_x_mat[1][2] = sin(rx); + rot_x_mat[2][2] = cos(rx); + + rot_y_mat[2][2] = cos(ry); + rot_y_mat[0][2] = -sin(ry); + rot_y_mat[2][0] = sin(ry); + rot_y_mat[0][0] = cos(ry); + + rot_z_mat[0][0] = cos(rz); + rot_z_mat[1][0] = -sin(rz); + rot_z_mat[0][1] = sin(rz); + rot_z_mat[1][1] = cos(rz); +} + +/* Recompute transform matrix of object in new coordinate system + * (from Y-Up to Z-Up). */ +void create_transform_matrix(float r_mat[4][4]) +{ + float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], transform_mat[4][4]; + float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3]; + float loc[3], scale[3], euler[3]; + + zero_v3(loc); + zero_v3(scale); + zero_v3(euler); + unit_m3(rot); + unit_m3(rot_mat); + unit_m4(scale_mat); + unit_m4(transform_mat); + unit_m4(invmat); + + /* Compute rotation matrix. */ + + /* Extract location, rotation, and scale from matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, r_mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_XYZ, rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, false); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + + /* Add rotation matrix to transformation matrix. */ + copy_m4_m3(transform_mat, rot_mat); + + /* Add translation to transformation matrix. */ + copy_yup_zup(transform_mat[3], loc); + + /* Create scale matrix. */ + scale_mat[0][0] = scale[0]; + scale_mat[1][1] = scale[2]; + scale_mat[2][2] = scale[1]; + + /* Add scale to transformation matrix. */ + mul_m4_m4m4(transform_mat, transform_mat, scale_mat); + + copy_m4_m4(r_mat, transform_mat); +} + +void create_input_transform(const Alembic::AbcGeom::ISampleSelector &sample_sel, + const Alembic::AbcGeom::IXform &ixform, Object *ob, + float r_mat[4][4], float scale, bool has_alembic_parent) +{ + + const Alembic::AbcGeom::IXformSchema &ixform_schema = ixform.getSchema(); + Alembic::AbcGeom::XformSample xs; + ixform_schema.get(xs, sample_sel); + const Imath::M44d &xform = xs.getMatrix(); + + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + r_mat[i][j] = xform[i][j]; + } + } + + if (ob->type == OB_CAMERA) { + float cam_to_yup[4][4]; + unit_m4(cam_to_yup); + rotate_m4(cam_to_yup, 'X', M_PI_2); + mul_m4_m4m4(r_mat, r_mat, cam_to_yup); + } + + create_transform_matrix(r_mat); + + if (ob->parent) { + mul_m4_m4m4(r_mat, ob->parent->obmat, r_mat); + } + /* TODO(kevin) */ + else if (!has_alembic_parent) { + /* Only apply scaling to root objects, parenting will propagate it. */ + float scale_mat[4][4]; + scale_m4_fl(scale_mat, scale); + mul_m4_m4m4(r_mat, r_mat, scale_mat); + mul_v3_fl(r_mat[3], scale); + } +} + +/* Recompute transform matrix of object in new coordinate system (from Z-Up to Y-Up). */ +void create_transform_matrix(Object *obj, float transform_mat[4][4]) +{ + float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], mat[4][4]; + float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3]; + float loc[3], scale[3], euler[3]; + + zero_v3(loc); + zero_v3(scale); + zero_v3(euler); + unit_m3(rot); + unit_m3(rot_mat); + unit_m4(scale_mat); + unit_m4(transform_mat); + unit_m4(invmat); + unit_m4(mat); + + /* get local matrix. */ + if (obj->parent) { + invert_m4_m4(invmat, obj->parent->obmat); + mul_m4_m4m4(mat, invmat, obj->obmat); + } + else { + copy_m4_m4(mat, obj->obmat); + } + + /* Compute rotation matrix. */ + switch (obj->rotmode) { + case ROT_MODE_AXISANGLE: + { + /* Get euler angles from axis angle rotation. */ + axis_angle_to_eulO(euler, ROT_MODE_XYZ, obj->rotAxis, obj->rotAngle); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + + /* Extract location and scale from matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, mat); + + break; + } + case ROT_MODE_QUAT: + { + float q[4]; + copy_v4_v4(q, obj->quat); + + /* Swap axis. */ + q[2] = obj->quat[3]; + q[3] = -obj->quat[2]; + + /* Compute rotation matrix from quaternion. */ + quat_to_mat3(rot_mat, q); + + /* Extract location and scale from matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, mat); + + break; + } + case ROT_MODE_XYZ: + { + /* Extract location, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_XYZ, rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + + break; + } + case ROT_MODE_XZY: + { + /* Extract location, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_XZY, rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + + break; + } + case ROT_MODE_YXZ: + { + /* Extract location, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_YXZ, rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); + + break; + } + case ROT_MODE_YZX: + { + /* Extract location, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_YZX, rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); + + break; + } + case ROT_MODE_ZXY: + { + /* Extract location, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_ZXY, rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); + + break; + } + case ROT_MODE_ZYX: + { + /* Extract location, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(loc, rot, scale, mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_ZYX, rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); + mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); + + break; + } + } + + /* Add rotation matrix to transformation matrix. */ + copy_m4_m3(transform_mat, rot_mat); + + /* Add translation to transformation matrix. */ + copy_zup_yup(transform_mat[3], loc); + + /* Create scale matrix. */ + scale_mat[0][0] = scale[0]; + scale_mat[1][1] = scale[2]; + scale_mat[2][2] = scale[1]; + + /* Add scale to transformation matrix. */ + mul_m4_m4m4(transform_mat, transform_mat, scale_mat); +} + +bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name) +{ + if (!prop.valid()) { + return false; + } + + return prop.getPropertyHeader(name) != NULL; +} diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h new file mode 100644 index 00000000000..648570f5f27 --- /dev/null +++ b/source/blender/alembic/intern/abc_util.h @@ -0,0 +1,137 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __ABC_UTIL_H__ +#define __ABC_UTIL_H__ + +#include <Alembic/Abc/All.h> +#include <Alembic/AbcGeom/All.h> + +#ifdef _MSC_VER +# define ABC_INLINE static __forceinline +#else +# define ABC_INLINE static inline +#endif + +using Alembic::Abc::chrono_t; + +class ImportSettings; + +struct ID; +struct Object; + +std::string get_id_name(ID *id); +std::string get_id_name(Object *ob); +std::string get_object_dag_path_name(Object *ob, Object *dupli_parent); + +bool object_selected(Object *ob); +bool parent_selected(Object *ob); + +Imath::M44d convert_matrix(float mat[4][4]); +void create_transform_matrix(float r_mat[4][4]); +void create_transform_matrix(Object *obj, float transform_mat[4][4]); + +void split(const std::string &s, const char delim, std::vector<std::string> &tokens); + +template<class TContainer> +bool begins_with(const TContainer &input, const TContainer &match) +{ + return input.size() >= match.size() + && std::equal(match.begin(), match.end(), input.begin()); +} + +void create_input_transform(const Alembic::AbcGeom::ISampleSelector &sample_sel, + const Alembic::AbcGeom::IXform &ixform, Object *ob, + float r_mat[4][4], float scale, bool has_alembic_parent = false); + +template <typename Schema> +void get_min_max_time_ex(const Schema &schema, chrono_t &min, chrono_t &max) +{ + const Alembic::Abc::TimeSamplingPtr &time_samp = schema.getTimeSampling(); + + if (!schema.isConstant()) { + const size_t num_samps = schema.getNumSamples(); + + if (num_samps > 0) { + const chrono_t min_time = time_samp->getSampleTime(0); + min = std::min(min, min_time); + + const chrono_t max_time = time_samp->getSampleTime(num_samps - 1); + max = std::max(max, max_time); + } + } +} + +template <typename Schema> +void get_min_max_time(const Alembic::AbcGeom::IObject &object, const Schema &schema, chrono_t &min, chrono_t &max) +{ + get_min_max_time_ex(schema, min, max); + + const Alembic::AbcGeom::IObject &parent = object.getParent(); + if (parent.valid() && Alembic::AbcGeom::IXform::matches(parent.getMetaData())) { + Alembic::AbcGeom::IXform xform(parent, Alembic::AbcGeom::kWrapExisting); + get_min_max_time_ex(xform.getSchema(), min, max); + } +} + +bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name); + +/* ************************** */ + +/* TODO(kevin): for now keeping these transformations hardcoded to make sure + * everything works properly, and also because Alembic is almost exclusively + * used in Y-up software, but eventually they'll be set by the user in the UI + * like other importers/exporters do, to support other axis. */ + +/* Copy from Y-up to Z-up. */ + +ABC_INLINE void copy_yup_zup(float zup[3], const float yup[3]) +{ + zup[0] = yup[0]; + zup[1] = -yup[2]; + zup[2] = yup[1]; +} + +ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3]) +{ + zup[0] = yup[0]; + zup[1] = -yup[2]; + zup[2] = yup[1]; +} + +/* Copy from Z-up to Y-up. */ + +ABC_INLINE void copy_zup_yup(float yup[3], const float zup[3]) +{ + yup[0] = zup[0]; + yup[1] = zup[2]; + yup[2] = -zup[1]; +} + +ABC_INLINE void copy_zup_yup(short yup[3], const short zup[3]) +{ + yup[0] = zup[0]; + yup[1] = zup[2]; + yup[2] = -zup[1]; +} + +#endif /* __ABC_UTIL_H__ */ diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc new file mode 100644 index 00000000000..d057cc341f6 --- /dev/null +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -0,0 +1,1196 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../ABC_alembic.h" + +#ifdef WITH_ALEMBIC_HDF5 +# include <Alembic/AbcCoreHDF5/All.h> +#endif + +#include <Alembic/AbcCoreOgawa/All.h> +#include <Alembic/AbcMaterial/IMaterial.h> + +#include <fstream> + +#ifdef WIN32 +# include "utfconv.h" +#endif + +#include "abc_camera.h" +#include "abc_curves.h" +#include "abc_hair.h" +#include "abc_mesh.h" +#include "abc_nurbs.h" +#include "abc_points.h" +#include "abc_transform.h" +#include "abc_util.h" + +extern "C" { +#include "MEM_guardedalloc.h" + +#include "DNA_cachefile_types.h" +#include "DNA_curve_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_cachefile.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_scene.h" + +/* SpaceType struct has a member called 'new' which obviously conflicts with C++ + * so temporarily redefining the new keyword to make it compile. */ +#define new extern_new +#include "BKE_screen.h" +#undef new + +#include "BLI_fileops.h" +#include "BLI_ghash.h" +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_path_util.h" +#include "BLI_string.h" + +#include "WM_api.h" +#include "WM_types.h" +} + +using Alembic::Abc::Int32ArraySamplePtr; +using Alembic::Abc::ObjectHeader; + +using Alembic::AbcGeom::ErrorHandler; +using Alembic::AbcGeom::Exception; +using Alembic::AbcGeom::MetaData; +using Alembic::AbcGeom::P3fArraySamplePtr; +using Alembic::AbcGeom::kWrapExisting; + +using Alembic::AbcGeom::IArchive; +using Alembic::AbcGeom::ICamera; +using Alembic::AbcGeom::ICurves; +using Alembic::AbcGeom::ICurvesSchema; +using Alembic::AbcGeom::IFaceSet; +using Alembic::AbcGeom::ILight; +using Alembic::AbcGeom::INuPatch; +using Alembic::AbcGeom::IObject; +using Alembic::AbcGeom::IPoints; +using Alembic::AbcGeom::IPointsSchema; +using Alembic::AbcGeom::IPolyMesh; +using Alembic::AbcGeom::IPolyMeshSchema; +using Alembic::AbcGeom::ISampleSelector; +using Alembic::AbcGeom::ISubD; +using Alembic::AbcGeom::IV2fGeomParam; +using Alembic::AbcGeom::IXform; +using Alembic::AbcGeom::IXformSchema; +using Alembic::AbcGeom::N3fArraySamplePtr; +using Alembic::AbcGeom::XformSample; +using Alembic::AbcGeom::ICompoundProperty; +using Alembic::AbcGeom::IN3fArrayProperty; +using Alembic::AbcGeom::IN3fGeomParam; +using Alembic::AbcGeom::V3fArraySamplePtr; + +using Alembic::AbcMaterial::IMaterial; + +static IArchive open_archive(const std::string &filename, + const std::vector<std::istream *> &input_streams, + bool &is_hdf5) +{ + try { + is_hdf5 = false; + Alembic::AbcCoreOgawa::ReadArchive archive_reader(input_streams); + + return IArchive(archive_reader(filename), + kWrapExisting, + ErrorHandler::kThrowPolicy); + } + catch (const Exception &e) { + std::cerr << e.what() << '\n'; + +#ifdef WITH_ALEMBIC_HDF5 + try { + is_hdf5 = true; + Alembic::AbcCoreAbstract::ReadArraySampleCachePtr cache_ptr; + + return IArchive(Alembic::AbcCoreHDF5::ReadArchive(), + filename.c_str(), ErrorHandler::kThrowPolicy, + cache_ptr); + } + catch (const Exception &) { + std::cerr << e.what() << '\n'; + return IArchive(); + } +#else + return IArchive(); +#endif + } + + return IArchive(); +} + +/* Wrapper around an archive to be able to use streams so that unicode paths + * work on Windows (T49112), and to make sure the input stream remains valid as + * long as the archive is open. */ +class ArchiveWrapper { + IArchive m_archive; + std::ifstream m_infile; + std::vector<std::istream *> m_streams; + +public: + explicit ArchiveWrapper(const char *filename) + { +#ifdef WIN32 + UTF16_ENCODE(filename); + std::wstring wstr(filename_16); + m_infile.open(wstr.c_str(), std::ios::in | std::ios::binary); + UTF16_UN_ENCODE(filename); +#else + m_infile.open(filename, std::ios::in | std::ios::binary); +#endif + + m_streams.push_back(&m_infile); + + bool is_hdf5; + m_archive = open_archive(filename, m_streams, is_hdf5); + + /* We can't open an HDF5 file from a stream, so close it. */ + if (is_hdf5) { + m_infile.close(); + m_streams.clear(); + } + } + + bool valid() const + { + return m_archive.valid(); + } + + IObject getTop() + { + return m_archive.getTop(); + } +}; + +struct AbcArchiveHandle { + int unused; +}; + +ABC_INLINE ArchiveWrapper *archive_from_handle(AbcArchiveHandle *handle) +{ + return reinterpret_cast<ArchiveWrapper *>(handle); +} + +ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveWrapper *archive) +{ + return reinterpret_cast<AbcArchiveHandle *>(archive); +} + +//#define USE_NURBS + +/* NOTE: this function is similar to visit_objects below, need to keep them in + * sync. */ +static void gather_objects_paths(const IObject &object, ListBase *object_paths) +{ + if (!object.valid()) { + return; + } + + for (int i = 0; i < object.getNumChildren(); ++i) { + IObject child = object.getChild(i); + + if (!child.valid()) { + continue; + } + + bool get_path = false; + + const MetaData &md = child.getMetaData(); + + if (IXform::matches(md)) { + /* Check whether or not this object is a Maya locator, which is + * similar to empties used as parent object in Blender. */ + if (has_property(child.getProperties(), "locator")) { + get_path = true; + } + else { + /* Avoid creating an empty object if the child of this transform + * is not a transform (that is an empty). */ + if (child.getNumChildren() == 1) { + if (IXform::matches(child.getChild(0).getMetaData())) { + get_path = true; + } +#if 0 + else { + std::cerr << "Skipping " << child.getFullName() << '\n'; + } +#endif + } + else { + get_path = true; + } + } + } + else if (IPolyMesh::matches(md)) { + get_path = true; + } + else if (ISubD::matches(md)) { + get_path = true; + } + else if (INuPatch::matches(md)) { +#ifdef USE_NURBS + get_path = true; +#endif + } + else if (ICamera::matches(md)) { + get_path = true; + } + else if (IPoints::matches(md)) { + get_path = true; + } + else if (IMaterial::matches(md)) { + /* Pass for now. */ + } + else if (ILight::matches(md)) { + /* Pass for now. */ + } + else if (IFaceSet::matches(md)) { + /* Pass, those are handled in the mesh reader. */ + } + else if (ICurves::matches(md)) { + get_path = true; + } + else { + assert(false); + } + + if (get_path) { + AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>( + MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath")); + + BLI_strncpy(abc_path->path, child.getFullName().c_str(), PATH_MAX); + + BLI_addtail(object_paths, abc_path); + } + + gather_objects_paths(child, object_paths); + } +} + +AbcArchiveHandle *ABC_create_handle(const char *filename, ListBase *object_paths) +{ + ArchiveWrapper *archive = new ArchiveWrapper(filename); + + if (!archive->valid()) { + delete archive; + return NULL; + } + + if (object_paths) { + gather_objects_paths(archive->getTop(), object_paths); + } + + return handle_from_archive(archive); +} + +void ABC_free_handle(AbcArchiveHandle *handle) +{ + delete archive_from_handle(handle); +} + +int ABC_get_version() +{ + return ALEMBIC_LIBRARY_VERSION; +} + +static void find_iobject(const IObject &object, IObject &ret, + const std::string &path) +{ + if (!object.valid()) { + return; + } + + std::vector<std::string> tokens; + split(path, '/', tokens); + + IObject tmp = object; + + std::vector<std::string>::iterator iter; + for (iter = tokens.begin(); iter != tokens.end(); ++iter) { + IObject child = tmp.getChild(*iter); + tmp = child; + } + + ret = tmp; +} + +struct ExportJobData { + Scene *scene; + Main *bmain; + + char filename[1024]; + ExportSettings settings; + + short *stop; + short *do_update; + float *progress; + + bool was_canceled; +}; + +static void export_startjob(void *customdata, short *stop, short *do_update, float *progress) +{ + ExportJobData *data = static_cast<ExportJobData *>(customdata); + + data->stop = stop; + data->do_update = do_update; + data->progress = progress; + + /* XXX annoying hack: needed to prevent data corruption when changing + * scene frame in separate threads + */ + G.is_rendering = true; + BKE_spacedata_draw_locks(true); + + G.is_break = false; + + try { + Scene *scene = data->scene; + AbcExporter exporter(scene, data->filename, data->settings); + + const int orig_frame = CFRA; + + data->was_canceled = false; + exporter(data->bmain, *data->progress, data->was_canceled); + + if (CFRA != orig_frame) { + CFRA = orig_frame; + + BKE_scene_update_for_newframe(data->bmain->eval_ctx, data->bmain, + scene, scene->lay); + } + } + catch (const std::exception &e) { + std::cerr << "Abc Export error: " << e.what() << '\n'; + } + catch (...) { + std::cerr << "Abc Export error\n"; + } +} + +static void export_endjob(void *customdata) +{ + ExportJobData *data = static_cast<ExportJobData *>(customdata); + + if (data->was_canceled && BLI_exists(data->filename)) { + BLI_delete(data->filename, false, false); + } + + G.is_rendering = false; + BKE_spacedata_draw_locks(false); +} + +void ABC_export( + Scene *scene, + bContext *C, + const char *filepath, + const struct AlembicExportParams *params) +{ + ExportJobData *job = static_cast<ExportJobData *>(MEM_mallocN(sizeof(ExportJobData), "ExportJobData")); + job->scene = scene; + job->bmain = CTX_data_main(C); + BLI_strncpy(job->filename, filepath, 1024); + + job->settings.scene = job->scene; + job->settings.frame_start = params->frame_start; + job->settings.frame_end = params->frame_end; + job->settings.frame_step_xform = params->frame_step_xform; + job->settings.frame_step_shape = params->frame_step_shape; + job->settings.shutter_open = params->shutter_open; + job->settings.shutter_close = params->shutter_close; + job->settings.selected_only = params->selected_only; + job->settings.export_face_sets = params->face_sets; + job->settings.export_normals = params->normals; + job->settings.export_uvs = params->uvs; + job->settings.export_vcols = params->vcolors; + job->settings.apply_subdiv = params->apply_subdiv; + job->settings.flatten_hierarchy = params->flatten_hierarchy; + job->settings.visible_layers_only = params->visible_layers_only; + job->settings.renderable_only = params->renderable_only; + job->settings.use_subdiv_schema = params->use_subdiv_schema; + job->settings.export_ogawa = (params->compression_type == ABC_ARCHIVE_OGAWA); + job->settings.pack_uv = params->packuv; + job->settings.global_scale = params->global_scale; + + if (job->settings.frame_start > job->settings.frame_end) { + std::swap(job->settings.frame_start, job->settings.frame_end); + } + + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + job->scene, + "Alembic Export", + WM_JOB_PROGRESS, + WM_JOB_TYPE_ALEMBIC); + + /* setup job */ + WM_jobs_customdata_set(wm_job, job, MEM_freeN); + WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME); + WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob); + + WM_jobs_start(CTX_wm_manager(C), wm_job); +} + +/* ********************** Import file ********************** */ + +static void visit_object(const IObject &object, + std::vector<AbcObjectReader *> &readers, + GHash *parent_map, + ImportSettings &settings) +{ + if (!object.valid()) { + return; + } + + for (int i = 0; i < object.getNumChildren(); ++i) { + IObject child = object.getChild(i); + + if (!child.valid()) { + continue; + } + + AbcObjectReader *reader = NULL; + + const MetaData &md = child.getMetaData(); + + if (IXform::matches(md)) { + bool create_xform = false; + + /* Check whether or not this object is a Maya locator, which is + * similar to empties used as parent object in Blender. */ + if (has_property(child.getProperties(), "locator")) { + create_xform = true; + } + else { + /* Avoid creating an empty object if the child of this transform + * is not a transform (that is an empty). */ + if (child.getNumChildren() == 1) { + if (IXform::matches(child.getChild(0).getMetaData())) { + create_xform = true; + } +#if 0 + else { + std::cerr << "Skipping " << child.getFullName() << '\n'; + } +#endif + } + else { + create_xform = true; + } + } + + if (create_xform) { + reader = new AbcEmptyReader(child, settings); + } + } + else if (IPolyMesh::matches(md)) { + reader = new AbcMeshReader(child, settings); + } + else if (ISubD::matches(md)) { + reader = new AbcSubDReader(child, settings); + } + else if (INuPatch::matches(md)) { +#ifdef USE_NURBS + /* TODO(kevin): importing cyclic NURBS from other software crashes + * at the moment. This is due to the fact that NURBS in other + * software have duplicated points which causes buffer overflows in + * Blender. Need to figure out exactly how these points are + * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV). + * Until this is fixed, disabling NURBS reading. */ + reader = new AbcNurbsReader(child, settings); +#endif + } + else if (ICamera::matches(md)) { + reader = new AbcCameraReader(child, settings); + } + else if (IPoints::matches(md)) { + reader = new AbcPointsReader(child, settings); + } + else if (IMaterial::matches(md)) { + /* Pass for now. */ + } + else if (ILight::matches(md)) { + /* Pass for now. */ + } + else if (IFaceSet::matches(md)) { + /* Pass, those are handled in the mesh reader. */ + } + else if (ICurves::matches(md)) { + reader = new AbcCurveReader(child, settings); + } + else { + assert(false); + } + + if (reader) { + readers.push_back(reader); + + AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>( + MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath")); + + BLI_strncpy(abc_path->path, child.getFullName().c_str(), PATH_MAX); + + BLI_addtail(&settings.cache_file->object_paths, abc_path); + + /* Cast to `void *` explicitly to avoid compiler errors because it + * is a `const char *` which the compiler cast to `const void *` + * instead of the expected `void *`. */ + BLI_ghash_insert(parent_map, (void *)child.getFullName().c_str(), reader); + } + + visit_object(child, readers, parent_map, settings); + } +} + +enum { + ABC_NO_ERROR = 0, + ABC_ARCHIVE_FAIL, +}; + +struct ImportJobData { + Main *bmain; + Scene *scene; + + char filename[1024]; + ImportSettings settings; + + GHash *parent_map; + std::vector<AbcObjectReader *> readers; + + short *stop; + short *do_update; + float *progress; + + char error_code; + bool was_cancelled; +}; + +ABC_INLINE bool is_mesh_and_strands(const IObject &object) +{ + if (object.getNumChildren() != 2) { + return false; + } + + bool has_mesh = false; + bool has_curve = false; + + for (int i = 0; i < object.getNumChildren(); ++i) { + const IObject &child = object.getChild(i); + + if (!child.valid()) { + continue; + } + + const MetaData &md = child.getMetaData(); + + if (IPolyMesh::matches(md)) { + has_mesh = true; + } + else if (ISubD::matches(md)) { + has_mesh = true; + } + else if (ICurves::matches(md)) { + has_curve = true; + } + } + + return has_mesh && has_curve; +} + +static void import_startjob(void *user_data, short *stop, short *do_update, float *progress) +{ + ImportJobData *data = static_cast<ImportJobData *>(user_data); + + data->stop = stop; + data->do_update = do_update; + data->progress = progress; + + ArchiveWrapper *archive = new ArchiveWrapper(data->filename); + + if (!archive->valid()) { + delete archive; + data->error_code = ABC_ARCHIVE_FAIL; + return; + } + + CacheFile *cache_file = static_cast<CacheFile *>(BKE_cachefile_add(data->bmain, BLI_path_basename(data->filename))); + + /* Decrement the ID ref-count because it is going to be incremented for each + * modifier and constraint that it will be attached to, so since currently + * it is not used by anyone, its use count will off by one. */ + id_us_min(&cache_file->id); + + cache_file->is_sequence = data->settings.is_sequence; + cache_file->scale = data->settings.scale; + cache_file->handle = handle_from_archive(archive); + BLI_strncpy(cache_file->filepath, data->filename, 1024); + + data->settings.cache_file = cache_file; + + *data->do_update = true; + *data->progress = 0.05f; + + data->parent_map = BLI_ghash_str_new("alembic parent ghash"); + + /* Parse Alembic Archive. */ + + visit_object(archive->getTop(), data->readers, data->parent_map, data->settings); + + if (G.is_break) { + data->was_cancelled = true; + return; + } + + *data->do_update = true; + *data->progress = 0.1f; + + /* Create objects and set scene frame range. */ + + const float size = static_cast<float>(data->readers.size()); + size_t i = 0; + + chrono_t min_time = std::numeric_limits<chrono_t>::max(); + chrono_t max_time = std::numeric_limits<chrono_t>::min(); + + std::vector<AbcObjectReader *>::iterator iter; + for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { + AbcObjectReader *reader = *iter; + + if (reader->valid()) { + reader->readObjectData(data->bmain, 0.0f); + reader->readObjectMatrix(0.0f); + + min_time = std::min(min_time, reader->minTime()); + max_time = std::max(max_time, reader->maxTime()); + } + + *data->progress = 0.1f + 0.6f * (++i / size); + *data->do_update = true; + + if (G.is_break) { + data->was_cancelled = true; + return; + } + } + + if (data->settings.set_frame_range) { + Scene *scene = data->scene; + + if (data->settings.is_sequence) { + SFRA = data->settings.offset; + EFRA = SFRA + (data->settings.sequence_len - 1); + CFRA = SFRA; + } + else if (min_time < max_time) { + SFRA = min_time * FPS; + EFRA = max_time * FPS; + CFRA = SFRA; + } + } + + /* Setup parentship. */ + + i = 0; + for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { + const AbcObjectReader *reader = *iter; + const AbcObjectReader *parent_reader = NULL; + const IObject &iobject = reader->iobject(); + + IObject parent = iobject.getParent(); + + if (!IXform::matches(iobject.getHeader())) { + /* In the case of an non XForm node, the parent is the transform + * matrix of the data itself, so we get the its grand parent. + */ + + /* Special case with object only containing a mesh and some strands, + * we want both objects to be parented to the same object. */ + if (!is_mesh_and_strands(parent)) { + parent = parent.getParent(); + } + } + + parent_reader = reinterpret_cast<AbcObjectReader *>( + BLI_ghash_lookup(data->parent_map, parent.getFullName().c_str())); + + if (parent_reader) { + Object *parent = parent_reader->object(); + + if (parent != NULL && reader->object() != parent) { + Object *ob = reader->object(); + ob->parent = parent; + } + } + + *data->progress = 0.7f + 0.3f * (++i / size); + *data->do_update = true; + + if (G.is_break) { + data->was_cancelled = true; + return; + } + } +} + +static void import_endjob(void *user_data) +{ + ImportJobData *data = static_cast<ImportJobData *>(user_data); + + std::vector<AbcObjectReader *>::iterator iter; + + /* Delete objects on cancelation. */ + if (data->was_cancelled) { + for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { + Object *ob = (*iter)->object(); + + if (ob->data) { + BKE_libblock_free_us(data->bmain, ob->data); + ob->data = NULL; + } + + BKE_libblock_free_us(data->bmain, ob); + } + } + else { + /* Add object to scene. */ + BKE_scene_base_deselect_all(data->scene); + + for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { + Object *ob = (*iter)->object(); + ob->lay = data->scene->lay; + + BKE_scene_base_add(data->scene, ob); + + DAG_id_tag_update_ex(data->bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + } + + DAG_relations_tag_update(data->bmain); + } + + for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { + delete *iter; + } + + if (data->parent_map) { + BLI_ghash_free(data->parent_map, NULL, NULL); + } + + switch (data->error_code) { + default: + case ABC_NO_ERROR: + break; + case ABC_ARCHIVE_FAIL: + WM_report(RPT_ERROR, "Could not open Alembic archive for reading! See console for detail."); + break; + } + + WM_main_add_notifier(NC_SCENE | ND_FRAME, data->scene); +} + +static void import_freejob(void *user_data) +{ + ImportJobData *data = static_cast<ImportJobData *>(user_data); + delete data; +} + +void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence, bool set_frame_range, int sequence_len, int offset, bool validate_meshes) +{ + /* Using new here since MEM_* funcs do not call ctor to properly initialize + * data. */ + ImportJobData *job = new ImportJobData(); + job->bmain = CTX_data_main(C); + job->scene = CTX_data_scene(C); + BLI_strncpy(job->filename, filepath, 1024); + + job->settings.scale = scale; + job->settings.is_sequence = is_sequence; + job->settings.set_frame_range = set_frame_range; + job->settings.sequence_len = sequence_len; + job->settings.offset = offset; + job->settings.validate_meshes = validate_meshes; + job->parent_map = NULL; + job->error_code = ABC_NO_ERROR; + job->was_cancelled = false; + + G.is_break = false; + + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + job->scene, + "Alembic Import", + WM_JOB_PROGRESS, + WM_JOB_TYPE_ALEMBIC); + + /* setup job */ + WM_jobs_customdata_set(wm_job, job, import_freejob); + WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME); + WM_jobs_callbacks(wm_job, import_startjob, NULL, NULL, import_endjob); + + WM_jobs_start(CTX_wm_manager(C), wm_job); +} + +/* ******************************* */ + +void ABC_get_transform(AbcArchiveHandle *handle, Object *ob, const char *object_path, float r_mat[4][4], float time, float scale) +{ + ArchiveWrapper *archive = archive_from_handle(handle); + + if (!archive || !archive->valid()) { + return; + } + + IObject tmp; + find_iobject(archive->getTop(), tmp, object_path); + + IXform ixform; + + if (IXform::matches(tmp.getHeader())) { + ixform = IXform(tmp, kWrapExisting); + } + else { + ixform = IXform(tmp.getParent(), kWrapExisting); + } + + IXformSchema schema = ixform.getSchema(); + + if (!schema.valid()) { + return; + } + + ISampleSelector sample_sel(time); + + create_input_transform(sample_sel, ixform, ob, r_mat, scale); +} + +/* ***************************************** */ + +static bool check_smooth_poly_flag(DerivedMesh *dm) +{ + MPoly *mpolys = dm->getPolyArray(dm); + + for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i) { + MPoly &poly = mpolys[i]; + + if ((poly.flag & ME_SMOOTH) != 0) { + return true; + } + } + + return false; +} + +static void set_smooth_poly_flag(DerivedMesh *dm) +{ + MPoly *mpolys = dm->getPolyArray(dm); + + for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i) { + MPoly &poly = mpolys[i]; + poly.flag |= ME_SMOOTH; + } +} + +static void *add_customdata_cb(void *user_data, const char *name, int data_type) +{ + DerivedMesh *dm = static_cast<DerivedMesh *>(user_data); + CustomDataType cd_data_type = static_cast<CustomDataType>(data_type); + void *cd_ptr = NULL; + + if (ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) { + cd_ptr = CustomData_get_layer_named(dm->getLoopDataLayout(dm), cd_data_type, name); + + if (cd_ptr == NULL) { + cd_ptr = CustomData_add_layer_named(dm->getLoopDataLayout(dm), + cd_data_type, + CD_DEFAULT, + NULL, + dm->getNumLoops(dm), + name); + } + } + + return cd_ptr; +} + +ABC_INLINE CDStreamConfig get_config(DerivedMesh *dm) +{ + CDStreamConfig config; + + config.user_data = dm; + config.mvert = dm->getVertArray(dm); + config.mloop = dm->getLoopArray(dm); + config.mpoly = dm->getPolyArray(dm); + config.totloop = dm->getNumLoops(dm); + config.totpoly = dm->getNumPolys(dm); + config.loopdata = dm->getLoopDataLayout(dm); + config.add_customdata_cb = add_customdata_cb; + + return config; +} + +static DerivedMesh *read_mesh_sample(DerivedMesh *dm, const IObject &iobject, const float time, int read_flag) +{ + IPolyMesh mesh(iobject, kWrapExisting); + IPolyMeshSchema schema = mesh.getSchema(); + ISampleSelector sample_sel(time); + const IPolyMeshSchema::Sample sample = schema.getValue(sample_sel); + + const P3fArraySamplePtr &positions = sample.getPositions(); + const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices(); + const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts(); + + DerivedMesh *new_dm = NULL; + + /* Only read point data when streaming meshes, unless we need to create new ones. */ + ImportSettings settings; + settings.read_flag |= read_flag; + + if (dm->getNumVerts(dm) != positions->size()) { + new_dm = CDDM_from_template(dm, + positions->size(), + 0, + 0, + face_indices->size(), + face_counts->size()); + + settings.read_flag |= MOD_MESHSEQ_READ_ALL; + } + + CDStreamConfig config = get_config(new_dm ? new_dm : dm); + + bool do_normals = false; + read_mesh_sample(&settings, schema, sample_sel, config, do_normals); + + if (new_dm) { + /* Check if we had ME_SMOOTH flag set to restore it. */ + if (!do_normals && check_smooth_poly_flag(dm)) { + set_smooth_poly_flag(new_dm); + } + + CDDM_calc_normals(new_dm); + CDDM_calc_edges(new_dm); + + return new_dm; + } + + if (do_normals) { + CDDM_calc_normals(dm); + } + + return dm; +} + +using Alembic::AbcGeom::ISubDSchema; + +static DerivedMesh *read_subd_sample(DerivedMesh *dm, const IObject &iobject, const float time, int read_flag) +{ + ISubD mesh(iobject, kWrapExisting); + ISubDSchema schema = mesh.getSchema(); + ISampleSelector sample_sel(time); + const ISubDSchema::Sample sample = schema.getValue(sample_sel); + + const P3fArraySamplePtr &positions = sample.getPositions(); + const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices(); + const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts(); + + DerivedMesh *new_dm = NULL; + + ImportSettings settings; + settings.read_flag |= read_flag; + + if (dm->getNumVerts(dm) != positions->size()) { + new_dm = CDDM_from_template(dm, + positions->size(), + 0, + 0, + face_indices->size(), + face_counts->size()); + + settings.read_flag |= MOD_MESHSEQ_READ_ALL; + } + + /* Only read point data when streaming meshes, unless we need to create new ones. */ + CDStreamConfig config = get_config(new_dm ? new_dm : dm); + read_subd_sample(&settings, schema, sample_sel, config); + + if (new_dm) { + /* Check if we had ME_SMOOTH flag set to restore it. */ + if (check_smooth_poly_flag(dm)) { + set_smooth_poly_flag(new_dm); + } + + CDDM_calc_normals(new_dm); + CDDM_calc_edges(new_dm); + + return new_dm; + } + + return dm; +} + +static DerivedMesh *read_points_sample(DerivedMesh *dm, const IObject &iobject, const float time) +{ + IPoints points(iobject, kWrapExisting); + IPointsSchema schema = points.getSchema(); + ISampleSelector sample_sel(time); + const IPointsSchema::Sample sample = schema.getValue(sample_sel); + + const P3fArraySamplePtr &positions = sample.getPositions(); + + DerivedMesh *new_dm = NULL; + + if (dm->getNumVerts(dm) != positions->size()) { + new_dm = CDDM_new(positions->size(), 0, 0, 0, 0); + } + + CDStreamConfig config = get_config(new_dm ? new_dm : dm); + read_points_sample(schema, sample_sel, config, time); + + return new_dm ? new_dm : dm; +} + +/* NOTE: Alembic only stores data about control points, but the DerivedMesh + * passed from the cache modifier contains the displist, which has more data + * than the control points, so to avoid corrupting the displist we modify the + * object directly and create a new DerivedMesh from that. Also we might need to + * create new or delete existing NURBS in the curve. + */ +static DerivedMesh *read_curves_sample(Object *ob, const IObject &iobject, const float time) +{ + ICurves points(iobject, kWrapExisting); + ICurvesSchema schema = points.getSchema(); + ISampleSelector sample_sel(time); + const ICurvesSchema::Sample sample = schema.getValue(sample_sel); + + const P3fArraySamplePtr &positions = sample.getPositions(); + const Int32ArraySamplePtr num_vertices = sample.getCurvesNumVertices(); + + int vertex_idx = 0; + int curve_idx = 0; + Curve *curve = static_cast<Curve *>(ob->data); + + const int curve_count = BLI_listbase_count(&curve->nurb); + + if (curve_count != num_vertices->size()) { + BKE_nurbList_free(&curve->nurb); + read_curve_sample(curve, schema, time); + } + else { + Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first); + for (; nurbs; nurbs = nurbs->next, ++curve_idx) { + const int totpoint = (*num_vertices)[curve_idx]; + + if (nurbs->bp) { + BPoint *point = nurbs->bp; + + for (int i = 0; i < totpoint; ++i, ++point, ++vertex_idx) { + const Imath::V3f &pos = (*positions)[vertex_idx]; + copy_yup_zup(point->vec, pos.getValue()); + } + } + else if (nurbs->bezt) { + BezTriple *bezier = nurbs->bezt; + + for (int i = 0; i < totpoint; ++i, ++bezier, ++vertex_idx) { + const Imath::V3f &pos = (*positions)[vertex_idx]; + copy_yup_zup(bezier->vec[1], pos.getValue()); + } + } + } + } + + return CDDM_from_curve(ob); +} + +DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle, + Object *ob, + DerivedMesh *dm, + const char *object_path, + const float time, + const char **err_str, + int read_flag) +{ + ArchiveWrapper *archive = archive_from_handle(handle); + + if (!archive || !archive->valid()) { + *err_str = "Invalid archive!"; + return NULL; + } + + IObject iobject; + find_iobject(archive->getTop(), iobject, object_path); + + if (!iobject.valid()) { + *err_str = "Invalid object: verify object path"; + return NULL; + } + + const ObjectHeader &header = iobject.getHeader(); + + if (IPolyMesh::matches(header)) { + if (ob->type != OB_MESH) { + *err_str = "Object type mismatch: object path points to a mesh!"; + return NULL; + } + + return read_mesh_sample(dm, iobject, time, read_flag); + } + else if (ISubD::matches(header)) { + if (ob->type != OB_MESH) { + *err_str = "Object type mismatch: object path points to a subdivision mesh!"; + return NULL; + } + + return read_subd_sample(dm, iobject, time, read_flag); + } + else if (IPoints::matches(header)) { + if (ob->type != OB_MESH) { + *err_str = "Object type mismatch: object path points to a point cloud (requires a mesh object)!"; + return NULL; + } + + return read_points_sample(dm, iobject, time); + } + else if (ICurves::matches(header)) { + if (ob->type != OB_CURVE) { + *err_str = "Object type mismatch: object path points to a curve!"; + return NULL; + } + + return read_curves_sample(ob, iobject, time); + } + + *err_str = "Unsupported object type: verify object path"; // or poke developer + return NULL; +} diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 483fefbd89c..189340db618 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,8 +27,8 @@ /* these lines are grep'd, watch out for our not-so-awesome regex * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ -#define BLENDER_VERSION 277 -#define BLENDER_SUBVERSION 3 +#define BLENDER_VERSION 278 +#define BLENDER_SUBVERSION 0 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 6 @@ -37,7 +37,7 @@ /* can be left blank, otherwise a,b,c... etc with no quotes */ #define BLENDER_VERSION_CHAR /* alpha/beta/rc/release, docs use this */ -#define BLENDER_VERSION_CYCLE alpha +#define BLENDER_VERSION_CYCLE rc extern char versionstr[]; /* from blender.c */ diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h new file mode 100644 index 00000000000..7a9744ef9d6 --- /dev/null +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -0,0 +1,69 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Kevin Dietrich. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_CACHEFILE_H__ +#define __BKE_CACHEFILE_H__ + +/** \file BKE_cachefile.h + * \ingroup bke + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct CacheFile; +struct Main; +struct Scene; + +void BKE_cachefiles_init(void); + +void *BKE_cachefile_add(struct Main *bmain, const char *name); + +void BKE_cachefile_init(struct CacheFile *cache_file); + +void BKE_cachefile_free(struct CacheFile *cache_file); + +struct CacheFile *BKE_cachefile_copy(struct Main *bmain, struct CacheFile *cache_file); + +void BKE_cachefile_make_local(struct Main *bmain, struct CacheFile *cache_file, const bool lib_local); + +void BKE_cachefile_reload(const struct Main *bmain, struct CacheFile *cache_file); + +void BKE_cachefile_ensure_handle(const struct Main *bmain, struct CacheFile *cache_file); + +void BKE_cachefile_update_frame(struct Main *bmain, struct Scene *scene, float ctime, const float fps); + +bool BKE_cachefile_filepath_get( + const struct Main *bmain, const struct CacheFile *cache_file, float frame, + char r_filename[1024]); + +float BKE_cachefile_time_offset(struct CacheFile *cache_file, const float time, const float fps); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_CACHEFILE_H__ */ diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index d5b4a584ec6..8fedcd4ab06 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -146,6 +146,10 @@ void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct ///////////////////////////////////////////////// // used in effect.c ///////////////////////////////////////////////// + +/* explicit control over layer mask and dupli recursion */ +struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli); + struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type); typedef struct ColliderCache { diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 30ac310c2df..4da6a61cbfa 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -39,6 +39,7 @@ extern "C" { struct ARegion; struct bScreen; +struct CacheFile; struct ListBase; struct Main; struct Object; @@ -271,6 +272,8 @@ struct Text *CTX_data_edit_text(const bContext *C); struct MovieClip *CTX_data_edit_movieclip(const bContext *C); struct Mask *CTX_data_edit_mask(const bContext *C); +struct CacheFile *CTX_data_edit_cachefile(const bContext *C); + int CTX_data_selected_nodes(const bContext *C, ListBase *list); struct EditBone *CTX_data_active_bone(const bContext *C); diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index f8fee444d91..b934ec7166d 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -110,7 +110,7 @@ typedef struct EffectorCache { } EffectorCache; void free_partdeflect(struct PartDeflect *pd); -struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool precalc); +struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool for_simulation); void pdEndEffectors(struct ListBase **effectors); void pdPrecalculateEffectors(struct ListBase *effectors); void pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse); diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index cbf167de25c..ab8b83f8271 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -43,36 +43,36 @@ struct Main; /* ------------ Grease-Pencil API ------------------ */ -void free_gpencil_stroke(struct bGPDstroke *gps); -bool free_gpencil_strokes(struct bGPDframe *gpf); -void free_gpencil_frames(struct bGPDlayer *gpl); -void free_gpencil_layers(struct ListBase *list); -void free_gpencil_brushes(struct ListBase *list); -void free_gpencil_palettes(struct ListBase *list); +void BKE_gpencil_free_stroke(struct bGPDstroke *gps); +bool BKE_gpencil_free_strokes(struct bGPDframe *gpf); +void BKE_gpencil_free_frames(struct bGPDlayer *gpl); +void BKE_gpencil_free_layers(struct ListBase *list); +void BKE_gpencil_free_brushes(struct ListBase *list); +void BKE_gpencil_free_palettes(struct ListBase *list); void BKE_gpencil_free(struct bGPdata *gpd, bool free_palettes); -void gpencil_stroke_sync_selection(struct bGPDstroke *gps); +void BKE_gpencil_stroke_sync_selection(struct bGPDstroke *gps); -struct bGPDframe *gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe); -struct bGPDframe *gpencil_frame_addcopy(struct bGPDlayer *gpl, int cframe); -struct bGPDlayer *gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive); -struct bGPdata *gpencil_data_addnew(const char name[]); +struct bGPDframe *BKE_gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe); +struct bGPDframe *BKE_gpencil_frame_addcopy(struct bGPDlayer *gpl, int cframe); +struct bGPDlayer *BKE_gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive); +struct bGPdata *BKE_gpencil_data_addnew(const char name[]); -struct bGPDframe *gpencil_frame_duplicate(const struct bGPDframe *gpf_src); -struct bGPDlayer *gpencil_layer_duplicate(const struct bGPDlayer *gpl_src); -struct bGPdata *gpencil_data_duplicate(struct Main *bmain, struct bGPdata *gpd, bool internal_copy); +struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src); +struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src); +struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, struct bGPdata *gpd, bool internal_copy); void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local); -void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf); +void BKE_gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf); -struct bGPDpalette *gpencil_palette_addnew(struct bGPdata *gpd, const char *name, bool setactive); -struct bGPDpalette *gpencil_palette_duplicate(const struct bGPDpalette *palette_src); -struct bGPDpalettecolor *gpencil_palettecolor_addnew(struct bGPDpalette *palette, const char *name, bool setactive); +struct bGPDpalette *BKE_gpencil_palette_addnew(struct bGPdata *gpd, const char *name, bool setactive); +struct bGPDpalette *BKE_gpencil_palette_duplicate(const struct bGPDpalette *palette_src); +struct bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(struct bGPDpalette *palette, const char *name, bool setactive); -struct bGPDbrush *gpencil_brush_addnew(struct ToolSettings *ts, const char *name, bool setactive); -struct bGPDbrush *gpencil_brush_duplicate(const struct bGPDbrush *brush_src); -void gpencil_brush_init_presets(struct ToolSettings *ts); +struct bGPDbrush *BKE_gpencil_brush_addnew(struct ToolSettings *ts, const char *name, bool setactive); +struct bGPDbrush *BKE_gpencil_brush_duplicate(const struct bGPDbrush *brush_src); +void BKE_gpencil_brush_init_presets(struct ToolSettings *ts); /* Stroke and Fill - Alpha Visibility Threshold */ @@ -94,28 +94,28 @@ typedef enum eGP_GetFrame_Mode { GP_GETFRAME_ADD_COPY = 2 } eGP_GetFrame_Mode; -struct bGPDframe *gpencil_layer_getframe(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew); +struct bGPDframe *BKE_gpencil_layer_getframe(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew); struct bGPDframe *BKE_gpencil_layer_find_frame(struct bGPDlayer *gpl, int cframe); -bool gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf); - -struct bGPDlayer *gpencil_layer_getactive(struct bGPdata *gpd); -void gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active); -void gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl); - -struct bGPDbrush *gpencil_brush_getactive(struct ToolSettings *ts); -void gpencil_brush_setactive(struct ToolSettings *ts, struct bGPDbrush *active); -void gpencil_brush_delete(struct ToolSettings *ts, struct bGPDbrush *palette); - -struct bGPDpalette *gpencil_palette_getactive(struct bGPdata *gpd); -void gpencil_palette_setactive(struct bGPdata *gpd, struct bGPDpalette *active); -void gpencil_palette_delete(struct bGPdata *gpd, struct bGPDpalette *palette); -void gpencil_palette_change_strokes(struct bGPdata *gpd); - -struct bGPDpalettecolor *gpencil_palettecolor_getactive(struct bGPDpalette *palette); -void gpencil_palettecolor_setactive(struct bGPDpalette *palette, struct bGPDpalettecolor *active); -void gpencil_palettecolor_delete(struct bGPDpalette *palette, struct bGPDpalettecolor *palcolor); -struct bGPDpalettecolor *gpencil_palettecolor_getbyname(struct bGPDpalette *palette, char *name); -void gpencil_palettecolor_changename(struct bGPdata *gpd, char *oldname, const char *newname); -void gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name); +bool BKE_gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf); + +struct bGPDlayer *BKE_gpencil_layer_getactive(struct bGPdata *gpd); +void BKE_gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active); +void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl); + +struct bGPDbrush *BKE_gpencil_brush_getactive(struct ToolSettings *ts); +void BKE_gpencil_brush_setactive(struct ToolSettings *ts, struct bGPDbrush *active); +void BKE_gpencil_brush_delete(struct ToolSettings *ts, struct bGPDbrush *palette); + +struct bGPDpalette *BKE_gpencil_palette_getactive(struct bGPdata *gpd); +void BKE_gpencil_palette_setactive(struct bGPdata *gpd, struct bGPDpalette *active); +void BKE_gpencil_palette_delete(struct bGPdata *gpd, struct bGPDpalette *palette); +void BKE_gpencil_palette_change_strokes(struct bGPdata *gpd); + +struct bGPDpalettecolor *BKE_gpencil_palettecolor_getactive(struct bGPDpalette *palette); +void BKE_gpencil_palettecolor_setactive(struct bGPDpalette *palette, struct bGPDpalettecolor *active); +void BKE_gpencil_palettecolor_delete(struct bGPDpalette *palette, struct bGPDpalettecolor *palcolor); +struct bGPDpalettecolor *BKE_gpencil_palettecolor_getbyname(struct bGPDpalette *palette, char *name); +void BKE_gpencil_palettecolor_changename(struct bGPdata *gpd, char *oldname, const char *newname); +void BKE_gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name); #endif /* __BKE_GPENCIL_H__ */ diff --git a/source/blender/blenkernel/BKE_idcode.h b/source/blender/blenkernel/BKE_idcode.h index 6de0efe2709..964a49435f1 100644 --- a/source/blender/blenkernel/BKE_idcode.h +++ b/source/blender/blenkernel/BKE_idcode.h @@ -42,6 +42,8 @@ bool BKE_idcode_is_valid(short idcode); int BKE_idcode_to_idfilter(const short idcode); short BKE_idcode_from_idfilter(const int idfilter); +int BKE_idcode_to_index(const short idcode); + /** * Return an ID code and steps the index forward 1. * diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index e32bc2ffb20..e49019fcfae 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -94,7 +94,7 @@ void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_ma struct ListBase *which_libbase(struct Main *mainlib, short type); -#define MAX_LIBARRAY 34 +#define MAX_LIBARRAY 35 int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); /* Main API */ diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 44e4da4e0a3..a4f5c425282 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -42,6 +42,8 @@ */ #include "DNA_listBase.h" +#include "BKE_library.h" + #ifdef __cplusplus extern "C" { #endif @@ -102,8 +104,9 @@ typedef struct Main { ListBase movieclip; ListBase mask; ListBase linestyle; + ListBase cachefiles; - char id_tag_update[256]; + char id_tag_update[MAX_LIBARRAY]; /* Evaluation context used by viewport */ struct EvaluationContext *eval_ctx; diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index df739996c54..8ae5c2b3c45 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -49,7 +49,7 @@ void BKE_material_free(struct Material *ma); void BKE_material_free_ex(struct Material *ma, bool do_id_user); void test_object_materials(struct Object *ob, struct ID *id); void test_all_objects_materials(struct Main *bmain, struct ID *id); -void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user); +void BKE_material_resize_object(struct Main *bmain, struct Object *ob, const short totcol, bool do_id_user); void BKE_material_init(struct Material *ma); void BKE_material_remap_object(struct Object *ob, const unsigned int *remap); void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst); @@ -90,10 +90,10 @@ void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma); void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob); /* rna api */ -void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user); -void BKE_material_append_id(struct ID *id, struct Material *ma); -struct Material *BKE_material_pop_id(struct ID *id, int index, bool update_data); /* index is an int because of RNA */ -void BKE_material_clear_id(struct ID *id, bool update_data); +void BKE_material_resize_id(struct Main *bmain, struct ID *id, short totcol, bool do_id_user); +void BKE_material_append_id(struct Main *bmain, struct ID *id, struct Material *ma); +struct Material *BKE_material_pop_id(struct Main *bmain, struct ID *id, int index, bool update_data); /* index is an int because of RNA */ +void BKE_material_clear_id(struct Main *bmain, struct ID *id, bool update_data); /* rendering */ void init_render_material(struct Material *, int, float *); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 37831728e6f..b3e3968ca9b 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -63,6 +63,8 @@ struct BVHTreeRay; struct BVHTreeRayHit; struct EdgeHash; +#define PARTICLE_COLLISION_MAX_COLLISIONS 10 + #define PARTICLE_P ParticleData * pa; int p #define LOOP_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) #define LOOP_EXISTING_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) if (!(pa->flag & PARS_UNEXIST)) @@ -205,8 +207,7 @@ typedef struct ParticleCollisionElement { typedef struct ParticleCollision { struct Object *current; struct Object *hit; - struct Object *prev; - struct Object *skip; + struct Object *skip[PARTICLE_COLLISION_MAX_COLLISIONS+1]; struct Object *emitter; struct CollisionModifierData *md; // collision modifier for current object; @@ -218,7 +219,7 @@ typedef struct ParticleCollision { float original_ray_length; //original length of co2-co1, needed for collision time evaluation - int prev_index; + int skip_count; ParticleCollisionElement pce; diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 8238ea64242..02f6c435ee2 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -304,7 +304,7 @@ void BKE_ptcache_mem_pointers_incr(struct PTCacheMem *pm); int BKE_ptcache_mem_pointers_seek(int point_index, struct PTCacheMem *pm); /* Main cache reading call. */ -int BKE_ptcache_read(PTCacheID *pid, float cfra); +int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old); /* Main cache writing call. */ int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 30bb6954019..811e9136fc9 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -477,4 +477,6 @@ struct ImBuf *BKE_sequencer_render_mask_input( int cfra, int fra_offset, bool make_float); void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, struct ImBuf *ibuf, float mul, bool make_float, struct ImBuf *mask_input); +void BKE_sequencer_all_free_anim_ibufs(int cfra); + #endif /* __BKE_SEQUENCER_H__ */ diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 1938bb08395..30873567297 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -277,9 +277,9 @@ void BKE_tracking_detect_harris(struct MovieTracking *tracking, struct ListBase bool place_outside_layer); /* **** 2D stabilization **** */ -void BKE_tracking_stabilization_data_get(struct MovieTracking *tracking, int framenr, int width, int height, +void BKE_tracking_stabilization_data_get(struct MovieClip *clip, int framenr, int width, int height, float translation[2], float *scale, float *angle); -struct ImBuf *BKE_tracking_stabilize_frame(struct MovieTracking *tracking, int framenr, struct ImBuf *ibuf, +struct ImBuf *BKE_tracking_stabilize_frame(struct MovieClip *clip, int framenr, struct ImBuf *ibuf, float translation[2], float *scale, float *angle); void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, float translation[2], float scale, float angle, float mat[4][4]); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b7ff81d603b..157c4408d6a 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -81,6 +81,7 @@ set(SRC intern/brush.c intern/bullet.c intern/bvhutils.c + intern/cachefile.c intern/camera.c intern/cdderivedmesh.c intern/cloth.c @@ -207,6 +208,7 @@ set(SRC BKE_brush.h BKE_bullet.h BKE_bvhutils.h + BKE_cachefile.h BKE_camera.h BKE_ccg.h BKE_cdderivedmesh.h @@ -500,6 +502,13 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() +if(WITH_ALEMBIC) + list(APPEND INC + ../alembic + ) + add_definitions(-DWITH_ALEMBIC) +endif() + if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) list(APPEND INC_SYS diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h index 7b3199efb41..69ca75836d9 100644 --- a/source/blender/blenkernel/depsgraph_private.h +++ b/source/blender/blenkernel/depsgraph_private.h @@ -34,6 +34,11 @@ #include "DNA_constraint_types.h" #include "BKE_constraint.h" +struct Scene; +struct Group; +struct EffectorWeights; +struct ModifierData; + /* **** DAG relation types *** */ /* scene link to object */ @@ -152,6 +157,11 @@ DagNode *dag_get_node(DagForest *forest, void *fob); DagNode *dag_get_sub_node(DagForest *forest, void *fob); void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name); +typedef bool (*DagCollobjFilterFunction)(struct Object *obj, struct ModifierData *md); + +void dag_add_collision_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name); +void dag_add_forcefield_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name); + void graph_print_queue(DagNodeQueue *nqueue); void graph_print_queue_dist(DagNodeQueue *nqueue); void graph_print_adj_list(DagForest *dag); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 79e500f8ceb..714417ae29e 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2282,7 +2282,7 @@ static void editbmesh_calc_modifiers( { ModifierData *md, *previewmd = NULL; float (*deformedVerts)[3] = NULL; - CustomDataMask mask, previewmask = 0, append_mask = 0; + CustomDataMask mask = 0, previewmask = 0, append_mask = 0; DerivedMesh *dm = NULL, *orcodm = NULL; int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); CDMaskLink *datamasks, *curr; @@ -2565,11 +2565,15 @@ static void editbmesh_calc_modifiers( * we'll be using GPU backend of OpenSubdiv. This is so * playback performance is kept as high as possible. */ -static bool calc_modifiers_skip_orco(const Object *ob) +static bool calc_modifiers_skip_orco(Scene *scene, + const Object *ob, + bool use_render_params) { - const ModifierData *last_md = ob->modifiers.last; + ModifierData *last_md = ob->modifiers.last; + const int required_mode = use_render_params ? eModifierMode_Render : eModifierMode_Realtime; if (last_md != NULL && - last_md->type == eModifierType_Subsurf) + last_md->type == eModifierType_Subsurf && + modifier_isEnabled(scene, last_md, required_mode)) { SubsurfModifierData *smd = (SubsurfModifierData *)last_md; /* TODO(sergey): Deduplicate this with checks from subsurf_ccg.c. */ @@ -2589,7 +2593,7 @@ static void mesh_build_data( BKE_object_sculpt_modifiers_changed(ob); #ifdef WITH_OPENSUBDIV - if (calc_modifiers_skip_orco(ob)) { + if (calc_modifiers_skip_orco(scene, ob, false)) { dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL); } #endif @@ -2624,7 +2628,7 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C BKE_editmesh_free_derivedmesh(em); #ifdef WITH_OPENSUBDIV - if (calc_modifiers_skip_orco(obedit)) { + if (calc_modifiers_skip_orco(scene, obedit, false)) { dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL); } #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 477c7036762..e3764adb969 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -97,6 +97,7 @@ bool id_type_can_have_animdata(const short id_type) case ID_MC: case ID_MSK: case ID_GD: + case ID_CF: return true; /* no AnimData */ @@ -1160,6 +1161,9 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u /* grease pencil */ ANIMDATA_IDS_CB(mainptr->gpencil.first); + + /* cache files */ + ANIMDATA_IDS_CB(mainptr->cachefiles.first); } /* Fix all RNA-Paths throughout the database (directly access the Global.main version) @@ -1250,6 +1254,9 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const cha /* grease pencil */ RENAMEFIX_ANIM_IDS(mainptr->gpencil.first); + + /* cache files */ + RENAMEFIX_ANIM_IDS(mainptr->cachefiles.first); /* scenes */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); @@ -1506,7 +1513,7 @@ static bool animsys_store_rna_setting( if (array_len && array_index >= array_len) { if (G.debug & G_DEBUG) { printf("Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d\n", - (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", + (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", path, array_index, array_len - 1); } } @@ -2873,6 +2880,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) /* grease pencil */ EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM); + + /* cache files */ + EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM); /* objects */ /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index aebd564ca58..3bc81a69c86 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -617,9 +617,9 @@ void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx), /* pass */ } else { - /* TODO(sergey): Use time source node for time. */ - float ctime = BKE_scene_frame_get(scene); /* not accurate... */ if ((pchan->flag & POSE_DONE) == 0) { + /* TODO(sergey): Use time source node for time. */ + float ctime = BKE_scene_frame_get(scene); /* not accurate... */ BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); } } @@ -641,8 +641,8 @@ void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx), /* IK are being solved separately/ */ } else { - float ctime = BKE_scene_frame_get(scene); /* not accurate... */ if ((pchan->flag & POSE_DONE) == 0) { + float ctime = BKE_scene_frame_get(scene); /* not accurate... */ BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); } } diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index a708c59fa97..487b8ffa2b5 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -48,6 +48,7 @@ #include "MEM_guardedalloc.h" #include "DNA_brush_types.h" +#include "DNA_cachefile_types.h" #include "DNA_image_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" @@ -653,6 +654,12 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int rewrite_path_fixed(clip->name, visit_cb, absbase, bpath_user_data); break; } + case ID_CF: + { + CacheFile *cache_file = (CacheFile *)id; + rewrite_path_fixed(cache_file->filepath, visit_cb, absbase, bpath_user_data); + break; + } default: /* Nothing to do for other IDs that don't contain file paths. */ break; diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c new file mode 100644 index 00000000000..502f1d53ab2 --- /dev/null +++ b/source/blender/blenkernel/intern/cachefile.c @@ -0,0 +1,193 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Kevin Dietrich. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/cachefile.c + * \ingroup bke + */ + +#include "DNA_anim_types.h" +#include "DNA_cachefile_types.h" +#include "DNA_scene_types.h" + +#include "BLI_fileops.h" +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "BKE_animsys.h" +#include "BKE_cachefile.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_scene.h" + +#ifdef WITH_ALEMBIC +# include "ABC_alembic.h" +#endif + +static SpinLock spin; + +void BKE_cachefiles_init(void) +{ + BLI_spin_init(&spin); +} + +void *BKE_cachefile_add(Main *bmain, const char *name) +{ + CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, name); + + BKE_cachefile_init(cache_file); + + return cache_file; +} + +void BKE_cachefile_init(CacheFile *cache_file) +{ + cache_file->handle = NULL; + cache_file->filepath[0] = '\0'; + cache_file->override_frame = false; + cache_file->frame = 0.0f; + cache_file->is_sequence = false; + cache_file->scale = 1.0f; + cache_file->handle_mutex = BLI_mutex_alloc(); +} + +/** Free (or release) any data used by this cachefile (does not free the cachefile itself). */ +void BKE_cachefile_free(CacheFile *cache_file) +{ + BKE_animdata_free((ID *)cache_file, false); + +#ifdef WITH_ALEMBIC + ABC_free_handle(cache_file->handle); +#endif + + BLI_mutex_free(cache_file->handle_mutex); + BLI_freelistN(&cache_file->object_paths); +} + +CacheFile *BKE_cachefile_copy(Main *bmain, CacheFile *cache_file) +{ + CacheFile *new_cache_file = BKE_libblock_copy(bmain, &cache_file->id); + new_cache_file->handle = NULL; + + BLI_listbase_clear(&cache_file->object_paths); + + BKE_id_copy_ensure_local(bmain, &cache_file->id, &new_cache_file->id); + + return new_cache_file; +} + +void BKE_cachefile_make_local(Main *bmain, CacheFile *cache_file, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &cache_file->id, true, lib_local); +} + +void BKE_cachefile_reload(const Main *bmain, CacheFile *cache_file) +{ + char filepath[FILE_MAX]; + + BLI_strncpy(filepath, cache_file->filepath, sizeof(filepath)); + BLI_path_abs(filepath, ID_BLEND_PATH(bmain, &cache_file->id)); + +#ifdef WITH_ALEMBIC + if (cache_file->handle) { + ABC_free_handle(cache_file->handle); + } + + cache_file->handle = ABC_create_handle(filepath, &cache_file->object_paths); +#endif +} + +void BKE_cachefile_ensure_handle(const Main *bmain, CacheFile *cache_file) +{ + BLI_spin_lock(&spin); + if (cache_file->handle_mutex == NULL) { + cache_file->handle_mutex = BLI_mutex_alloc(); + } + BLI_spin_unlock(&spin); + + BLI_mutex_lock(cache_file->handle_mutex); + + if (cache_file->handle == NULL) { + BKE_cachefile_reload(bmain, cache_file); + } + + BLI_mutex_unlock(cache_file->handle_mutex); +} + +void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, const float fps) +{ + CacheFile *cache_file; + char filename[FILE_MAX]; + + for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) { + /* Execute drivers only, as animation has already been done. */ + BKE_animsys_evaluate_animdata(scene, &cache_file->id, cache_file->adt, ctime, ADT_RECALC_DRIVERS); + + if (!cache_file->is_sequence) { + continue; + } + + const float time = BKE_cachefile_time_offset(cache_file, ctime, fps); + + if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) { +#ifdef WITH_ALEMBIC + ABC_free_handle(cache_file->handle); + cache_file->handle = ABC_create_handle(filename, NULL); +#endif + } + } +} + +bool BKE_cachefile_filepath_get( + const Main *bmain, const CacheFile *cache_file, float frame, + char r_filepath[FILE_MAX]) +{ + BLI_strncpy(r_filepath, cache_file->filepath, FILE_MAX); + BLI_path_abs(r_filepath, ID_BLEND_PATH(bmain, &cache_file->id)); + + int fframe; + int frame_len; + + if (cache_file->is_sequence && BLI_path_frame_get(r_filepath, &fframe, &frame_len)) { + char ext[32]; + BLI_path_frame_strip(r_filepath, true, ext); + BLI_path_frame(r_filepath, frame, frame_len); + BLI_ensure_extension(r_filepath, FILE_MAX, ext); + + /* TODO(kevin): store sequence range? */ + return BLI_exists(r_filepath); + } + + return true; +} + +float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const float fps) +{ + const float frame = (cache_file->override_frame ? cache_file->frame : time); + return cache_file->is_sequence ? frame : frame / fps; +} diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 159d5b82a6c..2d06bc88aa7 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -687,20 +687,24 @@ static void cdDM_drawMappedFaces( const int orig = (index_mp_to_orig) ? index_mp_to_orig[i] : i; bool is_hidden; - if (use_hide) { - if (flag & DM_DRAW_SELECT_USE_EDITMODE) { - BMFace *efa = BM_face_at_index(bm, orig); - is_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) != 0; + if (orig != ORIGINDEX_NONE) { + if (use_hide) { + if (flag & DM_DRAW_SELECT_USE_EDITMODE) { + BMFace *efa = BM_face_at_index(bm, orig); + is_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) != 0; + } + else { + is_hidden = (me->mpoly[orig].flag & ME_HIDE) != 0; + } + + if (!is_hidden) { + GPU_select_index_get(orig + 1, &selcol); + } } else { - is_hidden = (me->mpoly[orig].flag & ME_HIDE) != 0; - } - - if ((orig != ORIGINDEX_NONE) && !is_hidden) GPU_select_index_get(orig + 1, &selcol); + } } - else if (orig != ORIGINDEX_NONE) - GPU_select_index_get(orig + 1, &selcol); for (j = 0; j < mpoly->totloop; j++) fi_map[start_element++] = selcol; @@ -3402,7 +3406,7 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); - if (j == 0) { + if (j == 0 || !eindex) { med->flag = ME_EDGEDRAW | ME_EDGERENDER; *index = ORIGINDEX_NONE; } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 681b93172b2..28ef3f6f248 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -81,8 +81,10 @@ void cloth_init(ClothModifierData *clmd ) clmd->sim_parms->gravity[1] = 0.0; clmd->sim_parms->gravity[2] = -9.81; clmd->sim_parms->structural = 15.0; + clmd->sim_parms->max_struct = 15.0; clmd->sim_parms->shear = 15.0; clmd->sim_parms->bending = 0.5; + clmd->sim_parms->max_bend = 0.5; clmd->sim_parms->bending_damping = 0.5; clmd->sim_parms->Cdis = 5.0; clmd->sim_parms->Cvi = 1.0; @@ -449,9 +451,12 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived } /* try to read from cache */ - cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe); + bool can_simulate = (framenr == clmd->clothObject->last_frame+1) && !(cache->flag & PTCACHE_BAKED); - if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { + cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate); + + if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED || + (!can_simulate && cache_result == PTCACHE_READ_OLD)) { BKE_cloth_solver_set_positions(clmd); cloth_to_object (ob, clmd, vertexCos); @@ -473,7 +478,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived return; } - if (framenr!=clmd->clothObject->last_frame+1) + if (!can_simulate) return; /* if on second frame, write cache for first frame */ diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 8cac856b560..35a7aafdbde 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -503,12 +503,13 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned // return all collision objects in scene // collision object will exclude self -Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type) +Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli) { Base *base; Object **objs; GroupObject *go; unsigned int numobj= 0, maxobj= 100; + int level = dupli ? 0 : 1; objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); @@ -516,16 +517,14 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned if (group) { /* use specified group */ for (go= group->gobject.first; go; go= go->next) - add_collision_object(&objs, &numobj, &maxobj, go->ob, self, 0, modifier_type); + add_collision_object(&objs, &numobj, &maxobj, go->ob, self, level, modifier_type); } else { Scene *sce_iter; /* add objects in same layer in scene */ for (SETLOOPER(scene, sce_iter, base)) { - /* Need to check for active layers, too. - Otherwise this check fails if the objects are not on the same layer - DG */ - if ((base->lay & self->lay) || (base->lay & scene->lay)) - add_collision_object(&objs, &numobj, &maxobj, base->object, self, 0, modifier_type); + if ( base->lay & layer ) + add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type); } } @@ -535,6 +534,13 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned return objs; } +Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type) +{ + /* Need to check for active layers, too. + Otherwise this check fails if the objects are not on the same layer - DG */ + return get_collisionobjects_ext(scene, self, group, self->lay | scene->lay, numcollobj, modifier_type, true); +} + static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level) { CollisionModifierData *cmd= NULL; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 4c9ddd495e3..c4afa58b7d3 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -46,6 +46,7 @@ #include "BLT_translation.h" #include "DNA_armature_types.h" +#include "DNA_cachefile_types.h" #include "DNA_constraint_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" @@ -63,6 +64,7 @@ #include "BKE_anim.h" /* for the curve calculation part */ #include "BKE_armature.h" #include "BKE_bvhutils.h" +#include "BKE_cachefile.h" #include "BKE_camera.h" #include "BKE_constraint.h" #include "BKE_curve.h" @@ -86,6 +88,10 @@ # include "BPY_extern.h" #endif +#ifdef WITH_ALEMBIC +# include "ABC_alembic.h" +#endif + /* ---------------------------------------------------------------------------- */ /* Useful macros for testing various common flag combinations */ @@ -4333,6 +4339,84 @@ static bConstraintTypeInfo CTI_OBJECTSOLVER = { objectsolver_evaluate /* evaluate */ }; +/* ----------- Transform Cache ------------- */ + +static void transformcache_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) +{ + bTransformCacheConstraint *data = con->data; + func(con, (ID **)&data->cache_file, true, userdata); +} + +static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets) +{ +#ifdef WITH_ALEMBIC + bTransformCacheConstraint *data = con->data; + Scene *scene = cob->scene; + + CacheFile *cache_file = data->cache_file; + + if (!cache_file) { + return; + } + + const float frame = BKE_scene_frame_get(scene); + const float time = BKE_cachefile_time_offset(cache_file, frame, FPS); + + BKE_cachefile_ensure_handle(G.main, cache_file); + + ABC_get_transform(cache_file->handle, cob->ob, data->object_path, + cob->matrix, time, cache_file->scale); +#else + UNUSED_VARS(con, cob); +#endif + + UNUSED_VARS(targets); +} + +static void transformcache_copy(bConstraint *con, bConstraint *srccon) +{ + bTransformCacheConstraint *src = srccon->data; + bTransformCacheConstraint *dst = con->data; + + BLI_strncpy(dst->object_path, src->object_path, sizeof(dst->object_path)); + dst->cache_file = src->cache_file; + + if (dst->cache_file) { + id_us_plus(&dst->cache_file->id); + } +} + +static void transformcache_free(bConstraint *con) +{ + bTransformCacheConstraint *data = con->data; + + if (data->cache_file) { + id_us_min(&data->cache_file->id); + } +} + +static void transformcache_new_data(void *cdata) +{ + bTransformCacheConstraint *data = (bTransformCacheConstraint *)cdata; + + data->cache_file = NULL; +} + +static bConstraintTypeInfo CTI_TRANSFORM_CACHE = { + CONSTRAINT_TYPE_TRANSFORM_CACHE, /* type */ + sizeof(bTransformCacheConstraint), /* size */ + "Transform Cache", /* name */ + "bTransformCacheConstraint", /* struct name */ + transformcache_free, /* free data */ + transformcache_id_looper, /* id looper */ + transformcache_copy, /* copy data */ + transformcache_new_data, /* new data */ + NULL, /* get constraint targets */ + NULL, /* flush constraint targets */ + NULL, /* get target matrix */ + transformcache_evaluate /* evaluate */ +}; + /* ************************* Constraints Type-Info *************************** */ /* All of the constraints api functions use bConstraintTypeInfo structs to carry out * and operations that involve constraint specific code. @@ -4374,6 +4458,7 @@ static void constraints_init_typeinfo(void) constraintsTypeInfo[26] = &CTI_FOLLOWTRACK; /* Follow Track Constraint */ constraintsTypeInfo[27] = &CTI_CAMERASOLVER; /* Camera Solver Constraint */ constraintsTypeInfo[28] = &CTI_OBJECTSOLVER; /* Object Solver Constraint */ + constraintsTypeInfo[29] = &CTI_TRANSFORM_CACHE; /* Transform Cache Constraint */ } /* This function should be used for getting the appropriate type-info when only diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 9d5a95df838..926ca8da192 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -1067,6 +1067,11 @@ struct EditBone *CTX_data_active_bone(const bContext *C) return ctx_data_pointer_get(C, "active_bone"); } +struct CacheFile *CTX_data_edit_cachefile(const bContext *C) +{ + return ctx_data_pointer_get(C, "edit_cachefile"); +} + int CTX_data_selected_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_bones", list); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 8ea65bf92c1..5f8332dcf0c 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -46,6 +46,7 @@ #include "DNA_anim_types.h" #include "DNA_camera_types.h" +#include "DNA_cachefile_types.h" #include "DNA_group_types.h" #include "DNA_lamp_types.h" #include "DNA_lattice_types.h" @@ -58,14 +59,18 @@ #include "DNA_windowmanager_types.h" #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" +#include "DNA_modifier_types.h" +#include "DNA_rigidbody_types.h" #include "BKE_anim.h" #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_DerivedMesh.h" +#include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_idcode.h" #include "BKE_image.h" #include "BKE_key.h" #include "BKE_library.h" @@ -448,49 +453,51 @@ static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *l la->id.tag &= ~LIB_TAG_DOIT; } -static void check_and_create_collision_relation(DagForest *dag, Object *ob, DagNode *node, Object *ob1, int skip_forcefield, bool no_collision) +static void create_collision_relation(DagForest *dag, DagNode *node, Object *ob1, const char *name) { - DagNode *node2; - if (ob1->pd && (ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) { - if ((skip_forcefield && ob1->pd->forcefield == skip_forcefield) || (no_collision && ob1->pd->forcefield == 0)) - return; - node2 = dag_get_node(dag, ob1); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Collision"); + DagNode *node2 = dag_get_node(dag, ob1); + dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, name); +} + +void dag_add_collision_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name) +{ + unsigned int numcollobj; + Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli); + + for (unsigned int i = 0; i < numcollobj; i++) { + Object *ob1 = collobjs[i]; + + if (!fn || fn(ob1, modifiers_findByType(ob1, modifier_type))) { + create_collision_relation(dag, node, ob1, name); + } } + + if (collobjs) + MEM_freeN(collobjs); } -static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield, bool no_collision) +void dag_add_forcefield_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name) { - Base *base; - ParticleSystem *particle_system; + ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false); - for (particle_system = ob->particlesystem.first; - particle_system; - particle_system = particle_system->next) - { - EffectorWeights *effector_weights = particle_system->part->effector_weights; - if (effector_weights->group) { - GroupObject *group_object; + if (effectors) { + for (EffectorCache *eff = effectors->first; eff; eff = eff->next) { + if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) { + create_collision_relation(dag, node, eff->ob, name); - for (group_object = effector_weights->group->gobject.first; - group_object; - group_object = group_object->next) - { - if ((group_object->ob->lay & ob->lay)) { - check_and_create_collision_relation(dag, ob, node, group_object->ob, skip_forcefield, no_collision); + if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) { + create_collision_relation(dag, node, eff->pd->f_source, "Smoke Force Domain"); + } + + if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { + /* Actual code uses get_collider_cache */ + dag_add_collision_relations(dag, scene, ob, node, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption"); } } } } - /* would be nice to have a list of colliders here - * so for now walk all objects in scene check 'same layer rule' */ - for (base = scene->base.first; base; base = base->next) { - if ((base->lay & ob->lay)) { - Object *ob1 = base->object; - check_and_create_collision_relation(dag, ob, node, ob1, skip_forcefield, no_collision); - } - } + pdEndEffectors(&effectors); } static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Object *ob, int mask) @@ -641,23 +648,13 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc } } - /* softbody collision */ + /* rigidbody force fields */ if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_LATTICE)) { - if (ob->particlesystem.first || - modifiers_isModifierEnabled(ob, eModifierType_Softbody) || - modifiers_isModifierEnabled(ob, eModifierType_Cloth) || - modifiers_isModifierEnabled(ob, eModifierType_DynamicPaint)) - { - dag_add_collision_field_relation(dag, scene, ob, node, 0, false); /* TODO: use effectorweight->group */ - } - else if (modifiers_isModifierEnabled(ob, eModifierType_Smoke)) { - dag_add_collision_field_relation(dag, scene, ob, node, PFIELD_SMOKEFLOW, false); - } - else if (ob->rigidbody_object) { - dag_add_collision_field_relation(dag, scene, ob, node, 0, true); + if (ob->rigidbody_object && scene->rigidbody_world) { + dag_add_forcefield_relations(dag, scene, ob, node, scene->rigidbody_world->effector_weights, true, 0, "Force Field"); } } - + /* object data drivers */ if (ob->data) { AnimData *adt = BKE_animdata_from_id((ID *)ob->data); @@ -761,8 +758,6 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc BoidRule *rule = NULL; BoidState *state = NULL; ParticleSettings *part = psys->part; - ListBase *effectors = NULL; - EffectorCache *eff; if (part->adt) { dag_add_driver_relation(part->adt, dag, node, 1); @@ -801,18 +796,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc } } - effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false); - - if (effectors) { - for (eff = effectors->first; eff; eff = eff->next) { - if (eff->psys) { - node2 = dag_get_node(dag, eff->ob); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Field"); - } - } + if (part->type != PART_HAIR) { + /* Actual code uses get_collider_cache */ + dag_add_collision_relations(dag, scene, ob, node, part->collision_group, ob->lay, eModifierType_Collision, NULL, true, "Particle Collision"); } - pdEndEffectors(&effectors); + dag_add_forcefield_relations(dag, scene, ob, node, part->effector_weights, part->type == PART_HAIR, 0, "Particle Force Field"); if (part->boids) { for (state = part->boids->states.first; state; state = state->next) { @@ -2173,7 +2162,12 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob) if (cti) { /* special case for camera tracking -- it doesn't use targets to define relations */ - if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { + if (ELEM(cti->type, + CONSTRAINT_TYPE_FOLLOWTRACK, + CONSTRAINT_TYPE_CAMERASOLVER, + CONSTRAINT_TYPE_OBJECTSOLVER, + CONSTRAINT_TYPE_TRANSFORM_CACHE)) + { ob->recalc |= OB_RECALC_OB; } else if (cti->get_constraint_targets) { @@ -2799,9 +2793,7 @@ void DAG_ids_flush_tagged(Main *bmain) ListBase *lb = lbarray[a]; ID *id = lb->first; - /* we tag based on first ID type character to avoid - * looping over all ID's in case there are no tags */ - if (id && bmain->id_tag_update[id->name[0]]) { + if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) { for (; id; id = id->next) { if (id->tag & (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA)) { @@ -2841,9 +2833,7 @@ void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time) ListBase *lb = lbarray[a]; ID *id = lb->first; - /* we tag based on first ID type character to avoid - * looping over all ID's in case there are no tags */ - if (id && bmain->id_tag_update[id->name[0]]) { + if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) { updated = true; break; } @@ -2924,9 +2914,7 @@ void DAG_ids_clear_recalc(Main *bmain) ListBase *lb = lbarray[a]; ID *id = lb->first; - /* we tag based on first ID type character to avoid - * looping over all ID's in case there are no tags */ - if (id && bmain->id_tag_update[id->name[0]]) { + if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) { for (; id; id = id->next) { if (id->tag & (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA)) id->tag &= ~(LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA); @@ -3001,6 +2989,33 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag) /* BLI_assert(!"invalid flag for this 'idtype'"); */ } } + else if (GS(id->name) == ID_CF) { + for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { + ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); + + if (md) { + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; + + if (mcmd->cache_file && (&mcmd->cache_file->id == id)) { + ob->recalc |= OB_RECALC_DATA; + continue; + } + } + + for (bConstraint *con = ob->constraints.first; con; con = con->next) { + if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) { + continue; + } + + bTransformCacheConstraint *data = con->data; + + if (data->cache_file && (&data->cache_file->id == id)) { + ob->recalc |= OB_RECALC_DATA; + break; + } + } + } + } } void DAG_id_tag_update(ID *id, short flag) @@ -3020,12 +3035,12 @@ void DAG_id_type_tag(Main *bmain, short idtype) DAG_id_type_tag(bmain, ID_SCE); } - bmain->id_tag_update[((char *)&idtype)[0]] = 1; + bmain->id_tag_update[BKE_idcode_to_index(idtype)] = 1; } int DAG_id_type_tagged(Main *bmain, short idtype) { - return bmain->id_tag_update[((char *)&idtype)[0]]; + return bmain->id_tag_update[BKE_idcode_to_index(idtype)]; } #if 0 // UNUSED diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index d35de6fc5d3..24425720bd2 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2015,11 +2015,13 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene } /* try to read from cache */ - if (BKE_ptcache_read(&pid, (float)scene->r.cfra)) { + bool can_simulate = ((int)scene->r.cfra == current_frame) && !(cache->flag & PTCACHE_BAKED); + + if (BKE_ptcache_read(&pid, (float)scene->r.cfra, can_simulate)) { BKE_ptcache_validate(cache, (int)scene->r.cfra); } /* if read failed and we're on surface range do recalculate */ - else if ((int)scene->r.cfra == current_frame && !(cache->flag & PTCACHE_BAKED)) { + else if (can_simulate) { /* calculate surface frame */ canvas->flags |= MOD_DPAINT_BAKING; dynamicPaint_calculateFrame(surface, scene, ob, current_frame); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 5090e46f1fc..7e6897a2858 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -155,15 +155,20 @@ static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSyste eff->frame = -1; return eff; } -static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src) +static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation) { EffectorCache *eff = NULL; - if ( ob == ob_src || weights->weight[ob->pd->forcefield] == 0.0f ) + if ( ob == ob_src ) return; - if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal ) - return; + if (for_simulation) { + if (weights->weight[ob->pd->forcefield] == 0.0f ) + return; + + if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal ) + return; + } if (*effectors == NULL) *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); @@ -175,7 +180,7 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector BLI_addtail(*effectors, eff); } -static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src) +static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation) { ParticleSettings *part= psys->part; @@ -185,14 +190,14 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec if ( psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0) return; - if ( part->pd && part->pd->forcefield && weights->weight[part->pd->forcefield] != 0.0f) { + if ( part->pd && part->pd->forcefield && (!for_simulation || weights->weight[part->pd->forcefield] != 0.0f)) { if (*effectors == NULL) *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd)); } - if (part->pd2 && part->pd2->forcefield && weights->weight[part->pd2->forcefield] != 0.0f) { + if (part->pd2 && part->pd2->forcefield && (!for_simulation || weights->weight[part->pd2->forcefield] != 0.0f)) { if (*effectors == NULL) *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); @@ -202,7 +207,7 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec /* returns ListBase handle with objects taking part in the effecting */ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, - EffectorWeights *weights, bool precalc) + EffectorWeights *weights, bool for_simulation) { Base *base; unsigned int layer= ob_src->lay; @@ -214,13 +219,13 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src for (go= weights->group->gobject.first; go; go= go->next) { if ( (go->ob->lay & layer) ) { if ( go->ob->pd && go->ob->pd->forcefield ) - add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src); + add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src, for_simulation); if ( go->ob->particlesystem.first ) { ParticleSystem *psys= go->ob->particlesystem.first; for ( ; psys; psys=psys->next ) - add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src); + add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src, for_simulation); } } } @@ -229,19 +234,19 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src for (base = scene->base.first; base; base= base->next) { if ( (base->lay & layer) ) { if ( base->object->pd && base->object->pd->forcefield ) - add_object_to_effectors(&effectors, scene, weights, base->object, ob_src); + add_object_to_effectors(&effectors, scene, weights, base->object, ob_src, for_simulation); if ( base->object->particlesystem.first ) { ParticleSystem *psys= base->object->particlesystem.first; for ( ; psys; psys=psys->next ) - add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src); + add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src, for_simulation); } } } } - if (precalc) + if (for_simulation) pdPrecalculateEffectors(effectors); return effectors; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 083e0d050e6..2242113b79b 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -60,7 +60,7 @@ /* --------- Memory Management ------------ */ /* free stroke, doesn't unlink from any listbase */ -void free_gpencil_stroke(bGPDstroke *gps) +void BKE_gpencil_free_stroke(bGPDstroke *gps) { if (gps == NULL) { return; @@ -76,7 +76,7 @@ void free_gpencil_stroke(bGPDstroke *gps) } /* Free strokes belonging to a gp-frame */ -bool free_gpencil_strokes(bGPDframe *gpf) +bool BKE_gpencil_free_strokes(bGPDframe *gpf) { bGPDstroke *gps_next; bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false); @@ -84,7 +84,7 @@ bool free_gpencil_strokes(bGPDframe *gpf) /* free strokes */ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps_next) { gps_next = gps->next; - free_gpencil_stroke(gps); + BKE_gpencil_free_stroke(gps); } BLI_listbase_clear(&gpf->strokes); @@ -92,7 +92,7 @@ bool free_gpencil_strokes(bGPDframe *gpf) } /* Free all of a gp-layer's frames */ -void free_gpencil_frames(bGPDlayer *gpl) +void BKE_gpencil_free_frames(bGPDlayer *gpl) { bGPDframe *gpf_next; @@ -104,7 +104,7 @@ void free_gpencil_frames(bGPDlayer *gpl) gpf_next = gpf->next; /* free strokes and their associated memory */ - free_gpencil_strokes(gpf); + BKE_gpencil_free_strokes(gpf); BLI_freelinkN(&gpl->frames, gpf); } gpl->actframe = NULL; @@ -123,7 +123,7 @@ static void free_gpencil_colors(bGPDpalette *palette) } /* Free all of the gp-palettes and colors */ -void free_gpencil_palettes(ListBase *list) +void BKE_gpencil_free_palettes(ListBase *list) { bGPDpalette *palette_next; @@ -144,7 +144,7 @@ void free_gpencil_palettes(ListBase *list) } /* Free all of the gp-brushes for a viewport (list should be &gpd->brushes or so) */ -void free_gpencil_brushes(ListBase *list) +void BKE_gpencil_free_brushes(ListBase *list) { bGPDbrush *brush_next; @@ -173,7 +173,7 @@ void free_gpencil_brushes(ListBase *list) } /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */ -void free_gpencil_layers(ListBase *list) +void BKE_gpencil_free_layers(ListBase *list) { bGPDlayer *gpl_next; @@ -185,7 +185,7 @@ void free_gpencil_layers(ListBase *list) gpl_next = gpl->next; /* free layers and their data */ - free_gpencil_frames(gpl); + BKE_gpencil_free_frames(gpl); BLI_freelinkN(list, gpl); } } @@ -196,18 +196,18 @@ void BKE_gpencil_free(bGPdata *gpd, bool free_palettes) BKE_animdata_free(&gpd->id, false); /* free layers */ - free_gpencil_layers(&gpd->layers); + BKE_gpencil_free_layers(&gpd->layers); /* free palettes */ if (free_palettes) { - free_gpencil_palettes(&gpd->palettes); + BKE_gpencil_free_palettes(&gpd->palettes); } } /* -------- Container Creation ---------- */ /* add a new gp-frame to the given layer */ -bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe) +bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe) { bGPDframe *gpf = NULL, *gf = NULL; short state = 0; @@ -259,7 +259,7 @@ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe) } /* add a copy of the active gp-frame to the given layer */ -bGPDframe *gpencil_frame_addcopy(bGPDlayer *gpl, int cframe) +bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe) { bGPDframe *new_frame; bool found = false; @@ -271,11 +271,11 @@ bGPDframe *gpencil_frame_addcopy(bGPDlayer *gpl, int cframe) } else if (gpl->actframe == NULL) { /* no active frame, so just create a new one from scratch */ - return gpencil_frame_addnew(gpl, cframe); + return BKE_gpencil_frame_addnew(gpl, cframe); } /* Create a copy of the frame */ - new_frame = gpencil_frame_duplicate(gpl->actframe); + new_frame = BKE_gpencil_frame_duplicate(gpl->actframe); /* Find frame to insert it before */ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { @@ -290,7 +290,7 @@ bGPDframe *gpencil_frame_addcopy(bGPDlayer *gpl, int cframe) /* This only happens when we're editing with framelock on... * - Delete the new frame and don't do anything else here... */ - free_gpencil_strokes(new_frame); + BKE_gpencil_free_strokes(new_frame); MEM_freeN(new_frame); new_frame = NULL; @@ -314,7 +314,7 @@ bGPDframe *gpencil_frame_addcopy(bGPDlayer *gpl, int cframe) } /* add a new gp-layer and make it the active layer */ -bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive) +bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive) { bGPDlayer *gpl; @@ -353,14 +353,14 @@ bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive) /* make this one the active one */ if (setactive) - gpencil_layer_setactive(gpd, gpl); + BKE_gpencil_layer_setactive(gpd, gpl); /* return layer */ return gpl; } /* add a new gp-palette and make it the active */ -bGPDpalette *gpencil_palette_addnew(bGPdata *gpd, const char *name, bool setactive) +bGPDpalette *BKE_gpencil_palette_addnew(bGPdata *gpd, const char *name, bool setactive) { bGPDpalette *palette; @@ -383,7 +383,7 @@ bGPDpalette *gpencil_palette_addnew(bGPdata *gpd, const char *name, bool setacti /* make this one the active one */ if (setactive) { - gpencil_palette_setactive(gpd, palette); + BKE_gpencil_palette_setactive(gpd, palette); } /* return palette */ @@ -391,11 +391,11 @@ bGPDpalette *gpencil_palette_addnew(bGPdata *gpd, const char *name, bool setacti } /* create a set of default drawing brushes with predefined presets */ -void gpencil_brush_init_presets(ToolSettings *ts) +void BKE_gpencil_brush_init_presets(ToolSettings *ts) { bGPDbrush *brush; /* Basic brush */ - brush = gpencil_brush_addnew(ts, "Basic", true); + brush = BKE_gpencil_brush_addnew(ts, "Basic", true); brush->thickness = 3.0f; brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE; brush->draw_sensitivity = 1.0f; @@ -419,7 +419,7 @@ void gpencil_brush_init_presets(ToolSettings *ts) brush->draw_random_sub = 0.0f; /* Pencil brush */ - brush = gpencil_brush_addnew(ts, "Pencil", false); + brush = BKE_gpencil_brush_addnew(ts, "Pencil", false); brush->thickness = 7.0f; brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE; brush->draw_sensitivity = 1.0f; @@ -443,7 +443,7 @@ void gpencil_brush_init_presets(ToolSettings *ts) brush->draw_random_sub = 0.0f; /* Ink brush */ - brush = gpencil_brush_addnew(ts, "Ink", false); + brush = BKE_gpencil_brush_addnew(ts, "Ink", false); brush->thickness = 7.0f; brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE; brush->draw_sensitivity = 1.6f; @@ -467,7 +467,7 @@ void gpencil_brush_init_presets(ToolSettings *ts) brush->draw_random_sub = 0.0f; /* Ink Noise brush */ - brush = gpencil_brush_addnew(ts, "Ink noise", false); + brush = BKE_gpencil_brush_addnew(ts, "Ink noise", false); brush->thickness = 6.0f; brush->flag |= GP_BRUSH_USE_RANDOM_PRESSURE; brush->draw_sensitivity = 1.611f; @@ -491,7 +491,7 @@ void gpencil_brush_init_presets(ToolSettings *ts) brush->draw_random_sub = 0.0f; /* Marker brush */ - brush = gpencil_brush_addnew(ts, "Marker", false); + brush = BKE_gpencil_brush_addnew(ts, "Marker", false); brush->thickness = 10.0f; brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE; brush->draw_sensitivity = 2.0f; @@ -515,7 +515,7 @@ void gpencil_brush_init_presets(ToolSettings *ts) brush->draw_random_sub = 0.0f; /* Crayon brush */ - brush = gpencil_brush_addnew(ts, "Crayon", false); + brush = BKE_gpencil_brush_addnew(ts, "Crayon", false); brush->thickness = 10.0f; brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE; brush->draw_sensitivity = 3.0f; @@ -541,7 +541,7 @@ void gpencil_brush_init_presets(ToolSettings *ts) } /* add a new gp-brush and make it the active */ -bGPDbrush *gpencil_brush_addnew(ToolSettings *ts, const char *name, bool setactive) +bGPDbrush *BKE_gpencil_brush_addnew(ToolSettings *ts, const char *name, bool setactive) { bGPDbrush *brush; @@ -577,7 +577,7 @@ bGPDbrush *gpencil_brush_addnew(ToolSettings *ts, const char *name, bool setacti /* make this one the active one */ if (setactive) { - gpencil_brush_setactive(ts, brush); + BKE_gpencil_brush_setactive(ts, brush); } /* return brush */ @@ -585,7 +585,7 @@ bGPDbrush *gpencil_brush_addnew(ToolSettings *ts, const char *name, bool setacti } /* add a new gp-palettecolor and make it the active */ -bGPDpalettecolor *gpencil_palettecolor_addnew(bGPDpalette *palette, const char *name, bool setactive) +bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(bGPDpalette *palette, const char *name, bool setactive) { bGPDpalettecolor *palcolor; @@ -612,7 +612,7 @@ bGPDpalettecolor *gpencil_palettecolor_addnew(bGPDpalette *palette, const char * /* make this one the active one */ if (setactive) { - gpencil_palettecolor_setactive(palette, palcolor); + BKE_gpencil_palettecolor_setactive(palette, palcolor); } /* return palette color */ @@ -620,7 +620,7 @@ bGPDpalettecolor *gpencil_palettecolor_addnew(bGPDpalette *palette, const char * } /* add a new gp-datablock */ -bGPdata *gpencil_data_addnew(const char name[]) +bGPdata *BKE_gpencil_data_addnew(const char name[]) { bGPdata *gpd; @@ -641,7 +641,7 @@ bGPdata *gpencil_data_addnew(const char name[]) /* -------- Data Duplication ---------- */ /* make a copy of a given gpencil frame */ -bGPDframe *gpencil_frame_duplicate(const bGPDframe *gpf_src) +bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src) { bGPDstroke *gps_dst; bGPDframe *gpf_dst; @@ -671,7 +671,7 @@ bGPDframe *gpencil_frame_duplicate(const bGPDframe *gpf_src) } /* make a copy of a given gpencil brush */ -bGPDbrush *gpencil_brush_duplicate(const bGPDbrush *brush_src) +bGPDbrush *BKE_gpencil_brush_duplicate(const bGPDbrush *brush_src) { bGPDbrush *brush_dst; @@ -693,7 +693,7 @@ bGPDbrush *gpencil_brush_duplicate(const bGPDbrush *brush_src) } /* make a copy of a given gpencil palette */ -bGPDpalette *gpencil_palette_duplicate(const bGPDpalette *palette_src) +bGPDpalette *BKE_gpencil_palette_duplicate(const bGPDpalette *palette_src) { bGPDpalette *palette_dst; const bGPDpalettecolor *palcolor_src; @@ -720,7 +720,7 @@ bGPDpalette *gpencil_palette_duplicate(const bGPDpalette *palette_src) return palette_dst; } /* make a copy of a given gpencil layer */ -bGPDlayer *gpencil_layer_duplicate(const bGPDlayer *gpl_src) +bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src) { const bGPDframe *gpf_src; bGPDframe *gpf_dst; @@ -739,7 +739,7 @@ bGPDlayer *gpencil_layer_duplicate(const bGPDlayer *gpl_src) BLI_listbase_clear(&gpl_dst->frames); for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) { /* make a copy of source frame */ - gpf_dst = gpencil_frame_duplicate(gpf_src); + gpf_dst = BKE_gpencil_frame_duplicate(gpf_src); BLI_addtail(&gpl_dst->frames, gpf_dst); /* if source frame was the current layer's 'active' frame, reassign that too */ @@ -752,7 +752,7 @@ bGPDlayer *gpencil_layer_duplicate(const bGPDlayer *gpl_src) } /* make a copy of a given gpencil datablock */ -bGPdata *gpencil_data_duplicate(Main *bmain, bGPdata *gpd_src, bool internal_copy) +bGPdata *BKE_gpencil_data_duplicate(Main *bmain, bGPdata *gpd_src, bool internal_copy) { const bGPDlayer *gpl_src; bGPDlayer *gpl_dst; @@ -777,7 +777,7 @@ bGPdata *gpencil_data_duplicate(Main *bmain, bGPdata *gpd_src, bool internal_cop BLI_listbase_clear(&gpd_dst->layers); for (gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) { /* make a copy of source layer and its data */ - gpl_dst = gpencil_layer_duplicate(gpl_src); + gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); BLI_addtail(&gpd_dst->layers, gpl_dst); } if (!internal_copy) { @@ -785,7 +785,7 @@ bGPdata *gpencil_data_duplicate(Main *bmain, bGPdata *gpd_src, bool internal_cop bGPDpalette *palette_src, *palette_dst; BLI_listbase_clear(&gpd_dst->palettes); for (palette_src = gpd_src->palettes.first; palette_src; palette_src = palette_src->next) { - palette_dst = gpencil_palette_duplicate(palette_src); + palette_dst = BKE_gpencil_palette_duplicate(palette_src); BLI_addtail(&gpd_dst->palettes, palette_dst); } } @@ -802,7 +802,7 @@ void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local) /* -------- GP-Stroke API --------- */ /* ensure selection status of stroke is in sync with its points */ -void gpencil_stroke_sync_selection(bGPDstroke *gps) +void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps) { bGPDspoint *pt; int i; @@ -827,7 +827,7 @@ void gpencil_stroke_sync_selection(bGPDstroke *gps) /* -------- GP-Frame API ---------- */ /* delete the last stroke of the given frame */ -void gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf) +void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf) { bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL; int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */ @@ -843,8 +843,8 @@ void gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf) /* if frame has no strokes after this, delete it */ if (BLI_listbase_is_empty(&gpf->strokes)) { - gpencil_layer_delframe(gpl, gpf); - gpencil_layer_getframe(gpl, cfra, 0); + BKE_gpencil_layer_delframe(gpl, gpf); + BKE_gpencil_layer_getframe(gpl, cfra, 0); } } @@ -892,7 +892,7 @@ bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe) * - this sets the layer's actframe var (if allowed to) * - extension beyond range (if first gp-frame is after all frame in interest and cannot add) */ -bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew) +bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew) { bGPDframe *gpf = NULL; short found = 0; @@ -931,9 +931,9 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode if ((found) && (gpf->framenum == cframe)) gpl->actframe = gpf; else if (addnew == GP_GETFRAME_ADD_COPY) - gpl->actframe = gpencil_frame_addcopy(gpl, cframe); + gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe); else - gpl->actframe = gpencil_frame_addnew(gpl, cframe); + gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe); } else if (found) gpl->actframe = gpf; @@ -953,9 +953,9 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode if ((found) && (gpf->framenum == cframe)) gpl->actframe = gpf; else if (addnew == GP_GETFRAME_ADD_COPY) - gpl->actframe = gpencil_frame_addcopy(gpl, cframe); + gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe); else - gpl->actframe = gpencil_frame_addnew(gpl, cframe); + gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe); } else if (found) gpl->actframe = gpf; @@ -992,7 +992,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode if ((found) && (gpf->framenum == cframe)) gpl->actframe = gpf; else - gpl->actframe = gpencil_frame_addnew(gpl, cframe); + gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe); } else if (found) gpl->actframe = gpf; @@ -1005,7 +1005,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode else { /* currently no frames (add if allowed to) */ if (addnew) - gpl->actframe = gpencil_frame_addnew(gpl, cframe); + gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe); else { /* don't do anything... this may be when no frames yet! */ /* gpl->actframe should still be NULL */ @@ -1017,7 +1017,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode } /* delete the given frame from a layer */ -bool gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf) +bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf) { bool changed = false; @@ -1034,14 +1034,14 @@ bool gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf) gpl->actframe = NULL; /* free the frame and its data */ - changed = free_gpencil_strokes(gpf); + changed = BKE_gpencil_free_strokes(gpf); BLI_freelinkN(&gpl->frames, gpf); return changed; } /* get the active gp-layer for editing */ -bGPDlayer *gpencil_layer_getactive(bGPdata *gpd) +bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd) { bGPDlayer *gpl; @@ -1060,7 +1060,7 @@ bGPDlayer *gpencil_layer_getactive(bGPdata *gpd) } /* set the active gp-layer */ -void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active) +void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active) { bGPDlayer *gpl; @@ -1077,20 +1077,20 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active) } /* delete the active gp-layer */ -void gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl) +void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl) { /* error checking */ if (ELEM(NULL, gpd, gpl)) return; /* free layer */ - free_gpencil_frames(gpl); + BKE_gpencil_free_frames(gpl); BLI_freelinkN(&gpd->layers, gpl); } /* ************************************************** */ /* get the active gp-brush for editing */ -bGPDbrush *gpencil_brush_getactive(ToolSettings *ts) +bGPDbrush *BKE_gpencil_brush_getactive(ToolSettings *ts) { bGPDbrush *brush; @@ -1111,7 +1111,7 @@ bGPDbrush *gpencil_brush_getactive(ToolSettings *ts) } /* set the active gp-brush */ -void gpencil_brush_setactive(ToolSettings *ts, bGPDbrush *active) +void BKE_gpencil_brush_setactive(ToolSettings *ts, bGPDbrush *active) { bGPDbrush *brush; @@ -1130,7 +1130,7 @@ void gpencil_brush_setactive(ToolSettings *ts, bGPDbrush *active) } /* delete the active gp-brush */ -void gpencil_brush_delete(ToolSettings *ts, bGPDbrush *brush) +void BKE_gpencil_brush_delete(ToolSettings *ts, bGPDbrush *brush) { /* error checking */ if (ELEM(NULL, ts, brush)) { @@ -1154,7 +1154,7 @@ void gpencil_brush_delete(ToolSettings *ts, bGPDbrush *brush) /* ************************************************** */ /* get the active gp-palette for editing */ -bGPDpalette *gpencil_palette_getactive(bGPdata *gpd) +bGPDpalette *BKE_gpencil_palette_getactive(bGPdata *gpd) { bGPDpalette *palette; @@ -1174,7 +1174,7 @@ bGPDpalette *gpencil_palette_getactive(bGPdata *gpd) } /* set the active gp-palette */ -void gpencil_palette_setactive(bGPdata *gpd, bGPDpalette *active) +void BKE_gpencil_palette_setactive(bGPdata *gpd, bGPDpalette *active) { bGPDpalette *palette; @@ -1191,11 +1191,11 @@ void gpencil_palette_setactive(bGPdata *gpd, bGPDpalette *active) /* set as active one */ active->flag |= PL_PALETTE_ACTIVE; /* force color recalc */ - gpencil_palette_change_strokes(gpd); + BKE_gpencil_palette_change_strokes(gpd); } /* delete the active gp-palette */ -void gpencil_palette_delete(bGPdata *gpd, bGPDpalette *palette) +void BKE_gpencil_palette_delete(bGPdata *gpd, bGPDpalette *palette) { /* error checking */ if (ELEM(NULL, gpd, palette)) { @@ -1206,11 +1206,11 @@ void gpencil_palette_delete(bGPdata *gpd, bGPDpalette *palette) free_gpencil_colors(palette); BLI_freelinkN(&gpd->palettes, palette); /* force color recalc */ - gpencil_palette_change_strokes(gpd); + BKE_gpencil_palette_change_strokes(gpd); } /* Set all strokes to recalc the palette color */ -void gpencil_palette_change_strokes(bGPdata *gpd) +void BKE_gpencil_palette_change_strokes(bGPdata *gpd) { bGPDlayer *gpl; bGPDframe *gpf; @@ -1227,7 +1227,7 @@ void gpencil_palette_change_strokes(bGPdata *gpd) /* get the active gp-palettecolor for editing */ -bGPDpalettecolor *gpencil_palettecolor_getactive(bGPDpalette *palette) +bGPDpalettecolor *BKE_gpencil_palettecolor_getactive(bGPDpalette *palette) { bGPDpalettecolor *palcolor; @@ -1247,7 +1247,7 @@ bGPDpalettecolor *gpencil_palettecolor_getactive(bGPDpalette *palette) return NULL; } /* get the gp-palettecolor looking for name */ -bGPDpalettecolor *gpencil_palettecolor_getbyname(bGPDpalette *palette, char *name) +bGPDpalettecolor *BKE_gpencil_palettecolor_getbyname(bGPDpalette *palette, char *name) { /* error checking */ if (ELEM(NULL, palette, name)) { @@ -1258,7 +1258,7 @@ bGPDpalettecolor *gpencil_palettecolor_getbyname(bGPDpalette *palette, char *nam } /* Change color name in all strokes */ -void gpencil_palettecolor_changename(bGPdata *gpd, char *oldname, const char *newname) +void BKE_gpencil_palettecolor_changename(bGPdata *gpd, char *oldname, const char *newname) { bGPDlayer *gpl; bGPDframe *gpf; @@ -1268,7 +1268,7 @@ void gpencil_palettecolor_changename(bGPdata *gpd, char *oldname, const char *ne for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (gps = gpf->strokes.first; gps; gps = gps->next) { if (STREQ(gps->colorname, oldname)) { - strcpy(gps->colorname, newname); + BLI_strncpy(gps->colorname, newname, sizeof(gps->colorname)); } } } @@ -1277,7 +1277,7 @@ void gpencil_palettecolor_changename(bGPdata *gpd, char *oldname, const char *ne } /* Delete all strokes of the color */ -void gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name) +void BKE_gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name) { bGPDlayer *gpl; bGPDframe *gpf; @@ -1300,7 +1300,7 @@ void gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name) } /* set the active gp-palettecolor */ -void gpencil_palettecolor_setactive(bGPDpalette *palette, bGPDpalettecolor *active) +void BKE_gpencil_palettecolor_setactive(bGPDpalette *palette, bGPDpalettecolor *active) { bGPDpalettecolor *palcolor; @@ -1319,7 +1319,7 @@ void gpencil_palettecolor_setactive(bGPDpalette *palette, bGPDpalettecolor *acti } /* delete the active gp-palettecolor */ -void gpencil_palettecolor_delete(bGPDpalette *palette, bGPDpalettecolor *palcolor) +void BKE_gpencil_palettecolor_delete(bGPDpalette *palette, bGPDpalettecolor *palcolor) { /* error checking */ if (ELEM(NULL, palette, palcolor)) { diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 90b3713e47c..70d037d85f3 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -60,6 +60,7 @@ static IDType idtypes[] = { { ID_AR, "Armature", "armatures", BLT_I18NCONTEXT_ID_ARMATURE, IDTYPE_FLAGS_ISLINKABLE }, { ID_BR, "Brush", "brushes", BLT_I18NCONTEXT_ID_BRUSH, IDTYPE_FLAGS_ISLINKABLE }, { ID_CA, "Camera", "cameras", BLT_I18NCONTEXT_ID_CAMERA, IDTYPE_FLAGS_ISLINKABLE }, + { ID_CF, "CacheFile", "cache_files", BLT_I18NCONTEXT_ID_CACHEFILE, IDTYPE_FLAGS_ISLINKABLE }, { ID_CU, "Curve", "curves", BLT_I18NCONTEXT_ID_CURVE, IDTYPE_FLAGS_ISLINKABLE }, { ID_GD, "GPencil", "grease_pencil", BLT_I18NCONTEXT_ID_GPENCIL, IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */ { ID_GR, "Group", "groups", BLT_I18NCONTEXT_ID_GROUP, IDTYPE_FLAGS_ISLINKABLE }, @@ -184,6 +185,7 @@ int BKE_idcode_to_idfilter(const short idcode) CASE_IDFILTER(AR); CASE_IDFILTER(BR); CASE_IDFILTER(CA); + CASE_IDFILTER(CF); CASE_IDFILTER(CU); CASE_IDFILTER(GD); CASE_IDFILTER(GR); @@ -227,6 +229,7 @@ short BKE_idcode_from_idfilter(const int idfilter) CASE_IDFILTER(AR); CASE_IDFILTER(BR); CASE_IDFILTER(CA); + CASE_IDFILTER(CF); CASE_IDFILTER(CU); CASE_IDFILTER(GD); CASE_IDFILTER(GR); @@ -259,6 +262,56 @@ short BKE_idcode_from_idfilter(const int idfilter) } /** + * Convert an idcode into an index (e.g. ID_OB -> INDEX_ID_OB). + */ +int BKE_idcode_to_index(const short idcode) +{ +#define CASE_IDINDEX(_id) case ID_##_id: return INDEX_ID_##_id + + switch ((ID_Type)idcode) { + CASE_IDINDEX(AC); + CASE_IDINDEX(AR); + CASE_IDINDEX(BR); + CASE_IDINDEX(CA); + CASE_IDINDEX(CF); + CASE_IDINDEX(CU); + CASE_IDINDEX(GD); + CASE_IDINDEX(GR); + CASE_IDINDEX(IM); + CASE_IDINDEX(KE); + CASE_IDINDEX(IP); + CASE_IDINDEX(LA); + CASE_IDINDEX(LI); + CASE_IDINDEX(LS); + CASE_IDINDEX(LT); + CASE_IDINDEX(MA); + CASE_IDINDEX(MB); + CASE_IDINDEX(MC); + CASE_IDINDEX(ME); + CASE_IDINDEX(MSK); + CASE_IDINDEX(NT); + CASE_IDINDEX(OB); + CASE_IDINDEX(PA); + CASE_IDINDEX(PAL); + CASE_IDINDEX(PC); + CASE_IDINDEX(SCE); + CASE_IDINDEX(SCR); + CASE_IDINDEX(SPK); + CASE_IDINDEX(SO); + CASE_IDINDEX(TE); + CASE_IDINDEX(TXT); + CASE_IDINDEX(VF); + CASE_IDINDEX(WM); + CASE_IDINDEX(WO); + } + + BLI_assert(0); + return -1; + +#undef CASE_IDINDEX +} + +/** * Convert an idcode into a name (plural). * * \param idcode: The code to convert. diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ea28dabb945..8a9cb73c8c9 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -436,6 +436,7 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src) Image *BKE_image_copy(Main *bmain, Image *ima) { Image *nima = image_alloc(bmain, ima->id.name + 2, ima->source, ima->type); + ima->id.newid = &nima->id; BLI_strncpy(nima->name, ima->name, sizeof(ima->name)); @@ -1865,7 +1866,7 @@ void BKE_image_stamp_buf( display = IMB_colormanagement_display_get_named(display_device); if (stamp_data_template == NULL) { - stampdata(scene, camera, &stamp_data, 1); + stampdata(scene, camera, &stamp_data, (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0); } else { stampdata_from_template(&stamp_data, scene, stamp_data_template); diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index e9d039ad480..d098366aef4 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -154,8 +154,6 @@ Lamp *localize_lamp(Lamp *la) if (lan->mtex[a]) { lan->mtex[a] = MEM_mallocN(sizeof(MTex), "localize_lamp"); memcpy(lan->mtex[a], la->mtex[a], sizeof(MTex)); - /* free lamp decrements */ - id_us_plus((ID *)lan->mtex[a]->tex); } } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index d3f20859f06..6d94cd28b31 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -45,6 +45,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_brush_types.h" +#include "DNA_cachefile_types.h" #include "DNA_camera_types.h" #include "DNA_group_types.h" #include "DNA_gpencil_types.h" @@ -56,6 +57,7 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" +#include "DNA_modifier_types.h" #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" #include "DNA_node_types.h" @@ -81,6 +83,7 @@ #include "BKE_bpath.h" #include "BKE_brush.h" #include "BKE_camera.h" +#include "BKE_cachefile.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" @@ -332,8 +335,10 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c */ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) { - if (id->tag & LIB_TAG_INDIRECT) + /* We don't care whether ID is directly or indirectly linked in case we are making a whole lib local... */ + if (!lib_local && (id->tag & LIB_TAG_INDIRECT)) { return false; + } switch ((ID_Type)GS(id->name)) { case ID_SCE: @@ -423,6 +428,9 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) case ID_PC: if (!test) BKE_paint_curve_make_local(bmain, (PaintCurve *)id, lib_local); return true; + case ID_CF: + if (!test) BKE_cachefile_make_local(bmain, (CacheFile *)id, lib_local); + return true; case ID_SCR: case ID_LI: case ID_KE: @@ -510,7 +518,7 @@ bool id_copy(Main *bmain, ID *id, ID **newid, bool test) if (!test) *newid = (ID *)BKE_particlesettings_copy(bmain, (ParticleSettings *)id); return true; case ID_GD: - if (!test) *newid = (ID *)gpencil_data_duplicate(bmain, (bGPdata *)id, false); + if (!test) *newid = (ID *)BKE_gpencil_data_duplicate(bmain, (bGPdata *)id, false); return true; case ID_MC: if (!test) *newid = (ID *)BKE_movieclip_copy(bmain, (MovieClip *)id); @@ -527,6 +535,9 @@ bool id_copy(Main *bmain, ID *id, ID **newid, bool test) case ID_PC: if (!test) *newid = (ID *)BKE_paint_curve_copy(bmain, (PaintCurve *)id); return true; + case ID_CF: + if (!test) *newid = (ID *)BKE_cachefile_copy(bmain, (CacheFile *)id); + return true; case ID_SCE: case ID_LI: case ID_SCR: @@ -639,6 +650,8 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->palettes); case ID_PC: return &(mainlib->paintcurves); + case ID_CF: + return &(mainlib->cachefiles); } return NULL; } @@ -740,59 +753,56 @@ void BKE_main_lib_objects_recalc_all(Main *bmain) * \note MAX_LIBARRAY define should match this code */ int set_listbasepointers(Main *main, ListBase **lb) { - int a = 0; - /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last. * This is important because freeing data decreases usercounts of other datablocks, * if this data is its self freed it can crash. */ - lb[a++] = &(main->library); /* Libraries may be accessed from pretty much any other ID... */ - lb[a++] = &(main->ipo); - lb[a++] = &(main->action); /* moved here to avoid problems when freeing with animato (aligorith) */ - lb[a++] = &(main->key); - lb[a++] = &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */ - lb[a++] = &(main->nodetree); - lb[a++] = &(main->image); - lb[a++] = &(main->tex); - lb[a++] = &(main->mat); - lb[a++] = &(main->vfont); + lb[INDEX_ID_LI] = &(main->library); /* Libraries may be accessed from pretty much any other ID... */ + lb[INDEX_ID_IP] = &(main->ipo); + lb[INDEX_ID_AC] = &(main->action); /* moved here to avoid problems when freeing with animato (aligorith) */ + lb[INDEX_ID_KE] = &(main->key); + lb[INDEX_ID_GD] = &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */ + lb[INDEX_ID_NT] = &(main->nodetree); + lb[INDEX_ID_IM] = &(main->image); + lb[INDEX_ID_TE] = &(main->tex); + lb[INDEX_ID_MA] = &(main->mat); + lb[INDEX_ID_VF] = &(main->vfont); /* Important!: When adding a new object type, * the specific data should be inserted here */ - lb[a++] = &(main->armature); - - lb[a++] = &(main->mesh); - lb[a++] = &(main->curve); - lb[a++] = &(main->mball); - - lb[a++] = &(main->latt); - lb[a++] = &(main->lamp); - lb[a++] = &(main->camera); - - lb[a++] = &(main->text); - lb[a++] = &(main->sound); - lb[a++] = &(main->group); - lb[a++] = &(main->palettes); - lb[a++] = &(main->paintcurves); - lb[a++] = &(main->brush); - lb[a++] = &(main->particle); - lb[a++] = &(main->speaker); - - lb[a++] = &(main->world); - lb[a++] = &(main->movieclip); - lb[a++] = &(main->screen); - lb[a++] = &(main->object); - lb[a++] = &(main->linestyle); /* referenced by scenes */ - lb[a++] = &(main->scene); - lb[a++] = &(main->wm); - lb[a++] = &(main->mask); + lb[INDEX_ID_AR] = &(main->armature); + + lb[INDEX_ID_CF] = &(main->cachefiles); + lb[INDEX_ID_ME] = &(main->mesh); + lb[INDEX_ID_CU] = &(main->curve); + lb[INDEX_ID_MB] = &(main->mball); + + lb[INDEX_ID_LT] = &(main->latt); + lb[INDEX_ID_LA] = &(main->lamp); + lb[INDEX_ID_CA] = &(main->camera); + + lb[INDEX_ID_TXT] = &(main->text); + lb[INDEX_ID_SO] = &(main->sound); + lb[INDEX_ID_GR] = &(main->group); + lb[INDEX_ID_PAL] = &(main->palettes); + lb[INDEX_ID_PC] = &(main->paintcurves); + lb[INDEX_ID_BR] = &(main->brush); + lb[INDEX_ID_PA] = &(main->particle); + lb[INDEX_ID_SPK] = &(main->speaker); + + lb[INDEX_ID_WO] = &(main->world); + lb[INDEX_ID_MC] = &(main->movieclip); + lb[INDEX_ID_SCR] = &(main->screen); + lb[INDEX_ID_OB] = &(main->object); + lb[INDEX_ID_LS] = &(main->linestyle); /* referenced by scenes */ + lb[INDEX_ID_SCE] = &(main->scene); + lb[INDEX_ID_WM] = &(main->wm); + lb[INDEX_ID_MSK] = &(main->mask); - lb[a] = NULL; - - BLI_assert(a + 1 == MAX_LIBARRAY); + lb[INDEX_ID_NULL] = NULL; - return a; + return (MAX_LIBARRAY - 1); } /* *********** ALLOC AND FREE ***************** @@ -913,6 +923,9 @@ void *BKE_libblock_alloc_notest(short type) case ID_PC: id = MEM_callocN(sizeof(PaintCurve), "Paint Curve"); break; + case ID_CF: + id = MEM_callocN(sizeof(CacheFile), "Cache File"); + break; } return id; } @@ -1039,6 +1052,9 @@ void BKE_libblock_init_empty(ID *id) case ID_LS: BKE_linestyle_init((FreestyleLineStyle *)id); break; + case ID_CF: + BKE_cachefile_init((CacheFile *)id); + break; case ID_KE: /* Shapekeys are a complex topic too - they depend on their 'user' data type... * They are not linkable, though, so it should never reach here anyway. */ @@ -1226,6 +1242,7 @@ void BKE_main_free(Main *mainvar) case 31: BKE_libblock_free_ex(mainvar, id, false); break; case 32: BKE_libblock_free_ex(mainvar, id, false); break; case 33: BKE_libblock_free_ex(mainvar, id, false); break; + case 34: BKE_libblock_free_ex(mainvar, id, false); break; default: BLI_assert(0); break; @@ -1639,22 +1656,20 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged for (a = set_listbasepointers(bmain, lbarray); a--; ) { id = lbarray[a]->first; - if (!id || !BKE_idcode_is_linkable(GS(id->name))) { - /* Do not explicitly make local non-linkable IDs (shapekeys, in fact), they are assumed to be handled - * by real datablocks responsible of them. */ - continue; - } + /* Do not explicitly make local non-linkable IDs (shapekeys, in fact), they are assumed to be handled + * by real datablocks responsible of them. */ + const bool do_skip = (id && !BKE_idcode_is_linkable(GS(id->name))); for (; id; id = id_next) { id->newid = NULL; id_next = id->next; /* id is possibly being inserted again */ - + /* The check on the second line (LIB_TAG_PRE_EXISTING) is done so its * possible to tag data you don't want to be made local, used for * appending data, so any libdata already linked wont become local * (very nasty to discover all your links are lost after appending) * */ - if (id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) && + if (!do_skip && id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) && ((untagged_only == false) || !(id->tag & LIB_TAG_PRE_EXISTING))) { if (lib == NULL || id->lib == lib) { diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index 90dcd96341e..5e4f5f160eb 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -305,7 +305,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u library_foreach_animationData(&data, adt); } - switch (GS(id->name)) { + switch ((ID_Type)GS(id->name)) { case ID_LI: { Library *lib = (Library *) id; @@ -846,6 +846,25 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } break; } + + /* Nothing needed for those... */ + case ID_IM: + case ID_VF: + case ID_TXT: + case ID_SO: + case ID_AR: + case ID_AC: + case ID_GD: + case ID_WM: + case ID_PAL: + case ID_PC: + case ID_CF: + break; + + /* Deprecated. */ + case ID_IP: + break; + } } while ((id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL)); @@ -888,7 +907,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id return id_type_can_have_animdata(id_type_owner); } - switch (id_type_owner) { + switch ((ID_Type)id_type_owner) { case ID_LI: return ELEM(id_type_used, ID_LI); case ID_SCE: @@ -947,9 +966,24 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id return ELEM(id_type_used, ID_MC); /* WARNING! mask->parent.id, not typed. */ case ID_LS: return (ELEM(id_type_used, ID_TE, ID_OB) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used)); - default: + case ID_IM: + case ID_VF: + case ID_TXT: + case ID_SO: + case ID_AR: + case ID_AC: + case ID_GD: + case ID_WM: + case ID_PAL: + case ID_PC: + case ID_CF: + /* Those types never use/reference other IDs... */ + return false; + case ID_IP: + /* Deprecated... */ return false; } + return false; } diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index a7b93cf3cb1..9b89a2fb807 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -38,6 +38,7 @@ #include "DNA_armature_types.h" #include "DNA_brush_types.h" #include "DNA_camera_types.h" +#include "DNA_cachefile_types.h" #include "DNA_group_types.h" #include "DNA_gpencil_types.h" #include "DNA_ipo_types.h" @@ -69,6 +70,7 @@ #include "BKE_armature.h" #include "BKE_brush.h" #include "BKE_camera.h" +#include "BKE_cachefile.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_fcurve.h" @@ -812,6 +814,9 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user) case ID_PC: BKE_paint_curve_free((PaintCurve *)id); break; + case ID_CF: + BKE_cachefile_free((CacheFile *)id); + break; } /* avoid notifying on removed data */ @@ -870,8 +875,8 @@ void BKE_libblock_delete(Main *bmain, void *idv) BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); /* First tag all datablocks directly from target lib. - * Note that we go forward here, since we want to check dependencies before users (e.g. meshes before objects). - * Avoids to have to loop twice. */ + * Note that we go forward here, since we want to check dependencies before users (e.g. meshes before objects). + * Avoids to have to loop twice. */ for (i = 0; i < base_count; i++) { ListBase *lb = lbarray[i]; ID *id; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 470108545b8..54945242fe4 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -58,6 +58,7 @@ #include "BKE_animsys.h" #include "BKE_displist.h" #include "BKE_global.h" +#include "BKE_depsgraph.h" #include "BKE_icons.h" #include "BKE_image.h" #include "BKE_library.h" @@ -398,7 +399,7 @@ static void material_data_index_clear_id(ID *id) } } -void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user) +void BKE_material_resize_id(Main *bmain, ID *id, short totcol, bool do_id_user) { Material ***matar = give_matarar_id(id); short *totcolp = give_totcolp_id(id); @@ -424,9 +425,11 @@ void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user) *matar = MEM_recallocN(*matar, sizeof(void *) * totcol); } *totcolp = totcol; + + DAG_relations_tag_update(bmain); } -void BKE_material_append_id(ID *id, Material *ma) +void BKE_material_append_id(Main *bmain, ID *id, Material *ma) { Material ***matar; if ((matar = give_matarar_id(id))) { @@ -439,11 +442,12 @@ void BKE_material_append_id(ID *id, Material *ma) (*matar)[(*totcol)++] = ma; id_us_plus((ID *)ma); - test_all_objects_materials(G.main, id); + test_all_objects_materials(bmain, id); + DAG_relations_tag_update(bmain); } } -Material *BKE_material_pop_id(ID *id, int index_i, bool update_data) +Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data) { short index = (short)index_i; Material *ret = NULL; @@ -472,13 +476,15 @@ Material *BKE_material_pop_id(ID *id, int index_i, bool update_data) /* decrease mat_nr index */ material_data_index_remove_id(id, index); } + + DAG_relations_tag_update(bmain); } } return ret; } -void BKE_material_clear_id(struct ID *id, bool update_data) +void BKE_material_clear_id(Main *bmain, ID *id, bool update_data) { Material ***matar; if ((matar = give_matarar_id(id))) { @@ -497,6 +503,8 @@ void BKE_material_clear_id(struct ID *id, bool update_data) /* decrease mat_nr index */ material_data_index_clear_id(id); } + + DAG_relations_tag_update(bmain); } } @@ -553,7 +561,7 @@ Material *give_node_material(Material *ma) return NULL; } -void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user) +void BKE_material_resize_object(Main *bmain, Object *ob, const short totcol, bool do_id_user) { Material **newmatar; char *newmatbits; @@ -590,6 +598,8 @@ void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user) ob->totcol = totcol; if (ob->totcol && ob->actcol == 0) ob->actcol = 1; if (ob->actcol > ob->totcol) ob->actcol = ob->totcol; + + DAG_relations_tag_update(bmain); } void test_object_materials(Object *ob, ID *id) @@ -601,7 +611,7 @@ void test_object_materials(Object *ob, ID *id) return; } - BKE_material_resize_object(ob, *totcol, false); + BKE_material_resize_object(G.main, ob, *totcol, false); } void test_all_objects_materials(Main *bmain, ID *id) @@ -617,7 +627,7 @@ void test_all_objects_materials(Main *bmain, ID *id) BKE_main_lock(bmain); for (ob = bmain->object.first; ob; ob = ob->id.next) { if (ob->data == id) { - BKE_material_resize_object(ob, *totcol, false); + BKE_material_resize_object(bmain, ob, *totcol, false); } } BKE_main_unlock(bmain); @@ -1881,7 +1891,7 @@ static short mesh_getmaterialnumber(Mesh *me, Material *ma) /* append material */ static short mesh_addmaterial(Mesh *me, Material *ma) { - BKE_material_append_id(&me->id, NULL); + BKE_material_append_id(G.main, &me->id, NULL); me->mat[me->totcol - 1] = ma; id_us_plus(&ma->id); @@ -2020,7 +2030,7 @@ static void convert_tfacematerial(Main *main, Material *ma) /* remove material from mesh */ for (a = 0; a < me->totcol; ) { if (me->mat[a] == ma) { - BKE_material_pop_id(&me->id, a, true); + BKE_material_pop_id(main, &me->id, a, true); } else { a++; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 733e9030056..ba3aef81514 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2197,8 +2197,10 @@ Mesh *BKE_mesh_new_from_object( { Mesh *tmpmesh; Curve *tmpcu = NULL, *copycu; - int render = settings == eModifierMode_Render, i; - int cage = !apply_modifiers; + int i; + const bool render = (settings == eModifierMode_Render); + const bool cage = !apply_modifiers; + bool do_mat_id_us = true; /* perform the mesh extraction based on type */ switch (ob->type) { @@ -2268,6 +2270,12 @@ Mesh *BKE_mesh_new_from_object( BKE_mesh_texspace_copy_from_object(tmpmesh, ob); BKE_libblock_free_us(bmain, tmpobj); + + /* XXX The curve to mesh conversion is convoluted... But essentially, BKE_mesh_from_nurbs_displist() + * already transfers the ownership of materials from the temp copy of the Curve ID to the new + * Mesh ID, so we do not want to increase materials' usercount later. */ + do_mat_id_us = false; + break; } @@ -2315,8 +2323,11 @@ Mesh *BKE_mesh_new_from_object( if (cage) { /* copies the data */ tmpmesh = BKE_mesh_copy(bmain, ob->data); - /* if not getting the original caged mesh, get final derived mesh */ + + /* XXX BKE_mesh_copy() already handles materials usercount. */ + do_mat_id_us = false; } + /* if not getting the original caged mesh, get final derived mesh */ else { /* Make a dummy mesh, saves copying */ DerivedMesh *dm; @@ -2360,7 +2371,7 @@ Mesh *BKE_mesh_new_from_object( tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpcu->mat[i]; - if (tmpmesh->mat[i]) { + if (do_mat_id_us && tmpmesh->mat[i]) { id_us_plus(&tmpmesh->mat[i]->id); } } @@ -2379,7 +2390,7 @@ Mesh *BKE_mesh_new_from_object( /* are we an object material or data based? */ tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpmb->mat[i]; - if (tmpmesh->mat[i]) { + if (do_mat_id_us && tmpmesh->mat[i]) { id_us_plus(&tmpmesh->mat[i]->id); } } @@ -2399,7 +2410,7 @@ Mesh *BKE_mesh_new_from_object( /* are we an object material or data based? */ tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i]; - if (tmpmesh->mat[i]) { + if (do_mat_id_us && tmpmesh->mat[i]) { id_us_plus(&tmpmesh->mat[i]->id); } } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 0d362086134..6794a8e8f93 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1033,7 +1033,7 @@ static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, ImBu stableibuf = cache->stabilized.ibuf; - BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); + BKE_tracking_stabilization_data_get(clip, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); /* check for stabilization parameters */ if (tscale != cache->stabilized.scale || @@ -1057,7 +1057,7 @@ static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user float tloc[2], tscale, tangle; int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr); - stableibuf = BKE_tracking_stabilize_frame(&clip->tracking, clip_framenr, ibuf, tloc, &tscale, &tangle); + stableibuf = BKE_tracking_stabilize_frame(clip, clip_framenr, ibuf, tloc, &tscale, &tangle); copy_v2_v2(cache->stabilized.loc, tloc); @@ -1247,8 +1247,6 @@ static void free_buffers(MovieClip *clip) IMB_free_anim(clip->anim); clip->anim = NULL; } - - BKE_animdata_free((ID *) clip, false); } void BKE_movieclip_clear_cache(MovieClip *clip) @@ -1270,8 +1268,6 @@ void BKE_movieclip_reload(MovieClip *clip) /* clear cache */ free_buffers(clip); - clip->tracking.stabilization.ok = false; - /* update clip source */ detect_clip_source(clip); @@ -1489,6 +1485,7 @@ void BKE_movieclip_free(MovieClip *clip) free_buffers(clip); BKE_tracking_free(&clip->tracking); + BKE_animdata_free((ID *) clip, false); } MovieClip *BKE_movieclip_copy(Main *bmain, MovieClip *clip) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 84e7b855592..b03eaa5bf85 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1148,7 +1148,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) /* increase user numbers */ id_us_plus((ID *)obn->data); id_us_plus((ID *)obn->gpd); - id_lib_extern((ID *)obn->dup_group); + id_us_plus((ID *)obn->dup_group); for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 21a0246353e..14cc5ec0849 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -221,31 +221,39 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild if (ctx->group) { unsigned int lay = ctx->group->layer; + int groupid = 0; GroupObject *go; - for (go = ctx->group->gobject.first; go; go = go->next) { + for (go = ctx->group->gobject.first; go; go = go->next, groupid++) { Object *ob = go->ob; if ((ob->lay & lay) && ob != obedit && is_child(ob, parent)) { + DupliContext pctx; + copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false); + /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ - make_child_duplis_cb(ctx, userdata, ob); + make_child_duplis_cb(&pctx, userdata, ob); } } } else { unsigned int lay = ctx->scene->lay; + int baseid = 0; Base *base; - for (base = ctx->scene->base.first; base; base = base->next) { + for (base = ctx->scene->base.first; base; base = base->next, baseid++) { Object *ob = base->object; if ((base->lay & lay) && ob != obedit && is_child(ob, parent)) { + DupliContext pctx; + copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false); + /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ - make_child_duplis_cb(ctx, userdata, ob); + make_child_duplis_cb(&pctx, userdata, ob); } } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 42b818b35a5..aecaf8537bb 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3172,6 +3172,9 @@ void object_remove_particle_system(Scene *UNUSED(scene), Object *ob) /* clear particle system */ BLI_remlink(&ob->particlesystem, psys); + if (psys->part) { + id_us_min(&psys->part->id); + } psys_free(ob, psys); if (ob->particlesystem.first) @@ -4050,13 +4053,16 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, uv[0] = uv[1] = 0.f; + /* Grid distribution doesn't support UV or emit from vertex mode */ + bool is_grid = (part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT); + if (cpa) { if ((part->childtype == PART_CHILD_FACES) && (psmd->dm_final != NULL)) { CustomData *mtf_data = psmd->dm_final->getTessFaceDataLayout(psmd->dm_final); const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE); mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx); - if (mtface) { + if (mtface && !is_grid) { mface = psmd->dm_final->getTessFaceData(psmd->dm_final, cpa->num, CD_MFACE); mtface += cpa->num; psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv); @@ -4070,7 +4076,7 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, } } - if ((part->from == PART_FROM_FACE) && (psmd->dm_final != NULL)) { + if ((part->from == PART_FROM_FACE) && (psmd->dm_final != NULL) && !is_grid) { CustomData *mtf_data = psmd->dm_final->getTessFaceDataLayout(psmd->dm_final); const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE); mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 8e3e2f5d6d0..b4e951ce04a 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2183,7 +2183,6 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f * http://en.wikipedia.org/wiki/Newton's_method * ************************************************/ -#define COLLISION_MAX_COLLISIONS 10 #define COLLISION_MIN_RADIUS 0.001f #define COLLISION_MIN_DISTANCE 0.0001f #define COLLISION_ZERO 0.00001f @@ -2570,10 +2569,6 @@ void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay pce.inside = 0; pce.index = index; - /* don't collide with same face again */ - if (col->hit == col->current && col->pce.index == index && col->pce.tot == 3) - return; - collision = collision_sphere_to_tri(col, ray->radius, &pce, &t); if (col->pce.inside == 0) { collision += collision_sphere_to_edges(col, ray->radius, &pce, &t); @@ -2609,8 +2604,17 @@ static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRay hit->dist = col->original_ray_length = 0.000001f; for (coll = colliders->first; coll; coll=coll->next) { - /* for boids: don't check with current ground object */ - if (coll->ob == col->skip) + /* for boids: don't check with current ground object; also skip if permeated */ + bool skip = false; + + for (int i = 0; i < col->skip_count; i++) { + if (coll->ob == col->skip[i]) { + skip = true; + break; + } + } + + if (skip) continue; /* particles should not collide with emitter at birth */ @@ -2746,7 +2750,7 @@ static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeR if (through==0 && ((vc_dot>0.0f && v0_dot>0.0f && vc_dot>v0_dot) || (vc_dot<0.0f && v0_dot<0.0f && vc_dot<v0_dot))) mul_v3_v3fl(v0_nor, pce->nor, vc_dot); else if (v0_dot > 0.f) - mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? -1.0f : 1.0f) * v0_dot); + mul_v3_v3fl(v0_nor, pce->nor, vc_dot + v0_dot); else mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot); @@ -2801,8 +2805,10 @@ static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeR col->f = f; } - col->prev = col->hit; - col->prev_index = hit->index; + /* if permeability random roll succeeded, disable collider for this sim step */ + if (through) { + col->skip[col->skip_count++] = col->hit; + } return 1; } @@ -2863,16 +2869,16 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa if (part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) { col.boid = 1; col.boid_z = pa->state.co[2]; - col.skip = pa->boid->ground; + col.skip[col.skip_count++] = pa->boid->ground; } /* 10 iterations to catch multiple collisions */ - while (collision_count < COLLISION_MAX_COLLISIONS) { + while (collision_count < PARTICLE_COLLISION_MAX_COLLISIONS) { if (collision_detect(pa, &col, &hit, sim->colliders)) { collision_count++; - if (collision_count == COLLISION_MAX_COLLISIONS) + if (collision_count == PARTICLE_COLLISION_MAX_COLLISIONS) collision_fail(pa, &col); else if (collision_response(pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN)==0) return; @@ -3919,7 +3925,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ /* 2. try to read from the cache */ if (pid) { - int cache_result = BKE_ptcache_read(pid, cache_cfra); + int cache_result = BKE_ptcache_read(pid, cache_cfra, true); if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) { cached_step(sim, cfra); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 69a98c06000..30eb8dcb287 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1137,13 +1137,13 @@ static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_ OpenVDB_import_grid_fl(reader, "density", &dens, sds->res_wt); - if (fluid_fields & SM_ACTIVE_FIRE) { + if (cache_fields & SM_ACTIVE_FIRE) { OpenVDB_import_grid_fl(reader, "flame", &flame, sds->res_wt); OpenVDB_import_grid_fl(reader, "fuel", &fuel, sds->res_wt); OpenVDB_import_grid_fl(reader, "react", &react, sds->res_wt); } - if (fluid_fields & SM_ACTIVE_COLORS) { + if (cache_fields & SM_ACTIVE_COLORS) { OpenVDB_import_grid_vec(reader, "color", &r, &g, &b, sds->res_wt); } @@ -2632,7 +2632,7 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) } /* reads cache from disk or memory */ /* possible to get old or interpolated result */ -int BKE_ptcache_read(PTCacheID *pid, float cfra) +int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old) { int cfrai = (int)floor(cfra), cfra1=0, cfra2=0; int ret = 0; @@ -2658,10 +2658,17 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra) return 0; /* don't read old cache if already simulated past cached frame */ - if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) - return 0; - if (cfra1 && cfra1 == cfra2) - return 0; + if (no_extrapolate_old) { + if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) + return 0; + if (cfra1 && cfra1 == cfra2) + return 0; + } + else { + /* avoid calling interpolate between the same frame values */ + if (cfra1 && cfra1 == cfra2) + cfra1 = 0; + } if (cfra1) { if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) { diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 0f1f9b4bdf7..c3ae5736aa9 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1560,14 +1560,16 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) /* try to read from cache */ // RB_TODO deal with interpolated, old and baked results - if (BKE_ptcache_read(&pid, ctime)) { + bool can_simulate = (ctime == rbw->ltime + 1) && !(cache->flag & PTCACHE_BAKED); + + if (BKE_ptcache_read(&pid, ctime, can_simulate)) { BKE_ptcache_validate(cache, (int)ctime); rbw->ltime = ctime; return; } /* advance simulation, we can only step one frame forward */ - if (ctime == rbw->ltime + 1 && !(cache->flag & PTCACHE_BAKED)) { + if (can_simulate) { /* write cache for first frame when on second frame */ if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { BKE_ptcache_write(&pid, startframe); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 4a1d279545e..acf6a313989 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -65,6 +65,7 @@ #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_cachefile.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" #include "BKE_editmesh.h" @@ -161,7 +162,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) if (type == SCE_COPY_EMPTY) { ListBase rl, rv; - /* XXX. main should become an arg */ scen = BKE_scene_add(bmain, sce->id.name + 2); rl = scen->r.layers; @@ -290,7 +290,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) /* duplicate Grease Pencil Drawing Brushes */ BLI_listbase_clear(&ts->gp_brushes); for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) { - bGPDbrush *newbrush = gpencil_brush_duplicate(brush); + bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush); BLI_addtail(&ts->gp_brushes, newbrush); } @@ -342,7 +342,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) /* grease pencil */ if (scen->gpd) { if (type == SCE_COPY_FULL) { - scen->gpd = gpencil_data_duplicate(bmain, scen->gpd, false); + scen->gpd = BKE_gpencil_data_duplicate(bmain, scen->gpd, false); } else if (type == SCE_COPY_EMPTY) { scen->gpd = NULL; @@ -441,7 +441,7 @@ void BKE_scene_free(Scene *sce) MEM_freeN(sce->toolsettings->uvsculpt); } /* free Grease Pencil Drawing Brushes */ - free_gpencil_brushes(&sce->toolsettings->gp_brushes); + BKE_gpencil_free_brushes(&sce->toolsettings->gp_brushes); BLI_freelistN(&sce->toolsettings->gp_brushes); BKE_paint_free(&sce->toolsettings->imapaint.paint); @@ -1559,10 +1559,11 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state) #else finish_time = PIL_check_seconds_timer(); tot_thread = BLI_system_thread_count(); + int total_objects = 0; for (i = 0; i < tot_thread; i++) { - int total_objects = 0; - double total_time = 0.0; + int thread_total_objects = 0; + double thread_total_time = 0.0; StatisicsEntry *entry; if (state->has_updated_objects) { @@ -1571,11 +1572,14 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state) entry; entry = entry->next) { - total_objects++; - total_time += entry->duration; + thread_total_objects++; + thread_total_time += entry->duration; } - printf("Thread %d: total %d objects in %f sec.\n", i, total_objects, total_time); + printf("Thread %d: total %d objects in %f sec.\n", + i, + thread_total_objects, + thread_total_time); for (entry = state->statistics[i].first; entry; @@ -1583,12 +1587,16 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state) { printf(" %s in %f sec\n", entry->object->id.name + 2, entry->duration); } + + total_objects += thread_total_objects; } BLI_freelistN(&state->statistics[i]); } if (state->has_updated_objects) { - printf("Scene update in %f sec\n", finish_time - state->base_time); + printf("Scene updated %d objects in %f sec\n", + total_objects, + finish_time - state->base_time); } #endif } @@ -1926,6 +1934,9 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, BKE_mask_evaluate_all_masks(bmain, ctime, true); + /* Update animated cache files for modifiers. */ + BKE_cachefile_update_frame(bmain, sce, ctime, (((double)sce->r.frs_sec) / (double)sce->r.frs_sec_base)); + #ifdef POSE_ANIMATION_WORKAROUND scene_armature_depsgraph_workaround(bmain); #endif diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 6067a8b2d9b..c240aa27343 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1656,6 +1656,9 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render else if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE)) { BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); } + else if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { + BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + } else if (sanim && sanim->anim && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)) { char fname[FILE_MAXFILE]; BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); @@ -1675,13 +1678,21 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render if (view_id > 0) BLI_snprintf(suffix, sizeof(suffix), "_%d", view_id); - if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && sanim && sanim->anim && + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE) { - BLI_join_dirfile(name, PROXY_MAXFILE, - dir, proxy->file); - BLI_path_abs(name, G.main->name); - BLI_snprintf(name, PROXY_MAXFILE, "%s_%s", name, suffix); + char fname[FILE_MAXFILE]; + BLI_join_dirfile(fname, PROXY_MAXFILE, dir, proxy->file); + BLI_path_abs(fname, G.main->name); + if (suffix[0] != '\0') { + /* TODO(sergey): This will actually append suffix after extension + * which is weird but how was originally coded in multiview branch. + */ + BLI_snprintf(name, PROXY_MAXFILE, "%s_%s", fname, suffix); + } + else { + BLI_strncpy(name, fname, PROXY_MAXFILE); + } return true; } @@ -5595,3 +5606,31 @@ int BKE_sequencer_find_next_prev_edit( return best_frame; } + +static void sequencer_all_free_anim_ibufs(ListBase *seqbase, int cfra) +{ + for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) { + if (seq->enddisp < cfra || seq->startdisp > cfra) { + BKE_sequence_free_anim(seq); + } + if (seq->type == SEQ_TYPE_META) { + sequencer_all_free_anim_ibufs(&seq->seqbase, cfra); + } + } +} + +void BKE_sequencer_all_free_anim_ibufs(int cfra) +{ + BKE_sequencer_cache_cleanup(); + for (Scene *scene = G.main->scene.first; + scene != NULL; + scene = scene->id.next) + { + Editing *ed = BKE_sequencer_editing_get(scene, false); + if (ed == NULL) { + /* Ignore scenes without sequencer. */ + continue; + } + sequencer_all_free_anim_ibufs(&ed->seqbase, cfra); + } +} diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 43569f9ded2..f622d541f3a 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -2737,19 +2737,18 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object * return; } + /* only calculate something when we advanced a single frame */ + /* don't simulate if viewing start frame, but scene frame is not real start frame */ + bool can_simulate = (framenr == (int)smd->time + 1) && (framenr == scene->r.cfra); + /* try to read from cache */ - if (BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) { + if (BKE_ptcache_read(&pid, (float)framenr, can_simulate) == PTCACHE_READ_EXACT) { BKE_ptcache_validate(cache, framenr); smd->time = framenr; return; } - /* only calculate something when we advanced a single frame */ - if (framenr != (int)smd->time + 1) - return; - - /* don't simulate if viewing start frame, but scene frame is not real start frame */ - if (framenr != scene->r.cfra) + if (!can_simulate) return; #ifdef DEBUG_TIME @@ -3052,9 +3051,15 @@ float smoke_get_velocity_at(struct Object *ob, float position[3], float velocity int smoke_get_data_flags(SmokeDomainSettings *sds) { int flags = 0; - if (smoke_has_heat(sds->fluid)) flags |= SM_ACTIVE_HEAT; - if (smoke_has_fuel(sds->fluid)) flags |= SM_ACTIVE_FIRE; - if (smoke_has_colors(sds->fluid)) flags |= SM_ACTIVE_COLORS; + + if (sds->fluid) { + if (smoke_has_heat(sds->fluid)) + flags |= SM_ACTIVE_HEAT; + if (smoke_has_fuel(sds->fluid)) + flags |= SM_ACTIVE_FIRE; + if (smoke_has_colors(sds->fluid)) + flags |= SM_ACTIVE_COLORS; + } return flags; } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 901926dd8d4..03cf33083da 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3719,9 +3719,12 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i } /* try to read from cache */ - cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe); + bool can_simulate = (framenr == sb->last_frame+1) && !(cache->flag & PTCACHE_BAKED); - if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { + cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate); + + if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED || + (!can_simulate && cache_result == PTCACHE_READ_OLD)) { softbody_to_object(ob, vertexCos, numVerts, sb->local); BKE_ptcache_validate(cache, framenr); @@ -3742,7 +3745,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i return; } - if (framenr!=sb->last_frame+1) + if (!can_simulate) return; /* if on second frame, write cache for first frame */ diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index e876bf43809..60f1eb6b98c 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2707,7 +2707,6 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) GPU_vertex_setup(dm); GPU_normal_setup(dm); GPU_triangle_setup(dm); - glShadeModel(GL_SMOOTH); for (a = 0; a < dm->drawObject->totmaterial; a++) { if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) { GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, dm->drawObject->materials[a].start, @@ -2811,8 +2810,6 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, } #endif - glShadeModel(GL_SMOOTH); - CCG_key_top_level(&key, ss); ccgdm_pbvh_update(ccgdm); @@ -2965,6 +2962,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, } } + glShadeModel(GL_SMOOTH); #undef PASSATTRIB } else { @@ -3170,8 +3168,6 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, MEM_freeN(mat_orig_to_new); MEM_freeN(matconv); } - - glShadeModel(GL_SMOOTH); } static void ccgDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial) @@ -3369,6 +3365,7 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, } } + glShadeModel(GL_SMOOTH); #undef PASSATTRIB } @@ -3503,7 +3500,6 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, next_actualFace = 0; - glShadeModel(GL_SMOOTH); /* lastFlag = 0; */ /* UNUSED */ for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) { GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index; @@ -3681,8 +3677,8 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, if (do_draw) { glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); ccgSubSurf_drawGLMesh(ss, true, -1, -1); + glShadeModel(GL_SMOOTH); } - glShadeModel(GL_SMOOTH); return; } #endif @@ -3744,10 +3740,6 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); } - /* no need to set shading mode to flat because - * normals are already used to change shading */ - glShadeModel(GL_SMOOTH); - for (S = 0; S < numVerts; S++) { CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); if (ln) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index a56fc0f9abe..a86606f1099 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -241,13 +241,9 @@ static void tracking_reconstruction_copy( /* Copy stabilization structure. */ static void tracking_stabilization_copy( - MovieTrackingStabilization *stabilization_dst, MovieTrackingStabilization *stabilization_src, - GHash *tracks_mapping) + MovieTrackingStabilization *stabilization_dst, MovieTrackingStabilization *stabilization_src) { *stabilization_dst = *stabilization_src; - if (stabilization_src->rot_track) { - stabilization_dst->rot_track = BLI_ghash_lookup(tracks_mapping, stabilization_src->rot_track); - } } /* Copy tracking object. */ @@ -284,7 +280,7 @@ void BKE_tracking_copy(MovieTracking *tracking_dst, MovieTracking *tracking_src) tracking_tracks_copy(&tracking_dst->tracks, &tracking_src->tracks, tracks_mapping); tracking_plane_tracks_copy(&tracking_dst->plane_tracks, &tracking_src->plane_tracks, tracks_mapping); tracking_reconstruction_copy(&tracking_dst->reconstruction, &tracking_src->reconstruction); - tracking_stabilization_copy(&tracking_dst->stabilization, &tracking_src->stabilization, tracks_mapping); + tracking_stabilization_copy(&tracking_dst->stabilization, &tracking_src->stabilization); if (tracking_src->act_track) { tracking_dst->act_track = BLI_ghash_lookup(tracks_mapping, tracking_src->act_track); } @@ -316,7 +312,7 @@ void BKE_tracking_copy(MovieTracking *tracking_dst, MovieTracking *tracking_src) } /* Initialize motion tracking settings to default values, - * used when new movie clip datablock is creating. + * used when new movie clip datablock is created. */ void BKE_tracking_settings_init(MovieTracking *tracking) { @@ -334,10 +330,22 @@ void BKE_tracking_settings_init(MovieTracking *tracking) tracking->settings.object_distance = 1; tracking->stabilization.scaleinf = 1.0f; + tracking->stabilization.anchor_frame = 1; + zero_v2(tracking->stabilization.target_pos); + tracking->stabilization.target_rot = 0.0f; + tracking->stabilization.scale = 1.0f; + + tracking->stabilization.act_track = 0; + tracking->stabilization.act_rot_track = 0; + tracking->stabilization.tot_track = 0; + tracking->stabilization.tot_rot_track = 0; + + tracking->stabilization.scaleinf = 1.0f; tracking->stabilization.locinf = 1.0f; tracking->stabilization.rotinf = 1.0f; tracking->stabilization.maxscale = 2.0f; tracking->stabilization.filter = TRACKING_FILTER_BILINEAR; + tracking->stabilization.flag |= TRACKING_SHOW_STAB_TRACKS; BKE_tracking_object_add(tracking, "Camera"); } @@ -552,6 +560,7 @@ MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking, ListBase *tr track->flag = settings->default_flag; track->algorithm_flag = settings->default_algorithm_flag; track->weight = settings->default_weight; + track->weight_stab = settings->default_weight; memset(&marker, 0, sizeof(marker)); marker.pos[0] = x; @@ -590,6 +599,12 @@ MovieTrackingTrack *BKE_tracking_track_duplicate(MovieTrackingTrack *track) new_track->markers = MEM_dupallocN(new_track->markers); + /* Orevent duplicate from being used for 2D stabilization. + * If necessary, it shall be added explicitly. + */ + new_track->flag &= ~TRACK_USE_2D_STAB; + new_track->flag &= ~TRACK_USE_2D_STAB_ROT; + return new_track; } diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index eb224020977..df42f253fdf 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -21,6 +21,7 @@ * Contributor(s): Blender Foundation, * Sergey Sharybin * Keir Mierle + * Ichthyostega * * ***** END GPL LICENSE BLOCK ***** */ @@ -28,292 +29,1484 @@ /** \file blender/blenkernel/intern/tracking_stabilize.c * \ingroup bke * - * This file contains implementation of 2D frame stabilization. + * This file contains implementation of 2D image stabilization. */ #include <limits.h> #include "DNA_movieclip_types.h" +#include "DNA_scene_types.h" +#include "DNA_anim_types.h" +#include "RNA_access.h" #include "BLI_utildefines.h" +#include "BLI_sort_utils.h" +#include "BLI_math_vector.h" #include "BLI_math.h" #include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BKE_fcurve.h" +#include "BLI_ghash.h" +#include "MEM_guardedalloc.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -/* Calculate median point of markers of tracks marked as used for - * 2D stabilization. - * - * NOTE: frame number should be in clip space, not scene space + +/* == Parameterization constants == */ + +/* When measuring the scale changes relative to the rotation pivot point, it + * might happen accidentally that a probe point (tracking point), which doesn't + * actually move on a circular path, gets very close to the pivot point, causing + * the measured scale contribution to go toward infinity. We damp this undesired + * effect by adding a bias (floor) to the measured distances, which will + * dominate very small distances and thus cause the corresponding track's + * contribution to diminish. + * Measurements happen in normalized (0...1) coordinates within a frame. + */ +static float SCALE_ERROR_LIMIT_BIAS = 0.01f; + +/* When to consider a track as completely faded out. + * This is used in conjunction with the "disabled" flag of the track + * to determine start positions, end positions and gaps + */ +static float EPSILON_WEIGHT = 0.005f; + + + +/* == private working data == */ + +/* Per track baseline for stabilization, defined at reference frame. + * A track's reference frame is chosen as close as possible to the (global) + * anchor_frame. Baseline holds the constant part of each track's contribution + * to the observed movement; it is calculated at initialization pass, using the + * measurement value at reference frame plus the average contribution to fill + * the gap between global anchor_frame and the reference frame for this track. + * This struct with private working data is associated to the local call context + * via `StabContext::private_track_data` */ -static bool stabilization_median_point_get(MovieTracking *tracking, int framenr, float median[2]) +typedef struct TrackStabilizationBase { + float stabilization_offset_base[2]; + + /* measured relative to translated pivot */ + float stabilization_rotation_base[2][2]; + + /* measured relative to translated pivot */ + float stabilization_scale_base; + + bool is_init_for_stabilization; + FCurve *track_weight_curve; +} TrackStabilizationBase; + +/* Tracks are reordered for initialization, starting as close as possible to + * anchor_frame + */ +typedef struct TrackInitOrder { + int sort_value; + int reference_frame; + MovieTrackingTrack *data; +} TrackInitOrder; + +/* Per frame private working data, for accessing possibly animated values. */ +typedef struct StabContext { + MovieClip *clip; + MovieTracking *tracking; + MovieTrackingStabilization *stab; + GHash *private_track_data; + FCurve *locinf; + FCurve *rotinf; + FCurve *scaleinf; + FCurve *target_pos[2]; + FCurve *target_rot; + FCurve *target_scale; + bool use_animation; +} StabContext; + + +static TrackStabilizationBase *access_stabilization_baseline_data( + StabContext *ctx, + MovieTrackingTrack *track) { - bool ok = false; - float min[2], max[2]; - MovieTrackingTrack *track; + return BLI_ghash_lookup(ctx->private_track_data, track); +} - INIT_MINMAX2(min, max); +static void attach_stabilization_baseline_data( + StabContext *ctx, + MovieTrackingTrack *track, + TrackStabilizationBase *private_data) +{ + return BLI_ghash_insert(ctx->private_track_data, track, private_data); +} - track = tracking->tracks.first; - while (track) { - if (track->flag & TRACK_USE_2D_STAB) { - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); +static void discard_stabilization_baseline_data(void *val) +{ + if (val != NULL) { + MEM_freeN(val); + } +} + + +/* == access animated values for given frame == */ + +static FCurve *retrieve_stab_animation(MovieClip *clip, + const char *data_path, + int idx) +{ + return id_data_find_fcurve(&clip->id, + &clip->tracking.stabilization, + &RNA_MovieTrackingStabilization, + data_path, + idx, + NULL); +} + +static FCurve *retrieve_track_weight_animation(MovieClip *clip, + MovieTrackingTrack *track) +{ + return id_data_find_fcurve(&clip->id, + track, + &RNA_MovieTrackingTrack, + "weight_stab", + 0, + NULL); +} + +static float fetch_from_fcurve(FCurve *animationCurve, + int framenr, + StabContext *ctx, + float default_value) +{ + if (ctx && ctx->use_animation && animationCurve) { + int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(ctx->clip, + framenr); + return evaluate_fcurve(animationCurve, scene_framenr); + } + return default_value; +} + + +static float get_animated_locinf(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->locinf, framenr, ctx, ctx->stab->locinf); +} + +static float get_animated_rotinf(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->rotinf, framenr, ctx, ctx->stab->rotinf); +} + +static float get_animated_scaleinf(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->scaleinf, framenr, ctx, ctx->stab->scaleinf); +} + +static void get_animated_target_pos(StabContext *ctx, + int framenr, + float target_pos[2]) +{ + target_pos[0] = fetch_from_fcurve(ctx->target_pos[0], + framenr, + ctx, + ctx->stab->target_pos[0]); + target_pos[1] = fetch_from_fcurve(ctx->target_pos[1], + framenr, + ctx, + ctx->stab->target_pos[1]); +} + +static float get_animated_target_rot(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->target_rot, + framenr, + ctx, + ctx->stab->target_rot); +} + +static float get_animated_target_scale(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->target_scale, framenr, ctx, ctx->stab->scale); +} + +static float get_animated_weight(StabContext *ctx, + MovieTrackingTrack *track, + int framenr) +{ + TrackStabilizationBase *working_data = + access_stabilization_baseline_data(ctx, track); + if (working_data && working_data->track_weight_curve) { + int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(ctx->clip, + framenr); + return evaluate_fcurve(working_data->track_weight_curve, scene_framenr); + } + /* Use weight at global 'current frame' as fallback default. */ + return track->weight_stab; +} + +static void use_values_from_fcurves(StabContext *ctx, bool toggle) +{ + if (ctx != NULL) { + ctx->use_animation = toggle; + } +} + + +/* Prepare per call private working area. + * Used for access to possibly animated values: retrieve available F-curves. + */ +static StabContext *initialize_stabilization_working_context(MovieClip *clip) +{ + StabContext *ctx = MEM_callocN(sizeof(StabContext), + "2D stabilization animation runtime data"); + ctx->clip = clip; + ctx->tracking = &clip->tracking; + ctx->stab = &clip->tracking.stabilization; + ctx->private_track_data = BLI_ghash_ptr_new( + "2D stabilization per track private working data"); + ctx->locinf = retrieve_stab_animation(clip, "influence_location", 0); + ctx->rotinf = retrieve_stab_animation(clip, "influence_rotation", 0); + ctx->scaleinf = retrieve_stab_animation(clip, "influence_scale", 0); + ctx->target_pos[0] = retrieve_stab_animation(clip, "target_pos", 0); + ctx->target_pos[1] = retrieve_stab_animation(clip, "target_pos", 1); + ctx->target_rot = retrieve_stab_animation(clip, "target_rot", 0); + ctx->target_scale = retrieve_stab_animation(clip, "target_zoom", 0); + ctx->use_animation = true; + return ctx; +} + +/* Discard all private working data attached to this call context. + * NOTE: We allocate the record for the per track baseline contribution + * locally for each call context (i.e. call to + * BKE_tracking_stabilization_data_get() + * Thus it is correct to discard all allocations found within the + * corresponding _local_ GHash + */ +static void discard_stabilization_working_context(StabContext *ctx) +{ + if (ctx != NULL) { + BLI_ghash_free(ctx->private_track_data, + NULL, + discard_stabilization_baseline_data); + MEM_freeN(ctx); + } +} + +static bool is_init_for_stabilization(StabContext *ctx, + MovieTrackingTrack *track) +{ + TrackStabilizationBase *working_data = + access_stabilization_baseline_data(ctx, track); + return (working_data != NULL && working_data->is_init_for_stabilization); +} + +static bool is_usable_for_stabilization(StabContext *ctx, + MovieTrackingTrack *track) +{ + return (track->flag & TRACK_USE_2D_STAB) && + is_init_for_stabilization(ctx, track); +} + +static bool is_effectively_disabled(StabContext *ctx, + MovieTrackingTrack *track, + MovieTrackingMarker *marker) +{ + return (marker->flag & MARKER_DISABLED) || + (EPSILON_WEIGHT > get_animated_weight(ctx, track, marker->framenr)); +} + + +static int search_closest_marker_index(MovieTrackingTrack *track, + int ref_frame) +{ + MovieTrackingMarker *markers = track->markers; + int end = track->markersnr; + int i = track->last_marker; + + i = MAX2(0, i); + i = MIN2(i, end - 1); + for ( ; i < end - 1 && markers[i].framenr <= ref_frame; ++i); + for ( ; 0 < i && markers[i].framenr > ref_frame; --i); + + track->last_marker = i; + return i; +} + +static void retrieve_next_higher_usable_frame(StabContext *ctx, + MovieTrackingTrack *track, + int i, + int ref_frame, + int *next_higher) +{ + MovieTrackingMarker *markers = track->markers; + int end = track->markersnr; + BLI_assert(0 <= i && i < end); + + while (i < end && + (markers[i].framenr < ref_frame || + is_effectively_disabled(ctx, track, &markers[i]))) + { + ++i; + } + if (i < end && markers[i].framenr < *next_higher) { + BLI_assert(markers[i].framenr >= ref_frame); + *next_higher = markers[i].framenr; + } +} - minmax_v2v2_v2(min, max, marker->pos); +static void retrieve_next_lower_usable_frame(StabContext *ctx, + MovieTrackingTrack *track, + int i, + int ref_frame, + int *next_lower) +{ + MovieTrackingMarker *markers = track->markers; + BLI_assert(0 <= i && i < track->markersnr); + while (i >= 0 && + (markers[i].framenr > ref_frame || + is_effectively_disabled(ctx, track, &markers[i]))) + { + --i; + } + if (0 <= i && markers[i].framenr > *next_lower) { + BLI_assert(markers[i].framenr <= ref_frame); + *next_lower = markers[i].framenr; + } +} - ok = true; +/* Find closest frames with usable stabilization data. + * A frame counts as _usable_ when there is at least one track marked for + * translation stabilization, which has an enabled tracking marker at this very + * frame. We search both for the next lower and next higher position, to allow + * the caller to interpolate gaps and to extrapolate at the ends of the + * definition range. + * + * NOTE: Regarding performance note that the individual tracks will cache the + * last search position. + */ +static void find_next_working_frames(StabContext *ctx, + int framenr, + int *next_lower, + int *next_higher) +{ + for (MovieTrackingTrack *track = ctx->tracking->tracks.first; + track != NULL; + track = track->next) + { + if (is_usable_for_stabilization(ctx, track)) { + int startpoint = search_closest_marker_index(track, framenr); + retrieve_next_higher_usable_frame(ctx, + track, + startpoint, + framenr, + next_higher); + retrieve_next_lower_usable_frame(ctx, + track, + startpoint, + framenr, + next_lower); } + } +} - track = track->next; + +/* Find active (enabled) marker closest to the reference frame. */ +static MovieTrackingMarker *get_closest_marker(StabContext *ctx, + MovieTrackingTrack *track, + int ref_frame) +{ + int next_lower = MINAFRAME; + int next_higher = MAXFRAME; + int i = search_closest_marker_index(track, ref_frame); + retrieve_next_higher_usable_frame(ctx, track, i, ref_frame, &next_higher); + retrieve_next_lower_usable_frame(ctx, track, i, ref_frame, &next_lower); + + if ((next_higher - ref_frame) < (ref_frame - next_lower)) { + return BKE_tracking_marker_get_exact(track, next_higher); } + else { + return BKE_tracking_marker_get_exact(track, next_lower); + } +} - median[0] = (max[0] + min[0]) / 2.0f; - median[1] = (max[1] + min[1]) / 2.0f; - return ok; +/* Retrieve tracking data, if available and applicable for this frame. + * The returned weight value signals the validity; data recorded for this + * tracking marker on the exact requested frame is output with the full weight + * of this track, while gaps in the data sequence cause the weight to go to zero. + */ +static MovieTrackingMarker *get_tracking_data_point( + StabContext *ctx, + MovieTrackingTrack *track, + int framenr, + float *r_weight) +{ + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr); + if (marker != NULL && !(marker->flag & MARKER_DISABLED)) { + *r_weight = get_animated_weight(ctx, track, framenr); + return marker; + } + else { + /* No marker at this frame (=gap) or marker disabled. */ + *r_weight = 0.0f; + return NULL; + } } -/* Calculate stabilization data (translation, scale and rotation) from - * given median of first and current frame medians, tracking data and - * frame number. + +/* Define the reference point for rotation/scale measurement and compensation. + * The stabilizator works by assuming the image was distorted by a affine linear + * transform, i.e. it was rotated and stretched around this reference point + * (pivot point) and then shifted laterally. Any scale and orientation changes + * will be picked up relative to this point. And later the image will be + * stabilized by rotating around this point. The result can only be as + * accurate as this pivot point actually matches the real rotation center + * of the actual movements. Thus any scheme to define a pivot point is + * always guesswork. * - * NOTE: frame number should be in clip space, not scene space + * As a simple default, we use the weighted average of the location markers + * of the current frame as pivot point. TODO It is planned to add further + * options, like e.g. anchoring the pivot point at the canvas. Moreover, + * it is planned to allow for a user controllable offset. */ -static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height, - const float firstmedian[2], const float median[2], - float translation[2], float *scale, float *angle) +static void setup_pivot(const float ref_pos[2], float r_pivot[2]) { - MovieTrackingStabilization *stab = &tracking->stabilization; + zero_v2(r_pivot); /* TODO: add an animated offset position here. */ + add_v2_v2(r_pivot, ref_pos); +} - *scale = (stab->scale - 1.0f) * stab->scaleinf + 1.0f; - *angle = 0.0f; - translation[0] = (firstmedian[0] - median[0]) * width * (*scale); - translation[1] = (firstmedian[1] - median[1]) * height * (*scale); +/* Calculate the contribution of a single track at the time position (frame) of + * the given marker. Each track has a local reference frame, which is as close + * as possible to the global anchor_frame. Thus the translation contribution is + * comprised of the offset relative to the image position at that reference + * frame, plus a guess of the contribution for the time span between the + * anchor_frame and the local reference frame of this track. The constant part + * of this contribution is precomputed initially. At the anchor_frame, by + * definition the contribution of all tracks is zero, keeping the frame in place. + * + * track_ref is per track baseline contribution at reference frame; filled in at + * initialization + * marker is tracking data to use as contribution for current frame. + * result_offset is a total cumulated contribution of this track, + * relative to the stabilization anchor_frame, + * in normalized (0...1) coordinates. + */ +static void translation_contribution(TrackStabilizationBase *track_ref, + MovieTrackingMarker *marker, + float result_offset[2]) +{ + add_v2_v2v2(result_offset, + track_ref->stabilization_offset_base, + marker->pos); +} + +/* Similar to the ::translation_contribution(), the rotation contribution is + * comprised of the contribution by this individual track, and the averaged + * contribution from anchor_frame to the ref point of this track. + * - Contribution is in terms of angles, -pi < angle < +pi, and all averaging + * happens in this domain. + * - Yet the actual measurement happens as vector between pivot and the current + * tracking point + * - Currently we use the center of frame as approximation for the rotation pivot + * point. + * - Moreover, the pivot point has to be compensated for the already determined + * shift offset, in order to get the pure rotation around the pivot. + * To turn this into a _contribution_, the likewise corrected angle at the + * reference frame has to be subtracted, to get only the pure angle difference + * this tracking point has captured. + * - To get from vectors to angles, we have to go through an arcus tangens, + * which involves the issue of the definition range: the resulting angles will + * flip by 360deg when the measured vector passes from the 2nd to the third + * quadrant, thus messing up the average calculation. Since _any_ tracking + * point might be used, these problems are quite common in practice. + * - Thus we perform the subtraction of the reference and the addition of the + * baseline contribution in polar coordinates as simple addition of angles; + * since these parts are fixed, we can bake them into a rotation matrix. + * With this approach, the border of the arcus tangens definition range will + * be reached only, when the _whole_ contribution approaches +- 180deg, + * meaning we've already tilted the frame upside down. This situation is way + * less common and can be tolerated. + * - As an additional feature, when activated, also changes in image scale + * relative to the rotation center can be picked up. To handle those values + * in the same framework, we average the scales as logarithms. + * + * aspect is a total aspect ratio of the undistorted image (includes fame and + * pixel aspect). The function returns a quality factor, which can be used + * to damp the contributions of points in close proximity to the pivot point, + * since such contributions might be dominated by rounding errors and thus + * poison the calculated average. When the quality factor goes towards zero, + * the weight of this contribution should be reduced accordingly. + */ +static float rotation_contribution(TrackStabilizationBase *track_ref, + MovieTrackingMarker *marker, + const float aspect, + const float pivot[2], + float *result_angle, + float *result_scale) +{ + float len, quality; + float pos[2]; + sub_v2_v2v2(pos, marker->pos, pivot); - mul_v2_fl(translation, stab->locinf); + pos[0] *= aspect; + mul_m2v2(track_ref->stabilization_rotation_base, pos); - if ((stab->flag & TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) { - MovieTrackingMarker *marker; - float a[2], b[2]; - float x0 = (float)width / 2.0f, y0 = (float)height / 2.0f; - float x = median[0] * width, y = median[1] * height; + *result_angle = atan2f(pos[1],pos[0]); - marker = BKE_tracking_marker_get(stab->rot_track, 1); - sub_v2_v2v2(a, marker->pos, firstmedian); - a[0] *= width; - a[1] *= height; + len = len_v2(pos); - marker = BKE_tracking_marker_get(stab->rot_track, framenr); - sub_v2_v2v2(b, marker->pos, median); - b[0] *= width; - b[1] *= height; + /* prevent points very close to the pivot point from poisoning the result */ + quality = 1 - expf(-len*len / SCALE_ERROR_LIMIT_BIAS*SCALE_ERROR_LIMIT_BIAS); + len += SCALE_ERROR_LIMIT_BIAS; - *angle = -atan2f(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]); - *angle *= stab->rotinf; + *result_scale = len * track_ref->stabilization_scale_base; + BLI_assert(0.0 < *result_scale); - /* convert to rotation around image center */ - translation[0] -= (x0 + (x - x0) * cosf(*angle) - (y - y0) * sinf(*angle) - x) * (*scale); - translation[1] -= (y0 + (x - x0) * sinf(*angle) + (y - y0) * cosf(*angle) - y) * (*scale); - } + return quality; } -/* Calculate factor of a scale, which will eliminate black areas - * appearing on the frame caused by frame translation. + +/* Workaround to allow for rotation around an arbitrary pivot point. + * Currently, the public API functions do not support this flexibility. + * Rather, rotation will always be applied around a fixed origin. + * As a workaround, we shift the image after rotation to match the + * desired rotation centre. And since this offset needs to be applied + * after the rotation and scaling, we can collapse it with the + * translation compensation, which is also a lateral shift (offset). + * The offset to apply is intended_pivot - rotated_pivot */ -static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, int width, int height) +static void compensate_rotation_center(const int size, float aspect, + const float angle, + const float scale, + const float pivot[2], + float result_translation[2]) { - float firstmedian[2]; + const float origin[2] = {0.5f*aspect*size, 0.5f*size}; + float intended_pivot[2], rotated_pivot[2]; + float rotation_mat[2][2]; + + copy_v2_v2(intended_pivot, pivot); + copy_v2_v2(rotated_pivot, pivot); + rotate_m2(rotation_mat, +angle); + sub_v2_v2(rotated_pivot, origin); + mul_m2v2(rotation_mat, rotated_pivot); + mul_v2_fl(rotated_pivot, scale); + add_v2_v2(rotated_pivot, origin); + add_v2_v2(result_translation, intended_pivot); + sub_v2_v2(result_translation, rotated_pivot); +} + + +/* Weighted average of the per track cumulated contributions at given frame. + * Returns truth if all desired calculations could be done and all averages are + * available. + * + * NOTE: Even if the result is not `true`, the returned translation and angle + * are always sensible and as good as can be. Especially in the + * initialization phase we might not be able to get any average (yet) or + * get only a translation value. Since initialization visits tracks in a + * specific order, starting from anchor_frame, the result is logically + * correct non the less. But under normal operation conditions, + * a result of `false` should disable the stabilization function + */ +static bool average_track_contributions(StabContext *ctx, + int framenr, + float aspect, + float r_translation[2], + float r_pivot[2], + float *r_angle, + float *r_scale_step) +{ + bool ok; + float weight_sum; + MovieTrackingTrack *track; + MovieTracking *tracking = ctx->tracking; MovieTrackingStabilization *stab = &tracking->stabilization; - float aspect = tracking->camera.pixel_aspect; - - /* Early output if stabilization data is already up-to-date. */ - if (stab->ok) - return stab->scale; - - /* See comment in BKE_tracking_stabilization_data_get about first frame. */ - if (stabilization_median_point_get(tracking, 1, firstmedian)) { - int sfra = INT_MAX, efra = INT_MIN, cfra; - float scale = 1.0f; - MovieTrackingTrack *track; - - stab->scale = 1.0f; - - /* Calculate frame range of tracks used for stabilization. */ - track = tracking->tracks.first; - while (track) { - if (track->flag & TRACK_USE_2D_STAB || - ((stab->flag & TRACKING_STABILIZE_ROTATION) && track == stab->rot_track)) - { - sfra = min_ii(sfra, track->markers[0].framenr); - efra = max_ii(efra, track->markers[track->markersnr - 1].framenr); - } + float ref_pos[2]; + BLI_assert(stab->flag & TRACKING_2D_STABILIZATION); - track = track->next; + zero_v2(r_translation); + *r_scale_step = 0.0f; /* logarithm */ + *r_angle = 0.0f; + + zero_v2(ref_pos); + + ok = false; + weight_sum = 0.0f; + for (track = tracking->tracks.first; track; track = track->next) { + if (!is_init_for_stabilization(ctx, track)) { + continue; + } + if (track->flag & TRACK_USE_2D_STAB) { + float weight = 0.0f; + MovieTrackingMarker *marker = get_tracking_data_point(ctx, + track, + framenr, + &weight); + if (marker) { + TrackStabilizationBase *stabilization_base = + access_stabilization_baseline_data(ctx, track); + BLI_assert(stabilization_base != NULL); + float offset[2]; + weight_sum += weight; + translation_contribution(stabilization_base, marker, offset); + r_translation[0] += weight * offset[0]; + r_translation[1] += weight * offset[1]; + ref_pos[0] += weight * marker->pos[0]; + ref_pos[1] += weight * marker->pos[1]; + ok |= (weight_sum > EPSILON_WEIGHT); + } } + } + if (!ok) { + return false; + } + + ref_pos[0] /= weight_sum; + ref_pos[1] /= weight_sum; + r_translation[0] /= weight_sum; + r_translation[1] /= weight_sum; + setup_pivot(ref_pos, r_pivot); + + if (!(stab->flag & TRACKING_STABILIZE_ROTATION)) { + return ok; + } - /* For every frame we calculate scale factor needed to eliminate black - * area and choose largest scale factor as final one. + ok = false; + weight_sum = 0.0f; + for (track = tracking->tracks.first; track; track = track->next) { + if (!is_init_for_stabilization(ctx, track)) { + continue; + } + if (track->flag & TRACK_USE_2D_STAB_ROT) { + float weight = 0.0f; + MovieTrackingMarker *marker = get_tracking_data_point(ctx, + track, + framenr, + &weight); + if (marker) { + TrackStabilizationBase *stabilization_base = + access_stabilization_baseline_data(ctx, track); + BLI_assert(stabilization_base != NULL); + float rotation, scale, quality; + quality = rotation_contribution(stabilization_base, + marker, + aspect, + r_pivot, + &rotation, + &scale); + weight *= quality; + weight_sum += weight; + *r_angle += rotation * weight; + if (stab->flag & TRACKING_STABILIZE_SCALE) { + *r_scale_step += logf(scale) * weight; + } + else { + *r_scale_step = 0; + } + ok |= (weight_sum > EPSILON_WEIGHT); + } + } + } + if (ok) { + *r_scale_step /= weight_sum; + *r_angle /= weight_sum; + } + else { + /* We reach this point because translation could be calculated, + * but rotation/scale found no data to work on. */ - for (cfra = sfra; cfra <= efra; cfra++) { - float median[2]; - float translation[2], angle, tmp_scale; - int i; - float mat[4][4]; - float points[4][2] = {{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}}; - float si, co; + *r_scale_step = 0.0f; + *r_angle = 0.0f; + } + return true; +} - stabilization_median_point_get(tracking, cfra, median); - stabilization_calculate_data(tracking, cfra, width, height, firstmedian, median, translation, - &tmp_scale, &angle); +/* Calculate weight center of location tracks for given frame. + * This function performs similar calculations as average_track_contributions(), + * but does not require the tracks to be initialized for stabilisation. Moreover, + * when there is no usable tracking data for the given frame number, data from + * a neighbouring frame is used. Thus this function can be used to calculate + * a starting point on initialization. + */ +static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_pos[2]) +{ + bool ok = false; + float weight_sum; + MovieTrackingTrack *track; + MovieTracking *tracking = ctx->tracking; - BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation, 1.0f, angle, mat); + zero_v2(r_ref_pos); + weight_sum = 0.0f; + for (track = tracking->tracks.first; track; track = track->next) { + if (track->flag & TRACK_USE_2D_STAB) { + float weight = 0.0f; + MovieTrackingMarker *marker = + get_tracking_data_point(ctx, track, framenr, &weight); + if (marker) { + weight_sum += weight; + r_ref_pos[0] += weight * marker->pos[0]; + r_ref_pos[1] += weight * marker->pos[1]; + ok |= (weight_sum > EPSILON_WEIGHT); + } + } + } + if (ok) { + r_ref_pos[0] /= weight_sum; + r_ref_pos[1] /= weight_sum; + } else { + /* No usable tracking data on any track on this frame. + * Use data from neighbouring frames to extrapolate... + */ + int next_lower = MINAFRAME; + int next_higher = MAXFRAME; + use_values_from_fcurves(ctx, true); + for (track = tracking->tracks.first; track; track = track->next) { + /* Note: we deliberately do not care if this track + * is already initialized for stabilisation */ + if (track->flag & TRACK_USE_2D_STAB) { + int startpoint = search_closest_marker_index(track, framenr); + retrieve_next_higher_usable_frame(ctx, + track, + startpoint, + framenr, + &next_higher); + retrieve_next_lower_usable_frame(ctx, + track, + startpoint, + framenr, + &next_lower); + } + } + if (next_lower >= MINFRAME) { + /* use next usable frame to the left. + * Also default to this frame when we're in a gap */ + average_marker_positions(ctx, next_lower, r_ref_pos); - si = sinf(angle); - co = cosf(angle); + } else if (next_higher < MAXFRAME) { + average_marker_positions(ctx, next_higher, r_ref_pos); + } + use_values_from_fcurves(ctx, false); + } +} - for (i = 0; i < 4; i++) { - int j; - float a[3] = {0.0f, 0.0f, 0.0f}, b[3] = {0.0f, 0.0f, 0.0f}; - copy_v3_v3(a, points[i]); - copy_v3_v3(b, points[(i + 1) % 4]); +/* Linear interpolation of data retrieved at two measurement points. + * This function is used to fill gaps in the middle of the covered area, + * at frames without any usable tracks for stabilization. + * + * framenr is a position to interpolate for. + * frame_a is a valid measurement point below framenr + * frame_b is a valid measurement point above framenr + * Returns truth if both measurements could actually be retrieved. + * Otherwise output parameters remain unaltered + */ +static bool interpolate_averaged_track_contributions(StabContext *ctx, + int framenr, + int frame_a, + int frame_b, + const float aspect, + float r_translation[2], + float r_pivot[2], + float *r_angle, + float *r_scale_step) +{ + float t, s; + float trans_a[2], trans_b[2]; + float angle_a, angle_b; + float scale_a, scale_b; + float pivot_a[2], pivot_b[2]; + bool success = false; + + BLI_assert(frame_a <= frame_b); + BLI_assert(frame_a <= framenr); + BLI_assert(framenr <= frame_b); + + t = ((float)framenr - frame_a) / (frame_b - frame_a); + s = 1.0f - t; + + success = average_track_contributions(ctx, frame_a, aspect, trans_a, pivot_a, &angle_a, &scale_a); + if (!success) { + return false; + } + success = average_track_contributions(ctx, frame_b, aspect, trans_b, pivot_b, &angle_b, &scale_b); + if (!success) { + return false; + } - mul_m4_v3(mat, a); - mul_m4_v3(mat, b); + interp_v2_v2v2(r_translation, trans_a, trans_b, t); + interp_v2_v2v2(r_pivot, pivot_a, pivot_b, t); + *r_scale_step = s * scale_a + t * scale_b; + *r_angle = s * angle_a + t * angle_b; + return true; +} - for (j = 0; j < 4; j++) { - float point[3] = {points[j][0], points[j][1], 0.0f}; - float v1[3], v2[3]; - sub_v3_v3v3(v1, b, a); - sub_v3_v3v3(v2, point, a); +/* Reorder tracks starting with those providing a tracking data frame + * closest to the global anchor_frame. Tracks with a gap at anchor_frame or + * starting farer away from anchor_frame altogether will be visited later. + * This allows to build up baseline contributions incrementally. + * + * order is an array for sorting the tracks. Must be of suitable size to hold + * all tracks. + * Returns number of actually usable tracks, can be less than the overall number + * of tracks. + * + * NOTE: After returning, the order array holds entries up to the number of + * usable tracks, appropriately sorted starting with the closest tracks. + * Initialization includes disabled tracks, since they might be enabled + * through automation later. + */ +static int establish_track_initialization_order(StabContext *ctx, + TrackInitOrder *order) +{ + size_t tracknr = 0; + MovieTrackingTrack *track; + MovieTracking *tracking = ctx->tracking; + int anchor_frame = tracking->stabilization.anchor_frame; - if (cross_v2v2(v1, v2) >= 0.0f) { - const float rotDx[4][2] = {{1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}, {0.0f, 1.0f}}; - const float rotDy[4][2] = {{0.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}}; + for (track = tracking->tracks.first; track != NULL; track = track->next) { + MovieTrackingMarker *marker; + order[tracknr].data = track; + marker = get_closest_marker(ctx, track, anchor_frame); + if (marker != NULL && + (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT))) + { + order[tracknr].sort_value = abs(marker->framenr - anchor_frame); + order[tracknr].reference_frame = marker->framenr; + ++tracknr; + } + } + if (tracknr) { + qsort(order, tracknr, sizeof(TrackInitOrder), BLI_sortutil_cmp_int); + } + return tracknr; +} - float dx = translation[0] * rotDx[j][0] + translation[1] * rotDx[j][1], - dy = translation[0] * rotDy[j][0] + translation[1] * rotDy[j][1]; - float w, h, E, F, G, H, I, J, K, S; +/* Setup the constant part of this track's contribution to the determined frame + * movement. Tracks usually don't provide tracking data for every frame. Thus, + * for determining data at a given frame, we split up the contribution into a + * part covered by actual measurements on this track, and the initial gap + * between this track's reference frame and the global anchor_frame. + * The (missing) data for the gap can be substituted by the average offset + * observed by the other tracks covering the gap. This approximation doesn't + * introduce wrong data, but it records data with incorrect weight. A totally + * correct solution would require us to average the contribution per frame, and + * then integrate stepwise over all frames -- which of course would be way more + * expensive, especially for longer clips. To the contrary, our solution + * cumulates the total contribution per track and averages afterwards over all + * tracks; it can thus be calculated just based on the data of a single frame, + * plus the "baseline" for the reference frame, which is what we are computing + * here. + * + * Since we're averaging _contributions_, we have to calculate the _difference_ + * of the measured position at current frame and the position at the reference + * frame. But the "reference" part of this difference is constant and can thus + * be packed together with the baseline contribution into a single precomputed + * vector per track. + * + * In case of the rotation contribution, the principle is the same, but we have + * to compensate for the already determined translation and measure the pure + * rotation, simply because this is how we model the offset: shift plus rotation + * around the shifted rotation center. To circumvent problems with the + * definition range of the arcus tangens function, we perform this baseline + * addition and reference angle subtraction in polar coordinates and bake this + * operation into a precomputed rotation matrix. + * + * track is a track to be initialized to initialize + * reference_frame is a local frame for this track, the closest pick to the + * global anchor_frame. + * aspect is a total aspect ratio of the undistorted image (includes fame and + * pixel aspect). + * target_pos is a possibly animated target position as set by the user for + * the reference_frame + * average_translation is a value observed by the _other_ tracks for the gap + * between reference_frame and anchor_frame. This + * average must not contain contributions of frames + * not yet initialized + * average_angle in a similar way, the rotation value observed by the + * _other_ tracks. + * average_scale_step is an image scale factor observed on average by the other + * tracks for this frame. This value is recorded and + * averaged as logarithm. The recorded scale changes + * are damped for very small contributions, to limit + * the effect of probe points approaching the pivot + * too closely. + * + * NOTE: when done, this track is marked as initialized + */ +static void initialize_track_for_stabilization(StabContext *ctx, + MovieTrackingTrack *track, + int reference_frame, + float aspect, + const float average_translation[2], + const float pivot[2], + const float average_angle, + const float average_scale_step) +{ + float pos[2], angle, len; + TrackStabilizationBase *local_data = + access_stabilization_baseline_data(ctx, track); + MovieTrackingMarker *marker = + BKE_tracking_marker_get_exact(track, reference_frame); + /* Logic for initialization order ensures there *is* a marker on that + * very frame. + */ + BLI_assert(marker != NULL); + BLI_assert(local_data != NULL); - if (j % 2) { - w = (float)height / 2.0f; - h = (float)width / 2.0f; - } - else { - w = (float)width / 2.0f; - h = (float)height / 2.0f; - } + /* Per track baseline value for translation. */ + sub_v2_v2v2(local_data->stabilization_offset_base, + average_translation, + marker->pos); - E = -w * co + h * si; - F = -h * co - w * si; + /* Per track baseline value for rotation. */ + sub_v2_v2v2(pos, marker->pos, pivot); - if ((i % 2) == (j % 2)) { - G = -w * co - h * si; - H = h * co - w * si; - } - else { - G = w * co + h * si; - H = -h * co + w * si; - } + pos[0] *= aspect; + angle = average_angle - atan2f(pos[1],pos[0]); + rotate_m2(local_data->stabilization_rotation_base, angle); - I = F - H; - J = G - E; - K = G * F - E * H; + /* Per track baseline value for zoom. */ + len = len_v2(pos) + SCALE_ERROR_LIMIT_BIAS; + local_data->stabilization_scale_base = expf(average_scale_step) / len; - S = (-w * I - h * J) / (dx * I + dy * J + K); + local_data->is_init_for_stabilization = true; +} - scale = max_ff(scale, S); - } - } - } + +static void initialize_all_tracks(StabContext *ctx, float aspect) +{ + size_t i, track_cnt = 0; + MovieClip *clip = ctx->clip; + MovieTracking *tracking = ctx->tracking; + MovieTrackingTrack *track; + TrackInitOrder *order; + + /* Attempt to start initialization at anchor_frame. + * By definition, offset contribution is zero there. + */ + int reference_frame = tracking->stabilization.anchor_frame; + float average_angle=0, average_scale_step=0; + float average_translation[2], average_pos[2], pivot[2]; + zero_v2(average_translation); + zero_v2(pivot); + + /* Initialize private working data. */ + for (track = tracking->tracks.first; track != NULL; track = track->next) { + TrackStabilizationBase *local_data = + access_stabilization_baseline_data(ctx, track); + if (!local_data) { + local_data = MEM_callocN(sizeof(TrackStabilizationBase), + "2D stabilization per track baseline data"); + attach_stabilization_baseline_data(ctx, track, local_data); } + BLI_assert(local_data != NULL); + local_data->track_weight_curve = retrieve_track_weight_animation(clip, + track); + local_data->is_init_for_stabilization = false; - stab->scale = scale; + ++track_cnt; + } + if (!track_cnt) { + return; + } - if (stab->maxscale > 0.0f) - stab->scale = min_ff(stab->scale, stab->maxscale); + order = MEM_mallocN(track_cnt * sizeof(TrackInitOrder), + "stabilization track order"); + if (!order) { + return; } - else { - stab->scale = 1.0f; + + track_cnt = establish_track_initialization_order(ctx, order); + if (track_cnt == 0) { + goto cleanup; } - stab->ok = true; + /* starting point for pivot, before having initialized any track */ + average_marker_positions(ctx, reference_frame, average_pos); + setup_pivot(average_pos, pivot); + + for (i = 0; i < track_cnt; ++i) { + track = order[i].data; + if (reference_frame != order[i].reference_frame) { + reference_frame = order[i].reference_frame; + average_track_contributions(ctx, + reference_frame, + aspect, + average_translation, + pivot, + &average_angle, + &average_scale_step); + } + initialize_track_for_stabilization(ctx, + track, + reference_frame, + aspect, + average_translation, + pivot, + average_angle, + average_scale_step); + } - return stab->scale; +cleanup: + MEM_freeN(order); } -/* Get stabilization data (translation, scaling and angle) for a given frame. + +/* Retrieve the measurement of frame movement by averaging contributions of + * active tracks. * - * NOTE: frame number should be in clip space, not scene space + * translation is a measurement in normalized 0..1 coordinates. + * angle is a measurement in radians -pi..+pi counter clockwise relative to + * translation compensated frame center + * scale_step is a measurement of image scale changes, in logarithmic scale + * (zero means scale == 1) + * Returns calculation enabled and all data retrieved as expected for this frame. + * + * NOTE: when returning `false`, output parameters are reset to neutral values. */ -void BKE_tracking_stabilization_data_get(MovieTracking *tracking, int framenr, int width, int height, - float translation[2], float *scale, float *angle) +static bool stabilization_determine_offset_for_frame(StabContext *ctx, + int framenr, + float aspect, + float r_translation[2], + float r_pivot[2], + float *r_angle, + float *r_scale_step) { - float firstmedian[2], median[2]; - MovieTrackingStabilization *stab = &tracking->stabilization; + bool success = false; /* Early output if stabilization is disabled. */ - if ((stab->flag & TRACKING_2D_STABILIZATION) == 0) { - zero_v2(translation); - *scale = 1.0f; - *angle = 0.0f; + if ((ctx->stab->flag & TRACKING_2D_STABILIZATION) == 0) { + zero_v2(r_translation); + *r_scale_step = 0.0f; + *r_angle = 0.0f; + return false; + } - return; + success = average_track_contributions(ctx, + framenr, + aspect, + r_translation, + r_pivot, + r_angle, + r_scale_step); + if (!success) { + /* Try to hold extrapolated settings beyond the definition range + * and to interpolate in gaps without any usable tracking data + * to prevent sudden jump to image zero position. + */ + int next_lower = MINAFRAME; + int next_higher = MAXFRAME; + use_values_from_fcurves(ctx, true); + find_next_working_frames(ctx, framenr, &next_lower, &next_higher); + if (next_lower >= MINFRAME && next_higher < MAXFRAME) { + success = interpolate_averaged_track_contributions(ctx, + framenr, + next_lower, + next_higher, + aspect, + r_translation, + r_pivot, + r_angle, + r_scale_step); + } + else if (next_higher < MAXFRAME) { + /* Before start of stabilized range: extrapolate start point + * settings. + */ + success = average_track_contributions(ctx, + next_higher, + aspect, + r_translation, + r_pivot, + r_angle, + r_scale_step); + } + else if (next_lower >= MINFRAME) { + /* After end of stabilized range: extrapolate end point settings. */ + success = average_track_contributions(ctx, + next_lower, + aspect, + r_translation, + r_pivot, + r_angle, + r_scale_step); + } + use_values_from_fcurves(ctx, false); } + return success; +} - /* Even if tracks does not start at frame 1, their position will - * be estimated at this frame, which will give reasonable result - * in most of cases. - * - * However, it's still better to replace this with real first - * frame number at which tracks are appearing. +/* Calculate stabilization data (translation, scale and rotation) from given raw + * measurements. Result is in absolute image dimensions (expanded image, square + * pixels), includes automatic or manual scaling and compensates for a target + * frame position, if given. + * + * size is a size of the expanded image, the width in pixels is size * aspect. + * aspect is a ratio (width / height) of the effective canvas (square pixels). + * do_compensate denotes whether to actually output values necessary to + * _compensate_ the determined frame movement. + * Otherwise, the effective target movement is returned. + */ +static void stabilization_calculate_data(StabContext *ctx, + int framenr, + int size, + float aspect, + bool do_compensate, + float scale_step, + float r_translation[2], + float r_pivot[2], + float *r_scale, + float *r_angle) +{ + float target_pos[2], target_scale; + float scaleinf = get_animated_scaleinf(ctx, framenr); + + if (ctx->stab->flag & TRACKING_STABILIZE_SCALE) { + *r_scale = expf(scale_step * scaleinf); /* Averaged in log scale */ + } else { + *r_scale = 1.0f; + } + + mul_v2_fl(r_translation, get_animated_locinf(ctx, framenr)); + *r_angle *= get_animated_rotinf(ctx, framenr); + + /* Compensate for a target frame position. + * This allows to follow tracking / panning shots in a semi manual fashion, + * when animating the settings for the target frame position. */ - if (stabilization_median_point_get(tracking, 1, firstmedian)) { - stabilization_median_point_get(tracking, framenr, median); + get_animated_target_pos(ctx, framenr, target_pos); + sub_v2_v2(r_translation, target_pos); + *r_angle -= get_animated_target_rot(ctx,framenr); + target_scale = get_animated_target_scale(ctx,framenr); + if (target_scale != 0.0f) { + *r_scale /= target_scale; + /* target_scale is an expected/intended reference zoom value */ + } + + /* Convert from relative to absolute coordinates, square pixels. */ + r_translation[0] *= (float)size * aspect; + r_translation[1] *= (float)size; + r_pivot[0] *= (float)size * aspect; + r_pivot[1] *= (float)size; + + /* Output measured data, or inverse of the measured values for + * compensation? + */ + if (do_compensate) { + mul_v2_fl(r_translation, -1.0f); + *r_angle *= -1.0f; + if (*r_scale != 0.0f) { + *r_scale = 1.0f / *r_scale; + } + } +} + +static void stabilization_data_to_mat4(float pixel_aspect, + const float pivot[2], + const float translation[2], + float scale, + float angle, + float r_mat[4][4]) +{ + float translation_mat[4][4], rotation_mat[4][4], scale_mat[4][4], + pivot_mat[4][4], inv_pivot_mat[4][4], + aspect_mat[4][4], inv_aspect_mat[4][4]; + float scale_vector[3] = {scale, scale, 1.0f}; - if ((stab->flag & TRACKING_AUTOSCALE) == 0) - stab->scale = 1.0f; + unit_m4(translation_mat); + unit_m4(rotation_mat); + unit_m4(scale_mat); + unit_m4(aspect_mat); + unit_m4(pivot_mat); + unit_m4(inv_pivot_mat); - if (!stab->ok) { - if (stab->flag & TRACKING_AUTOSCALE) - stabilization_calculate_autoscale_factor(tracking, width, height); + /* aspect ratio correction matrix */ + aspect_mat[0][0] /= pixel_aspect; + invert_m4_m4(inv_aspect_mat, aspect_mat); - stabilization_calculate_data(tracking, framenr, width, height, firstmedian, median, - translation, scale, angle); + add_v2_v2(pivot_mat[3], pivot); + sub_v2_v2(inv_pivot_mat[3], pivot); - stab->ok = true; + size_to_mat4(scale_mat, scale_vector); /* scale matrix */ + add_v2_v2(translation_mat[3], translation); /* translation matrix */ + rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */ + + /* Compose transformation matrix. */ + mul_m4_series(r_mat, aspect_mat, translation_mat, + pivot_mat, scale_mat, rotation_mat, inv_pivot_mat, + inv_aspect_mat); +} + +/* Calculate scale factor necessary to eliminate black image areas + * caused by the compensating movements of the stabilizator. + * This function visits every frame where stabilisation data is + * available and determines the factor for this frame. The overall + * largest factor found is returned as result. + * + * NOTE: all tracks need to be initialized before calling this function. + */ +static float calculate_autoscale_factor(StabContext *ctx, + int size, + float aspect) +{ + MovieTrackingStabilization *stab = ctx->stab; + float pixel_aspect = ctx->tracking->camera.pixel_aspect; + int height = size, width = aspect*size; + + int sfra = INT_MAX, efra = INT_MIN, cfra; + float scale = 1.0f, scale_step = 0.0f; + MovieTrackingTrack *track; + + /* Calculate maximal frame range of tracks where stabilization is active. */ + for (track = ctx->tracking->tracks.first; track; track = track->next) { + if ((track->flag & TRACK_USE_2D_STAB) || + ((stab->flag & TRACKING_STABILIZE_ROTATION) && + (track->flag & TRACK_USE_2D_STAB_ROT))) + { + int first_frame = track->markers[0].framenr; + int last_frame = track->markers[track->markersnr - 1].framenr; + sfra = min_ii(sfra, first_frame); + efra = max_ii(efra, last_frame); } - else { - stabilization_calculate_data(tracking, framenr, width, height, firstmedian, median, - translation, scale, angle); + } + + use_values_from_fcurves(ctx, true); + for (cfra = sfra; cfra <= efra; cfra++) { + float translation[2], pivot[2], angle, tmp_scale; + float mat[4][4]; + const float points[4][2] = {{0.0f, 0.0f}, + {0.0f, height}, + {width, height}, + {width, 0.0f}}; + const bool do_compensate = true; + /* Calculate stabilization parameters for the current frame. */ + stabilization_determine_offset_for_frame(ctx, + cfra, + aspect, + translation, + pivot, + &angle, + &scale_step); + stabilization_calculate_data(ctx, + cfra, + size, + aspect, + do_compensate, + scale_step, + translation, + pivot, + &tmp_scale, + &angle); + /* Compose transformation matrix. */ + /* NOTE: Here we operate in NON-COMPENSATED coordinates, meaning we have + * to construct transformation matrix using proper pivot point. + * Compensation for that will happen later on. + */ + stabilization_data_to_mat4(pixel_aspect, + pivot, + translation, + tmp_scale, + angle, + mat); + /* Investigate the transformed border lines for this frame; + * find out, where it cuts the original frame. + */ + for (int edge_index = 0; edge_index < 4; edge_index++) { + /* Calculate coordinates of stabilized frame edge points. + * Use matrix multiplication here so we operate in homogeneous + * coordinates. + */ + float stable_edge_p1[3], stable_edge_p2[3]; + copy_v2_v2(stable_edge_p1, points[edge_index]); + copy_v2_v2(stable_edge_p2, points[(edge_index + 1) % 4]); + stable_edge_p1[2] = stable_edge_p2[2] = 0.0f; + mul_m4_v3(mat, stable_edge_p1); + mul_m4_v3(mat, stable_edge_p2); + /* Now we iterate over all original frame corners (we call them + * 'point' here) to see if there's black area between stabilized + * frame edge and original point. + */ + for (int point_index = 0; point_index < 4; point_index++) { + const float point[3] = {points[point_index][0], + points[point_index][1], + 0.0f}; + /* Calculate vector which goes from first edge point to + * second one. + */ + float stable_edge_vec[3]; + sub_v3_v3v3(stable_edge_vec, stable_edge_p2, stable_edge_p1); + /* Calculate vector which connects current frame point to + * first edge point. + */ + float point_to_edge_start_vec[3]; + sub_v3_v3v3(point_to_edge_start_vec, point, stable_edge_p1); + /* Use this two vectors to check whether frame point is inside + * of the stabilized frame or not. + * If the point is inside, there is no black area happening + * and no scaling required for it. + */ + if (cross_v2v2(stable_edge_vec, point_to_edge_start_vec) >= 0.0f) { + /* We are scaling around motion-compensated pivot point. */ + float scale_pivot[2]; + add_v2_v2v2(scale_pivot, pivot, translation); + /* Calculate line which goes via `point` and parallel to + * the stabilized frame edge. This line is coming via + * `point` and `point2` at the end. + */ + float point2[2]; + add_v2_v2v2(point2, point, stable_edge_vec); + /* Calculate actual distance between pivot point and + * the stabilized frame edge. Then calculate distance + * between pivot point and line which goes via actual + * corner and is parallel to the edge. + * + * Dividing one by another will give us required scale + * factor to get rid of black areas. + */ + float real_dist = dist_to_line_v2(scale_pivot, + stable_edge_p1, + stable_edge_p2); + float required_dist = dist_to_line_v2(scale_pivot, + point, + point2); + const float S = required_dist / real_dist; + scale = max_ff(scale, S); + } + } } } + if (stab->maxscale > 0.0f) { + scale = min_ff(scale, stab->maxscale); + } + use_values_from_fcurves(ctx, false); + + return scale; +} + + +/* Prepare working data and determine reference point for each track. + * + * NOTE: These calculations _could_ be cached and reused for all frames of the + * same clip. However, since proper initialization depends on (weight) + * animation and setup of tracks, ensuring consistency of cached init data + * turns out to be tricky, hard to maintain and generally not worth the + * effort. Thus we'll re-initialize on every frame. + */ +static StabContext *init_stabilizer(MovieClip *clip, int size, float aspect) +{ + StabContext *ctx = initialize_stabilization_working_context(clip); + BLI_assert(ctx != NULL); + initialize_all_tracks(ctx, aspect); + if (ctx->stab->flag & TRACKING_AUTOSCALE) { + ctx->stab->scale = 1.0; + ctx->stab->scale = calculate_autoscale_factor(ctx, size, aspect); + } + /* By default, just use values for the global current frame. */ + use_values_from_fcurves(ctx, false); + return ctx; +} + + +/* === public interface functions === */ + +/* Get stabilization data (translation, scaling and angle) for a given frame. + * Returned data describes how to compensate the detected movement, but with any + * chosen scale factor already applied and any target frame position already + * compensated. In case stabilization fails or is disabled, neutral values are + * returned. + * + * framenr is a frame number, relative to the clip (not relative to the scene + * timeline) + * width is an effective width of the canvas (square pixels), used to scale the + * determined translation + * + * Outputs: + * - translation of the lateral shift, absolute canvas coordinates + * (square pixels). + * - scale of the scaling to apply + * - angle of the rotation angle, relative to the frame center + */ +/* TODO(sergey): Use r_ prefix for output parameters here. */ +void BKE_tracking_stabilization_data_get(MovieClip *clip, + int framenr, + int width, + int height, + float translation[2], + float *scale, + float *angle) +{ + StabContext *ctx = NULL; + MovieTracking *tracking = &clip->tracking; + bool enabled = (tracking->stabilization.flag & TRACKING_2D_STABILIZATION); + /* Might become a parameter of a stabilization compositor node. */ + bool do_compensate = true; + float scale_step = 0.0f; + float pixel_aspect = tracking->camera.pixel_aspect; + float aspect = (float)width * pixel_aspect / height; + int size = height; + float pivot[2]; + + if (enabled) { + ctx = init_stabilizer(clip, size, aspect); + } + + if (enabled && + stabilization_determine_offset_for_frame(ctx, + framenr, + aspect, + translation, + pivot, + angle, + &scale_step)) + { + stabilization_calculate_data(ctx, + framenr, + size, + aspect, + do_compensate, + scale_step, + translation, + pivot, + scale, + angle); + compensate_rotation_center(size, + aspect, + *angle, + *scale, + pivot, + translation); + } else { zero_v2(translation); *scale = 1.0f; *angle = 0.0f; } + discard_stabilization_working_context(ctx); } -/* Stabilize given image buffer using stabilization data for - * a specified frame number. +/* Stabilize given image buffer using stabilization data for a specified + * frame number. * - * NOTE: frame number should be in clip space, not scene space + * NOTE: frame number should be in clip space, not scene space. */ -ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf *ibuf, - float translation[2], float *scale, float *angle) +/* TODO(sergey): Use r_ prefix for output parameters here. */ +ImBuf *BKE_tracking_stabilize_frame(MovieClip *clip, + int framenr, + ImBuf *ibuf, + float translation[2], + float *scale, + float *angle) { float tloc[2], tscale, tangle; + MovieTracking *tracking = &clip->tracking; MovieTrackingStabilization *stab = &tracking->stabilization; ImBuf *tmpibuf; int width = ibuf->x, height = ibuf->y; - float aspect = tracking->camera.pixel_aspect; + float pixel_aspect = tracking->camera.pixel_aspect; float mat[4][4]; int j, filter = tracking->stabilization.filter; void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL; @@ -349,8 +1542,12 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ibuf_flags); /* Calculate stabilization matrix. */ - BKE_tracking_stabilization_data_get(tracking, framenr, width, height, tloc, &tscale, &tangle); - BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat); + BKE_tracking_stabilization_data_get(clip, framenr, width, height, tloc, &tscale, &tangle); + BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, pixel_aspect, tloc, tscale, tangle, mat); + + /* The following code visits each nominal target grid position + * and picks interpolated data "backwards" from source. + * thus we need the inverse of the transformation to apply. */ invert_m4(mat); if (filter == TRACKING_FILTER_NEAREST) @@ -397,48 +1594,44 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf return tmpibuf; } -/* Get 4x4 transformation matrix which corresponds to - * stabilization data and used for easy coordinate - * transformation. + +/* Build a 4x4 transformation matrix based on the given 2D stabilization data. + * mat is a 4x4 matrix in homogeneous coordinates, adapted to the + * final image buffer size and compensated for pixel aspect ratio, + * ready for direct OpenGL drawing. * - * NOTE: The reason it is 4x4 matrix is because it's - * used for OpenGL drawing directly. + * TODO(sergey): The signature of this function should be changed. we actually + * don't need the dimensions of the image buffer. Instead we + * should consider to provide the pivot point of the rotation as a + * further stabilization data parameter. */ -void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, - float translation[2], float scale, float angle, - float mat[4][4]) +void BKE_tracking_stabilization_data_to_mat4(int buffer_width, + int buffer_height, + float pixel_aspect, + float translation[2], + float scale, + float angle, + float r_mat[4][4]) { - float translation_mat[4][4], rotation_mat[4][4], scale_mat[4][4], - center_mat[4][4], inv_center_mat[4][4], - aspect_mat[4][4], inv_aspect_mat[4][4]; - float scale_vector[3] = {scale, scale, scale}; - - unit_m4(translation_mat); - unit_m4(rotation_mat); - unit_m4(scale_mat); - unit_m4(center_mat); - unit_m4(aspect_mat); - - /* aspect ratio correction matrix */ - aspect_mat[0][0] = 1.0f / aspect; - invert_m4_m4(inv_aspect_mat, aspect_mat); - - /* image center as rotation center - * - * Rotation matrix is constructing in a way rotation happens around image center, - * and it's matter of calculating translation in a way, that applying translation - * after rotation would make it so rotation happens around median point of tracks - * used for translation stabilization. + /* Since we cannot receive the real pivot point coordinates (API limitation), + * we perform the rotation/scale around the center of frame. + * Then we correct by an additional shift, which was calculated in + * compensate_rotation_center() and "sneaked in" as additional offset + * in the translation parameter. This works, since translation needs to be + * applied after rotation/scale anyway. Thus effectively the image gets + * rotated around the desired pivot point */ - center_mat[3][0] = (float)width / 2.0f; - center_mat[3][1] = (float)height / 2.0f; - invert_m4_m4(inv_center_mat, center_mat); - - size_to_mat4(scale_mat, scale_vector); /* scale matrix */ - add_v2_v2(translation_mat[3], translation); /* translation matrix */ - rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */ - - /* compose transformation matrix */ - mul_m4_series(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat, - scale_mat, inv_center_mat); + /* TODO(sergey) pivot shouldn't be calculated here, rather received + * as a parameter. + */ + float pivot[2]; + pivot[0] = 0.5f * pixel_aspect * buffer_width; + pivot[1] = 0.5f * buffer_height; + /* Compose transformation matrix. */ + stabilization_data_to_mat4(pixel_aspect, + pivot, + translation, + scale, + angle, + r_mat); } diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index a73eb834299..0e2e9ac75c2 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -167,8 +167,6 @@ World *localize_world(World *wrld) if (wrld->mtex[a]) { wrldn->mtex[a] = MEM_mallocN(sizeof(MTex), "localize_world"); memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex)); - /* free world decrements */ - id_us_plus((ID *)wrldn->mtex[a]->tex); } } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 9dbc045f1b0..de55a1977bf 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -1393,7 +1393,7 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char avcodec_get_context_defaults3(&c, NULL); - strncpy(name_, str, sizeof(name_)); + BLI_strncpy(name_, str, sizeof(name_)); name = name_; while (*name == ' ') name++; diff --git a/source/blender/blenlib/BLI_system.h b/source/blender/blenlib/BLI_system.h index cb8cb6f5a0d..f51b9623803 100644 --- a/source/blender/blenlib/BLI_system.h +++ b/source/blender/blenlib/BLI_system.h @@ -21,15 +21,14 @@ #ifndef __BLI_SYSTEM_H__ #define __BLI_SYSTEM_H__ +#include <stdio.h> + /** \file BLI_system.h * \ingroup bli */ int BLI_cpu_support_sse2(void); - -#if defined(NDEBUG) || !defined(__BLI_UTILDEFINES_H__) void BLI_system_backtrace(FILE *fp); -#endif /* getpid */ #ifdef WIN32 diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index d504e503c68..746eb922c65 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -633,7 +633,7 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size); * for aborting need to define WITH_ASSERT_ABORT */ #ifndef NDEBUG -extern void BLI_system_backtrace(FILE *fp); +# include "BLI_system.h" # ifdef WITH_ASSERT_ABORT # define _BLI_DUMMY_ABORT abort # else diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c index 6000c1a680c..21ddddad32e 100644 --- a/source/blender/blenlib/intern/array_store.c +++ b/source/blender/blenlib/intern/array_store.c @@ -579,7 +579,7 @@ static void bchunk_list_calc_trim_len( /** * Append and don't manage merging small chunks. */ -static bool bchunk_list_append_only( +static void bchunk_list_append_only( BArrayMemory *bs_mem, BChunkList *chunk_list, BChunk *chunk) { @@ -588,7 +588,6 @@ static bool bchunk_list_append_only( cref->link = chunk; chunk_list->chunk_refs_len += 1; chunk->users += 1; - return chunk; } /** diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 40454a93ec8..dd30f267f78 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2892,8 +2892,8 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int int x2 = p2[0]; int y2 = p2[1]; - signed char ix; - signed char iy; + int ix; + int iy; /* if x1 == x2 or y1 == y2, then it does not matter what we set here */ int delta_x = (x2 > x1 ? ((void)(ix = 1), x2 - x1) : ((void)(ix = -1), x1 - x2)) << 1; diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 5d1bdd6d978..898075e651e 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -25,6 +25,7 @@ #include <stdio.h> #include <stdlib.h> +#include "BLI_utildefines.h" #include "BLI_system.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 479d3a15e6c..8cb9ef837b2 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -77,6 +77,13 @@ if(WITH_CODEC_FFMPEG) add_definitions(-DWITH_FFMPEG) endif() +if(WITH_ALEMBIC) + list(APPEND INC + ../alembic + ) + add_definitions(-DWITH_ALEMBIC) +endif() + blender_add_lib(bf_blenloader "${SRC}" "${INC}" "${INC_SYS}") # needed so writefile.c can use dna_type_offsets.h diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6aaeabb4096..96b5bb757ea 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -59,6 +59,7 @@ #include "DNA_actuator_types.h" #include "DNA_brush_types.h" #include "DNA_camera_types.h" +#include "DNA_cachefile_types.h" #include "DNA_cloth_types.h" #include "DNA_controller_types.h" #include "DNA_constraint_types.h" @@ -114,6 +115,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_brush.h" +#include "BKE_cachefile.h" #include "BKE_cloth.h" #include "BKE_constraint.h" #include "BKE_context.h" @@ -2691,6 +2693,38 @@ static void direct_link_animdata(FileData *fd, AnimData *adt) adt->actstrip = newdataadr(fd, adt->actstrip); } +/* ************ READ CACHEFILES *************** */ + +static void lib_link_cachefiles(FileData *fd, Main *bmain) +{ + CacheFile *cache_file; + + /* only link ID pointers */ + for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) { + if (cache_file->id.tag & LIB_TAG_NEED_LINK) { + cache_file->id.tag &= ~LIB_TAG_NEED_LINK; + } + + BLI_listbase_clear(&cache_file->object_paths); + cache_file->handle = NULL; + cache_file->handle_mutex = NULL; + + if (cache_file->adt) { + lib_link_animdata(fd, &cache_file->id, cache_file->adt); + } + } +} + +static void direct_link_cachefile(FileData *fd, CacheFile *cache_file) +{ + cache_file->handle = NULL; + cache_file->handle_mutex = NULL; + + /* relink animdata */ + cache_file->adt = newdataadr(fd, cache_file->adt); + direct_link_animdata(fd, cache_file->adt); +} + /* ************ READ MOTION PATHS *************** */ /* direct data for cache */ @@ -4743,7 +4777,7 @@ static void lib_link_object(FileData *fd, Main *main) /* Only expand so as not to loose any object materials that might be set. */ if (totcol_data && (*totcol_data > ob->totcol)) { /* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */ - BKE_material_resize_object(ob, *totcol_data, false); + BKE_material_resize_object(main, ob, *totcol_data, false); } } @@ -5277,6 +5311,9 @@ static void direct_link_object(FileData *fd, Object *ob) */ ob->recalc = 0; + /* XXX This should not be needed - but seems like it can happen in some cases, so for now play safe... */ + ob->proxy_from = NULL; + /* loading saved files with editmode enabled works, but for undo we like * to stay in object mode during undo presses so keep editmode disabled. * @@ -6675,10 +6712,13 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc * since it gets initialized later */ sima->iuser.scene = NULL; - sima->scopes.waveform_1 = NULL; - sima->scopes.waveform_2 = NULL; - sima->scopes.waveform_3 = NULL; - sima->scopes.vecscope = NULL; +#if 0 + /* Those are allocated and freed by space code, no need to handle them here. */ + MEM_SAFE_FREE(sima->scopes.waveform_1); + MEM_SAFE_FREE(sima->scopes.waveform_2); + MEM_SAFE_FREE(sima->scopes.waveform_3); + MEM_SAFE_FREE(sima->scopes.vecscope); +#endif sima->scopes.ok = 0; /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data @@ -7464,7 +7504,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) clip->tracking_context = NULL; clip->tracking.stats = NULL; - clip->tracking.stabilization.ok = 0; + /* Needed for proper versioning, will be NULL for all newer files anyway. */ clip->tracking.stabilization.rot_track = newdataadr(fd, clip->tracking.stabilization.rot_track); clip->tracking.dopesheet.ok = 0; @@ -7930,6 +7970,7 @@ static const char *dataname(short id_code) case ID_MC: return "Data from MC"; case ID_MSK: return "Data from MSK"; case ID_LS: return "Data from LS"; + case ID_CF: return "Data from CF"; } return "Data from Lib Block"; @@ -8181,6 +8222,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short case ID_PC: direct_link_paint_curve(fd, (PaintCurve *)id); break; + case ID_CF: + direct_link_cachefile(fd, (CacheFile *)id); + break; } oldnewmap_free_unused(fd->datamap); @@ -8374,6 +8418,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_mask(fd, main); lib_link_linestyle(fd, main); lib_link_gpencil(fd, main); + lib_link_cachefiles(fd, main); lib_link_mesh(fd, main); /* as last: tpage images with users at zero */ @@ -9484,6 +9529,13 @@ static void expand_camera(FileData *fd, Main *mainvar, Camera *ca) expand_animdata(fd, mainvar, ca->adt); } +static void expand_cachefile(FileData *fd, Main *mainvar, CacheFile *cache_file) +{ + if (cache_file->adt) { + expand_animdata(fd, mainvar, cache_file->adt); + } +} + static void expand_speaker(FileData *fd, Main *mainvar, Speaker *spk) { expand_doit(fd, mainvar, spk->sound); @@ -9679,6 +9731,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_GD: expand_gpencil(fd, mainvar, (bGPdata *)id); break; + case ID_CF: + expand_cachefile(fd, mainvar, (CacheFile *)id); + break; } do_it = true; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 7e811d9e203..eaa7d487862 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -63,6 +63,7 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_screen.h" +#include "BKE_tracking.h" #include "BKE_gpencil.h" #include "BLI_math.h" @@ -75,6 +76,23 @@ #include "MEM_guardedalloc.h" +/** + * Setup rotation stabilization from ancient single track spec. + * Former Version of 2D stabilization used a single tracking marker to determine the rotation + * to be compensated. Now several tracks can contribute to rotation detection and this feature + * is enabled by the MovieTrackingTrack#flag on a per track base. + */ +static void migrate_single_rot_stabilization_track_settings(MovieTrackingStabilization *stab) +{ + if (stab->rot_track) { + if (!(stab->rot_track->flag & TRACK_USE_2D_STAB_ROT)) { + stab->tot_rot_track++; + stab->rot_track->flag |= TRACK_USE_2D_STAB_ROT; + } + } + stab->rot_track = NULL; /* this field is now ignored */ +} + static void do_version_constraints_radians_degrees_270_1(ListBase *lb) { bConstraint *con; @@ -1269,7 +1287,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) if (!MAIN_VERSION_ATLEAST(main, 277, 3)) { /* ------- init of grease pencil initialization --------------- */ - if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "bGPDpalettecolor", "palcolor")) { + if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "bGPDpalettecolor", "*palcolor")) { for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { ToolSettings *ts = scene->toolsettings; /* initialize use position for sculpt brushes */ @@ -1293,7 +1311,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { ToolSettings *ts = scene->toolsettings; if (BLI_listbase_is_empty(&ts->gp_brushes)) { - gpencil_brush_init_presets(ts); + BKE_gpencil_brush_init_presets(ts); } } } @@ -1303,45 +1321,98 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) for (bGPdata *gpd = main->gpencil.first; gpd; gpd = gpd->id.next) { if (BLI_listbase_is_empty(&gpd->palettes)) { /* create palette */ - bGPDpalette *palette = gpencil_palette_addnew(gpd, "GP_Palette", true); + bGPDpalette *palette = BKE_gpencil_palette_addnew(gpd, "GP_Palette", true); for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* create color using layer name */ - bGPDpalettecolor *palcolor = gpencil_palettecolor_addnew(palette, gpl->info, true); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_addnew(palette, gpl->info, true); if (palcolor != NULL) { /* set color attributes */ copy_v4_v4(palcolor->color, gpl->color); copy_v4_v4(palcolor->fill, gpl->fill); - palcolor->flag = gpl->flag; + + if (gpl->flag & GP_LAYER_HIDE) palcolor->flag |= PC_COLOR_HIDE; + if (gpl->flag & GP_LAYER_LOCKED) palcolor->flag |= PC_COLOR_LOCKED; + if (gpl->flag & GP_LAYER_ONIONSKIN) palcolor->flag |= PC_COLOR_ONIONSKIN; + if (gpl->flag & GP_LAYER_VOLUMETRIC) palcolor->flag |= PC_COLOR_VOLUMETRIC; + if (gpl->flag & GP_LAYER_HQ_FILL) palcolor->flag |= PC_COLOR_HQ_FILL; + /* set layer opacity to 1 */ gpl->opacity = 1.0f; + /* set tint color */ ARRAY_SET_ITEMS(gpl->tintcolor, 0.0f, 0.0f, 0.0f, 0.0f); - + + /* flush relevant layer-settings to strokes */ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { /* set stroke to palette and force recalculation */ - strcpy(gps->colorname, gpl->info); + BLI_strncpy(gps->colorname, gpl->info, sizeof(gps->colorname)); gps->palcolor = NULL; gps->flag |= GP_STROKE_RECALC_COLOR; gps->thickness = gpl->thickness; + /* set alpha strength to 1 */ for (int i = 0; i < gps->totpoints; i++) { gps->points[i].strength = 1.0f; } - } } } + /* set thickness to 0 (now it is a factor to override stroke thickness) */ gpl->thickness = 0.0f; } /* set first color as active */ if (palette->colors.first) - gpencil_palettecolor_setactive(palette, palette->colors.first); + BKE_gpencil_palettecolor_setactive(palette, palette->colors.first); } } } /* ------- end of grease pencil initialization --------------- */ } + if (!MAIN_VERSION_ATLEAST(main, 278, 0)) { + if (!DNA_struct_elem_find(fd->filesdna, "MovieTrackingTrack", "float", "weight_stab")) { + MovieClip *clip; + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object; + for (tracking_object = tracking->objects.first; + tracking_object != NULL; + tracking_object = tracking_object->next) + { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); + MovieTrackingTrack *track; + for (track = tracksbase->first; + track != NULL; + track = track->next) + { + track->weight_stab = track->weight; + } + } + } + } + + if (!DNA_struct_elem_find(fd->filesdna, "MovieTrackingStabilization", "int", "tot_rot_track")) { + MovieClip *clip; + for (clip = main->movieclip.first; clip != NULL; clip = clip->id.next) { + if (clip->tracking.stabilization.rot_track) { + migrate_single_rot_stabilization_track_settings(&clip->tracking.stabilization); + } + if (clip->tracking.stabilization.scale == 0.0f) { + /* ensure init. + * Was previously used for autoscale only, + * now used always (as "target scale") */ + clip->tracking.stabilization.scale = 1.0f; + } + /* blender prefers 1-based frame counting; + * thus using frame 1 as reference typically works best */ + clip->tracking.stabilization.anchor_frame = 1; + /* by default show the track lists expanded, to improve "discoverability" */ + clip->tracking.stabilization.flag |= TRACKING_SHOW_STAB_TRACKS; + /* deprecated, not used anymore */ + clip->tracking.stabilization.ok = false; + } + } + } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 2404271bf25..8e797e38de3 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -49,7 +49,7 @@ * <bh.len> int, len data after BHead * <bh.old> void, old pointer * <bh.SDNAnr> int - * <bh.nr> int, in case of array: amount of structs + * <bh.nr> int, in case of array: number of structs * data * ... * ... @@ -107,6 +107,7 @@ #include "DNA_armature_types.h" #include "DNA_actuator_types.h" #include "DNA_brush_types.h" +#include "DNA_cachefile_types.h" #include "DNA_camera_types.h" #include "DNA_cloth_types.h" #include "DNA_constraint_types.h" @@ -3893,6 +3894,21 @@ static void write_linestyles(WriteData *wd, ListBase *idbase) } } +static void write_cachefiles(WriteData *wd, ListBase *idbase) +{ + CacheFile *cache_file; + + for (cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) { + if (cache_file->id.us > 0 || wd->current) { + writestruct(wd, ID_CF, CacheFile, 1, cache_file); + + if (cache_file->adt) { + write_animdata(wd, cache_file->adt); + } + } + } +} + /* Keep it last of write_foodata functions. */ static void write_libraries(WriteData *wd, Main *main) { @@ -4090,6 +4106,7 @@ static bool write_file_handle( write_paintcurves(wd, &mainvar->paintcurves); write_gpencils(wd, &mainvar->gpencil); write_linestyles(wd, &mainvar->linestyle); + write_cachefiles(wd, &mainvar->cachefiles); write_libraries(wd, mainvar->next); /* So changes above don't cause a 'DNA1' to be detected as changed on undo. */ diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h index 3838e8c827c..1d76077c9f1 100644 --- a/source/blender/blentranslation/BLT_translation.h +++ b/source/blender/blentranslation/BLT_translation.h @@ -120,6 +120,7 @@ bool BLT_lang_is_ime_supported(void); #define BLT_I18NCONTEXT_ID_ARMATURE "Armature" #define BLT_I18NCONTEXT_ID_BRUSH "Brush" #define BLT_I18NCONTEXT_ID_CAMERA "Camera" +#define BLT_I18NCONTEXT_ID_CACHEFILE "CacheFile" #define BLT_I18NCONTEXT_ID_CURVE "Curve" #define BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle" #define BLT_I18NCONTEXT_ID_GPENCIL "GPencil" @@ -171,6 +172,7 @@ typedef struct { BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ARMATURE, "id_armature"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_BRUSH, "id_brush"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CAMERA, "id_camera"), \ + BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CACHEFILE, "id_cachefile"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVE, "id_curve"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \ diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index b647f5a667d..1dfb9dee8eb 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -3563,7 +3563,7 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme) BLI_assert(first_bme != NULL); bv->edges[i].e = first_bme; BM_BEVEL_EDGE_TAG_ENABLE(first_bme); - if (fast_bevel_edge_order(bv)) + if (i == 0 && fast_bevel_edge_order(bv)) break; i = bevel_edge_order_extend(bm, bv, i); i++; @@ -3588,6 +3588,7 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme) e2 = (i == bv->edgecount - 1) ? &bv->edges[0] : &bv->edges[i + 1]; bme = e->e; bme2 = e2->e; + BLI_assert(bme != NULL); BM_ITER_ELEM(l, &iter, bme, BM_LOOPS_OF_EDGE) { f = l->f; if ((l->prev->e == bme2 || l->next->e == bme2) && !e->fnext && !e2->fprev) diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 52a0df5b9d1..372d341f223 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -430,7 +430,7 @@ static int *bm_edge_symmetry_map(BMesh *bm, unsigned int symmetry_axis, float li tree = BLI_kdtree_new(bm->totedge); - etable = MEM_mallocN(sizeof(BMEdge **) * bm->totedge, __func__); + etable = MEM_mallocN(sizeof(*etable) * bm->totedge, __func__); edge_symmetry_map = MEM_mallocN(sizeof(*edge_symmetry_map) * bm->totedge, __func__); BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index e205608a365..b16e2e2b0d3 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -49,6 +49,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], double dmat[4][4]; UnitConverter *converter = new UnitConverter(); converter->mat4_to_dae_double(dmat, local); + delete converter; TransformBase::decompose(local, loc, rot, NULL, scale); diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp index 933223dacac..b3f1b5a4458 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp @@ -91,7 +91,7 @@ void MovieClipNode::convertToOperations(NodeConverter &converter, const Composit if (stab->flag & TRACKING_2D_STABILIZATION) { int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(movieClip, context.getFramenumber()); - BKE_tracking_stabilization_data_get(&movieClip->tracking, clip_framenr, ibuf->x, ibuf->y, loc, &scale, &angle); + BKE_tracking_stabilization_data_get(movieClip, clip_framenr, ibuf->x, ibuf->y, loc, &scale, &angle); } } diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp index 76afedf4b2a..ca3c5f7b069 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp @@ -20,6 +20,8 @@ * Monique Dewanchand */ +#include <stdlib.h> + #include "COM_DoubleEdgeMaskOperation.h" #include "BLI_math.h" #include "DNA_node_types.h" @@ -1151,12 +1153,13 @@ void DoubleEdgeMaskOperation::doDoubleEdgeMask(float *imask, float *omask, float if (true) { // if both input sockets have some data coming in... - t = (this->getWidth() * this->getHeight()) - 1; // determine size of the frame + rw = this->getWidth(); // width of a row of pixels + t = (rw * this->getHeight()) - 1; // determine size of the frame + memset(res, 0, sizeof(float) * (t + 1)); // clear output buffer (not all pixels will be written later) lres = (unsigned int *)res; // unsigned int pointer to output buffer (for bit level ops) limask = (unsigned int *)imask; // unsigned int pointer to input mask (for bit level ops) lomask = (unsigned int *)omask; // unsigned int pointer to output mask (for bit level ops) - rw = this->getWidth(); // width of a row of pixels /* diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp index 5ddf15f7684..41f7da7c49f 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp @@ -47,7 +47,7 @@ void MovieClipAttributeOperation::executePixelSampled(float output[4], angle = 0.0f; if (this->m_clip) { int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_clip, this->m_framenumber); - BKE_tracking_stabilization_data_get(&this->m_clip->tracking, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle); + BKE_tracking_stabilization_data_get(this->m_clip, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle); } switch (this->m_attribute) { case MCA_SCALE: diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index 49b648c7dae..0945da439ef 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -42,6 +42,8 @@ struct Depsgraph; struct Main; struct Scene; +struct Group; +struct EffectorWeights; #ifdef __cplusplus extern "C" { @@ -79,6 +81,7 @@ void DEG_scene_graph_free(struct Scene *scene); */ struct DepsNodeHandle; +struct CacheFile; struct Object; typedef enum eDepsSceneComponentType { @@ -100,15 +103,23 @@ typedef enum eDepsObjectComponentType { DEG_OB_COMP_EVAL_PARTICLES, /* Particle Systems Component */ DEG_OB_COMP_SHADING, /* Material Shading Component */ + DEG_OB_COMP_CACHE, /* Cache Component */ } eDepsObjectComponentType; void DEG_add_scene_relation(struct DepsNodeHandle *node, struct Scene *scene, eDepsSceneComponentType component, const char *description); void DEG_add_object_relation(struct DepsNodeHandle *node, struct Object *ob, eDepsObjectComponentType component, const char *description); void DEG_add_bone_relation(struct DepsNodeHandle *handle, struct Object *ob, const char *bone_name, eDepsObjectComponentType component, const char *description); +void DEG_add_object_cache_relation(struct DepsNodeHandle *handle, struct CacheFile *cache_file, eDepsObjectComponentType component, const char *description); /* TODO(sergey): Remove once all geometry update is granular. */ void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag); +/* Utility functions for physics modifiers */ +typedef bool (*DEG_CollobjFilterFunction)(struct Object *obj, struct ModifierData *md); + +void DEG_add_collision_relations(struct DepsNodeHandle *handle, struct Scene *scene, Object *ob, struct Group *group, int layer, unsigned int modifier_type, DEG_CollobjFilterFunction fn, bool dupli, const char *name); +void DEG_add_forcefield_relations(struct DepsNodeHandle *handle, struct Scene *scene, Object *ob, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name); + /* ************************************************ */ #ifdef __cplusplus diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index a397b48e19c..1812384440f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -46,6 +46,7 @@ extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" +#include "DNA_cachefile_types.h" #include "DNA_camera_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" @@ -339,6 +340,14 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene) if (scene->gpd) { build_gpencil(scene->gpd); } + + /* cache files */ + for (CacheFile *cachefile = static_cast<CacheFile *>(bmain->cachefiles.first); + cachefile; + cachefile = static_cast<CacheFile *>(cachefile->id.next)) + { + build_cachefile(cachefile); + } } void DepsgraphNodeBuilder::build_group(Scene *scene, @@ -1259,4 +1268,18 @@ void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd) build_animdata(gpd_id); } +void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file) +{ + ID *cache_file_id = &cache_file->id; + + add_component_node(cache_file_id, DEPSNODE_TYPE_CACHE); + + add_operation_node(cache_file_id, DEPSNODE_TYPE_CACHE, + DEPSOP_TYPE_EXEC, NULL, + DEG_OPCODE_PLACEHOLDER, "Cache File Update"); + + add_id_node(cache_file_id); + build_animdata(cache_file_id); +} + } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 6ee0b8406a1..f378f076804 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -33,6 +33,7 @@ #include "intern/depsgraph_types.h" struct Base; +struct CacheFile; struct bGPdata; struct ListBase; struct GHash; @@ -144,6 +145,7 @@ struct DepsgraphNodeBuilder { void build_world(World *world); void build_compositor(Scene *scene); void build_gpencil(bGPdata *gpd); + void build_cachefile(CacheFile *cache_file); protected: Main *m_bmain; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 42b8260c05a..2148a3501d8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -47,6 +47,7 @@ extern "C" { #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" +#include "DNA_cachefile_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_effect_types.h" @@ -64,6 +65,7 @@ extern "C" { #include "DNA_scene_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" +#include "DNA_object_force.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -71,6 +73,7 @@ extern "C" { #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_effect.h" +#include "BKE_collision.h" #include "BKE_fcurve.h" #include "BKE_group.h" #include "BKE_key.h" @@ -242,6 +245,69 @@ void DepsgraphRelationBuilder::add_operation_relation( } } +void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name) +{ + unsigned int numcollobj; + Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, eModifierType_Collision, dupli); + + for (unsigned int i = 0; i < numcollobj; i++) + { + Object *ob1 = collobjs[i]; + + ComponentKey trf_key(&ob1->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, name); + + ComponentKey coll_key(&ob1->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(coll_key, key, DEPSREL_TYPE_STANDARD, name); + } + + if (collobjs) + MEM_freeN(collobjs); +} + +void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name) +{ + ListBase *effectors = pdInitEffectors(scene, ob, psys, eff, false); + + if (effectors) { + for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) { + if (eff->ob != ob) { + ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name); + } + + if (eff->psys) { + if (eff->ob != ob) { + ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES); + add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name); + + /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */ + ComponentKey mod_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(mod_key, key, DEPSREL_TYPE_STANDARD, name); + } + else if (eff->psys != psys) { + OperationKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, eff->psys->name); + add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name); + } + } + + if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) { + ComponentKey trf_key(&eff->pd->f_source->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain"); + + ComponentKey eff_key(&eff->pd->f_source->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain"); + } + + if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { + add_collision_relations(key, scene, ob, NULL, eff->ob->lay, true, "Force Absorption"); + } + } + } + + pdEndEffectors(&effectors); +} + /* **** Functions to build relations between entities **** */ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) @@ -599,6 +665,18 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode TimeSourceKey time_src_key; add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]"); } + else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) { + /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint dependency chain. */ + TimeSourceKey time_src_key; + add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]"); + + bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data; + + if (data->cache_file) { + ComponentKey cache_key(&data->cache_file->id, DEPSNODE_TYPE_CACHE); + add_relation(cache_key, constraint_op_key, DEPSREL_TYPE_CACHE, cti->name); + } + } else if (cti->get_constraint_targets) { ListBase targets = {NULL, NULL}; cti->get_constraint_targets(con, &targets); @@ -1124,20 +1202,13 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob) } #endif - /* effectors */ - ListBase *effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false); - - if (effectors) { - for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) { - if (eff->psys) { - // XXX: DAG_RL_DATA_DATA | DAG_RL_OB_DATA - ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY); // xxx: particles instead? - add_relation(eff_key, psys_key, DEPSREL_TYPE_STANDARD, "Particle Field"); - } - } + /* collisions */ + if (part->type != PART_HAIR) { + add_collision_relations(psys_key, scene, ob, part->collision_group, ob->lay, true, "Particle Collision"); } - pdEndEffectors(&effectors); + /* effectors */ + add_forcefield_relations(psys_key, scene, ob, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field"); /* boids */ if (part->boids) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index ce6d2c961fd..46e65d464a4 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -63,6 +63,8 @@ struct bConstraint; struct Scene; struct Tex; struct World; +struct EffectorWeights; +struct ParticleSystem; struct PropertyRNA; @@ -244,6 +246,9 @@ struct DepsgraphRelationBuilder void build_compositor(Scene *scene); void build_gpencil(ID *owner, bGPdata *gpd); + void add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name); + void add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name); + template <typename KeyType> OperationDepsNode *find_operation_node(const KeyType &key); diff --git a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc index 9088e3bf403..70cd5f11a47 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc @@ -90,6 +90,7 @@ static const int deg_debug_node_type_color_map[][2] = { {DEPSNODE_TYPE_GEOMETRY, 8}, {DEPSNODE_TYPE_SEQUENCER, 9}, {DEPSNODE_TYPE_SHADING, 10}, + {DEPSNODE_TYPE_CACHE, 11}, {-1, 0} }; #endif @@ -401,6 +402,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, case DEPSNODE_TYPE_EVAL_POSE: case DEPSNODE_TYPE_BONE: case DEPSNODE_TYPE_SHADING: + case DEPSNODE_TYPE_CACHE: case DEPSNODE_TYPE_EVAL_PARTICLES: { ComponentDepsNode *comp_node = (ComponentDepsNode *)node; diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index b1271c39851..7a3b19e82c6 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -33,13 +33,18 @@ #include "MEM_guardedalloc.h" extern "C" { +#include "DNA_cachefile_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_object_force.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BKE_main.h" +#include "BKE_collision.h" +#include "BKE_effect.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -89,6 +94,7 @@ static DEG::eDepsNode_Type deg_build_object_component_type( case DEG_OB_COMP_BONE: return DEG::DEPSNODE_TYPE_BONE; case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEPSNODE_TYPE_EVAL_PARTICLES; case DEG_OB_COMP_SHADING: return DEG::DEPSNODE_TYPE_SHADING; + case DEG_OB_COMP_CACHE: return DEG::DEPSNODE_TYPE_CACHE; } return DEG::DEPSNODE_TYPE_UNDEFINED; } @@ -126,6 +132,20 @@ void DEG_add_object_relation(DepsNodeHandle *handle, description); } +void DEG_add_object_cache_relation(DepsNodeHandle *handle, + CacheFile *cache_file, + eDepsObjectComponentType component, + const char *description) +{ + DEG::eDepsNode_Type type = deg_build_object_component_type(component); + DEG::ComponentKey comp_key(&cache_file->id, type); + DEG::DepsNodeHandle *deg_handle = get_handle(handle); + deg_handle->builder->add_node_handle_relation(comp_key, + deg_handle, + DEG::DEPSREL_TYPE_CACHE, + description); +} + void DEG_add_bone_relation(DepsNodeHandle *handle, Object *ob, const char *bone_name, @@ -288,3 +308,52 @@ void DEG_scene_graph_free(Scene *scene) scene->depsgraph = NULL; } } + +void DEG_add_collision_relations(DepsNodeHandle *handle, Scene *scene, Object *ob, Group *group, int layer, unsigned int modifier_type, DEG_CollobjFilterFunction fn, bool dupli, const char *name) +{ + unsigned int numcollobj; + Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli); + + for (unsigned int i = 0; i < numcollobj; i++) { + Object *ob1 = collobjs[i]; + + if (!fn || fn(ob1, modifiers_findByType(ob1, (ModifierType)modifier_type))) { + DEG_add_object_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name); + DEG_add_object_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name); + } + } + + if (collobjs) + MEM_freeN(collobjs); +} + +void DEG_add_forcefield_relations(DepsNodeHandle *handle, Scene *scene, Object *ob, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name) +{ + ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false); + + if (effectors) { + for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) { + if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) { + DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_TRANSFORM, name); + + if (eff->psys) { + DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_EVAL_PARTICLES, name); + + /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */ + DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_GEOMETRY, name); + } + + if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) { + DEG_add_object_relation(handle, eff->pd->f_source, DEG_OB_COMP_TRANSFORM, "Smoke Force Domain"); + DEG_add_object_relation(handle, eff->pd->f_source, DEG_OB_COMP_GEOMETRY, "Smoke Force Domain"); + } + + if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { + DEG_add_collision_relations(handle, scene, ob, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption"); + } + } + } + } + + pdEndEffectors(&effectors); +} diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index cac4eaae215..7f2f6a65f5e 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -33,6 +33,7 @@ #include "MEM_guardedalloc.h" extern "C" { +#include "BKE_idcode.h" #include "BKE_main.h" #include "DEG_depsgraph_query.h" @@ -42,7 +43,7 @@ extern "C" { bool DEG_id_type_tagged(Main *bmain, short idtype) { - return bmain->id_tag_update[((unsigned char *)&idtype)[0]] != 0; + return bmain->id_tag_update[BKE_idcode_to_index(idtype)] != 0; } short DEG_get_eval_flags_for_id(Depsgraph *graph, ID *id) diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index ea5afaab3f7..b7b62bd59f9 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -44,6 +44,7 @@ extern "C" { #include "BLI_task.h" +#include "BKE_idcode.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_node.h" @@ -259,10 +260,8 @@ void DEG_id_type_tag(Main *bmain, short idtype) DEG_id_type_tag(bmain, ID_WO); DEG_id_type_tag(bmain, ID_SCE); } - /* We tag based on first ID type character to avoid - * looping over all ID's in case there are no tags. - */ - bmain->id_tag_update[((unsigned char *)&idtype)[0]] = 1; + + bmain->id_tag_update[BKE_idcode_to_index(idtype)] = 1; } /* Recursively push updates out to all nodes dependent on this, @@ -373,10 +372,7 @@ void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time) ListBase *lb = lbarray[a]; ID *id = (ID *)lb->first; - /* We tag based on first ID type character to avoid - * looping over all ID's in case there are no tags. - */ - if (id && bmain->id_tag_update[(unsigned char)id->name[0]]) { + if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) { updated = true; break; } @@ -401,10 +397,7 @@ void DEG_ids_clear_recalc(Main *bmain) ListBase *lb = lbarray[a]; ID *id = (ID *)lb->first; - /* We tag based on first ID type character to avoid - * looping over all ID's in case there are no tags. - */ - if (id && bmain->id_tag_update[(unsigned char)id->name[0]]) { + if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) { for (; id; id = (ID *)id->next) { id->tag &= ~(LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA); diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h index 7516ccbfdc2..effd34a0eb9 100644 --- a/source/blender/depsgraph/intern/depsgraph_types.h +++ b/source/blender/depsgraph/intern/depsgraph_types.h @@ -133,6 +133,8 @@ typedef enum eDepsNode_Type { DEPSNODE_TYPE_EVAL_PARTICLES = 23, /* Material Shading Component */ DEPSNODE_TYPE_SHADING = 24, + /* Cache Component */ + DEPSNODE_TYPE_CACHE = 25, } eDepsNode_Type; /* Identifiers for common operations (as an enum). */ @@ -330,6 +332,9 @@ typedef enum eDepsRelation_Type { /* relationship is used to trigger editor/screen updates */ DEPSREL_TYPE_UPDATE_UI, + + /* cache dependency */ + DEPSREL_TYPE_CACHE, } eDepsRelation_Type; } // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index c3fd202d832..f8cca5393e2 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -304,7 +304,7 @@ static void schedule_node(TaskPool *pool, Depsgraph *graph, unsigned int layers, deg_task_run_func, node, false, - TASK_PRIORITY_LOW, + TASK_PRIORITY_HIGH, thread_id); } } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index f9e1504b3ce..7c6c25bef0d 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -33,7 +33,7 @@ #include "intern/eval/deg_eval_flush.h" // TODO(sergey): Use some sort of wrapper. -#include <queue> +#include <deque> extern "C" { #include "DNA_object_types.h" @@ -71,7 +71,7 @@ void lib_id_recalc_data_tag(Main *bmain, ID *id) } /* namespace */ -typedef std::queue<OperationDepsNode *> FlushQueue; +typedef std::deque<OperationDepsNode *> FlushQueue; static void flush_init_func(void *data_v, int i) { @@ -122,20 +122,60 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) */ GSET_FOREACH_BEGIN(OperationDepsNode *, node, graph->entry_tags) { - queue.push(node); + queue.push_back(node); node->scheduled = true; } GSET_FOREACH_END(); + int num_flushed_objects = 0; while (!queue.empty()) { OperationDepsNode *node = queue.front(); - queue.pop(); + queue.pop_front(); for (;;) { node->flag |= DEPSOP_FLAG_NEEDS_UPDATE; ComponentDepsNode *comp_node = node->owner; IDDepsNode *id_node = comp_node->owner; + + ID *id = id_node->id; + if(id_node->done == 0) { + deg_editors_id_update(bmain, id); + lib_id_recalc_tag(bmain, id); + /* TODO(sergey): For until we've got proper data nodes in the graph. */ + lib_id_recalc_data_tag(bmain, id); + } + + if(comp_node->done == 0) { + Object *object = NULL; + if (GS(id->name) == ID_OB) { + object = (Object *)id; + if(id_node->done == 0) { + ++num_flushed_objects; + } + } + foreach (OperationDepsNode *op, comp_node->operations) { + op->flag |= DEPSOP_FLAG_NEEDS_UPDATE; + } + if (object != NULL) { + /* This code is used to preserve those areas which does + * direct object update, + * + * Plus it ensures visibility changes and relations and + * layers visibility update has proper flags to work with. + */ + if (comp_node->type == DEPSNODE_TYPE_ANIMATION) { + object->recalc |= OB_RECALC_TIME; + } + else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) { + object->recalc |= OB_RECALC_OB; + } + else { + object->recalc |= OB_RECALC_DATA; + } + } + } + id_node->done = 1; comp_node->done = 1; @@ -154,7 +194,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) foreach (DepsRelation *rel, node->outlinks) { OperationDepsNode *to_node = (OperationDepsNode *)rel->to; if (to_node->scheduled == false) { - queue.push(to_node); + queue.push_front(to_node); to_node->scheduled = true; } } @@ -162,52 +202,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) } } } - - GHASH_FOREACH_BEGIN(DEG::IDDepsNode *, id_node, graph->id_hash) - { - if (id_node->done == 1) { - ID *id = id_node->id; - Object *object = NULL; - - if (GS(id->name) == ID_OB) { - object = (Object *)id; - } - - deg_editors_id_update(bmain, id_node->id); - - lib_id_recalc_tag(bmain, id_node->id); - /* TODO(sergey): For until we've got proper data nodes in the graph. */ - lib_id_recalc_data_tag(bmain, id_node->id); - - GHASH_FOREACH_BEGIN(const ComponentDepsNode *, comp_node, id_node->components) - { - if (comp_node->done) { - foreach (OperationDepsNode *op, comp_node->operations) { - op->flag |= DEPSOP_FLAG_NEEDS_UPDATE; - } - if (object != NULL) { - /* This code is used to preserve those areas which does - * direct object update, - * - * Plus it ensures visibility changes and relations and - * layers visibility update has proper flags to work with. - */ - if (comp_node->type == DEPSNODE_TYPE_ANIMATION) { - object->recalc |= OB_RECALC_TIME; - } - else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) { - object->recalc |= OB_RECALC_OB; - } - else { - object->recalc |= OB_RECALC_DATA; - } - } - } - } - GHASH_FOREACH_END(); - } - } - GHASH_FOREACH_END(); + DEG_DEBUG_PRINTF("Update flushed to %d objects\n", num_flushed_objects); } static void graph_clear_func(void *data_v, int i) diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc index 5832c458896..01f33b6368b 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc @@ -366,6 +366,11 @@ static DepsNodeFactoryImpl<ParticlesComponentDepsNode> DNTI_EVAL_PARTICLES; DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEPSNODE_TYPE_SHADING, "Shading Component"); static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING; +/* Cache Component Defines ============================ */ + +DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEPSNODE_TYPE_CACHE, "Cache Component"); +static DepsNodeFactoryImpl<CacheComponentDepsNode> DNTI_CACHE; + /* Node Types Register =================================== */ @@ -383,6 +388,8 @@ void deg_register_component_depsnodes() deg_register_node_typeinfo(&DNTI_EVAL_PARTICLES); deg_register_node_typeinfo(&DNTI_SHADING); + + deg_register_node_typeinfo(&DNTI_CACHE); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h index acccb1cdcd4..7dec8eaaa90 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.h +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h @@ -209,6 +209,10 @@ struct ShadingComponentDepsNode : public ComponentDepsNode { DEG_DEPSNODE_DECLARE; }; +struct CacheComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + void deg_register_component_depsnodes(); diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 084006ce277..1559512d713 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -19,6 +19,10 @@ # ***** END GPL LICENSE BLOCK ***** if(WITH_BLENDER) + if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) + endif() + add_subdirectory(animation) add_subdirectory(armature) add_subdirectory(curve) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 752544f65e1..d727ea0a957 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -40,6 +40,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" +#include "DNA_cachefile_types.h" #include "DNA_camera_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" @@ -1578,6 +1579,88 @@ static bAnimChannelType ACF_DSTEX = /* Camera Expander ------------------------------------------- */ // TODO: just get this from RNA? +static int acf_dscachefile_icon(bAnimListElem *ale) +{ + UNUSED_VARS(ale); + return ICON_FILE; +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_dscachefile_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg) +{ + /* clear extra return data first */ + *neg = false; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return CACHEFILE_DS_EXPAND; + + case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ + return ADT_NLA_EVAL_OFF; + + case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ + *neg = true; + return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; + + default: /* unsupported */ + return 0; + } + + UNUSED_VARS(ac); +} + +/* get pointer to the setting */ +static void *acf_dscachefile_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type) +{ + CacheFile *cache_file = (CacheFile *)ale->data; + + /* clear extra return data first */ + *type = 0; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return GET_ACF_FLAG_PTR(cache_file->flag, type); + + case ACHANNEL_SETTING_SELECT: /* selected */ + case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ + case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ + if (cache_file->adt) { + return GET_ACF_FLAG_PTR(cache_file->adt->flag, type); + } + + return NULL; + + default: /* unsupported */ + return NULL; + } +} + +/* CacheFile expander type define. */ +static bAnimChannelType ACF_DSCACHEFILE = +{ + "Cache File Expander", /* type name */ + ACHANNEL_ROLE_EXPANDER, /* role */ + + acf_generic_dataexpand_color, /* backdrop color */ + acf_generic_dataexpand_backdrop, /* backdrop */ + acf_generic_indention_1, /* indent level */ + acf_generic_basic_offset, /* offset */ + + acf_generic_idblock_name, /* name */ + acf_generic_idfill_name_prop, /* name prop */ + acf_dscachefile_icon, /* icon */ + + acf_generic_dataexpand_setting_valid, /* has setting */ + acf_dscachefile_setting_flag, /* flag for setting */ + acf_dscachefile_setting_ptr /* pointer for setting */ +}; + +/* Camera Expander ------------------------------------------- */ + +// TODO: just get this from RNA? static int acf_dscam_icon(bAnimListElem *UNUSED(ale)) { return ICON_CAMERA_DATA; @@ -3388,6 +3471,7 @@ static void ANIM_init_channel_typeinfo_data(void) animchannelTypeInfo[type++] = &ACF_DSMAT; /* Material Channel */ animchannelTypeInfo[type++] = &ACF_DSLAM; /* Lamp Channel */ animchannelTypeInfo[type++] = &ACF_DSCAM; /* Camera Channel */ + animchannelTypeInfo[type++] = &ACF_DSCACHEFILE; /* CacheFile Channel */ animchannelTypeInfo[type++] = &ACF_DSCUR; /* Curve Channel */ animchannelTypeInfo[type++] = &ACF_DSSKEY; /* ShapeKey Channel */ animchannelTypeInfo[type++] = &ACF_DSWOR; /* World Channel */ @@ -3817,7 +3901,12 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void /* send notifiers before doing anything else... */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + + /* verify that we have a channel to operate on. */ + if (!ale_setting) { + return; + } + if (ale_setting->type == ANIMTYPE_GPLAYER) WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); @@ -3825,17 +3914,13 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void if (ANIM_animdata_get_context(C, &ac) == 0) return; - /* verify that we have a channel to operate on, and that it has all we need */ - if (ale_setting) { - /* check if the setting is on... */ - on = ANIM_channel_setting_get(&ac, ale_setting, setting); - - /* on == -1 means setting not found... */ - if (on == -1) - return; - } - else + /* check if the setting is on... */ + on = ANIM_channel_setting_get(&ac, ale_setting, setting); + + /* on == -1 means setting not found... */ + if (on == -1) { return; + } /* get all channels that can possibly be chosen - but ignore hierarchy */ filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS; diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index af9b0a176f5..cb65a9aecad 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -120,6 +120,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ case ANIMTYPE_DSLAM: case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: case ANIMTYPE_DSCUR: case ANIMTYPE_DSSKEY: case ANIMTYPE_DSWOR: @@ -175,6 +176,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ case ANIMTYPE_DSLAM: case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: case ANIMTYPE_DSCUR: case ANIMTYPE_DSSKEY: case ANIMTYPE_DSWOR: @@ -275,6 +277,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ case ANIMTYPE_DSLAM: case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: case ANIMTYPE_DSCUR: case ANIMTYPE_DSSKEY: case ANIMTYPE_DSWOR: @@ -370,6 +373,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ case ANIMTYPE_DSLAM: case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: case ANIMTYPE_DSCUR: case ANIMTYPE_DSSKEY: case ANIMTYPE_DSWOR: @@ -1686,7 +1690,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) bGPDlayer *gpl = (bGPDlayer *)ale->data; /* try to delete the layer's data and the layer itself */ - free_gpencil_frames(gpl); + BKE_gpencil_free_frames(gpl); BLI_freelinkN(&gpd->layers, gpl); break; } @@ -2716,6 +2720,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ case ANIMTYPE_DSLAM: case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: case ANIMTYPE_DSCUR: case ANIMTYPE_DSSKEY: case ANIMTYPE_DSWOR: diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 88d96c531e0..5cd305f69f5 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -53,6 +53,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" +#include "DNA_cachefile_types.h" #include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_linestyle_types.h" @@ -199,6 +200,16 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->mode = saction->mode; return true; + + case SACTCONT_CACHEFILE: /* Cache File */ /* XXX review how this mode is handled... */ + /* update scene-pointer (no need to check for pinning yet, as not implemented) */ + saction->ads.source = (ID *)ac->scene; + + ac->datatype = ANIMCONT_CHANNEL; + ac->data = &saction->ads; + + ac->mode = saction->mode; + return true; case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */ { @@ -660,6 +671,19 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne ale->adt = BKE_animdata_from_id(data); break; } + case ANIMTYPE_DSCACHEFILE: + { + CacheFile *cache_file = (CacheFile *)data; + AnimData *adt = cache_file->adt; + + ale->flag = FILTER_CACHEFILE_OBJD(cache_file); + + ale->key_data = (adt) ? adt->action : NULL; + ale->datatype = ALE_ACT; + + ale->adt = BKE_animdata_from_id(data); + break; + } case ANIMTYPE_DSCUR: { Curve *cu = (Curve *)data; @@ -1751,6 +1775,42 @@ static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data, return items; } +/* Helper for Cache File data integrated with main DopeSheet */ +static size_t animdata_filter_ds_cachefile(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, CacheFile *cache_file, int filter_mode) +{ + ListBase tmp_data = {NULL, NULL}; + size_t tmp_items = 0; + size_t items = 0; + + /* add relevant animation channels for Cache File */ + BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_CACHEFILE_OBJD(cache_file)) + { + /* add animation channels */ + tmp_items += animfilter_block_data(ac, &tmp_data, ads, &cache_file->id, filter_mode); + } + END_ANIMFILTER_SUBCHANNELS; + + /* did we find anything? */ + if (tmp_items) { + /* include data-expand widget first */ + if (filter_mode & ANIMFILTER_LIST_CHANNELS) { + /* check if filtering by active status */ + // XXX: active check here needs checking + if (ANIMCHANNEL_ACTIVEOK(cache_file)) { + ANIMCHANNEL_NEW_CHANNEL(cache_file, ANIMTYPE_DSCACHEFILE, cache_file); + } + } + + /* now add the list of collected channels */ + BLI_movelisttolist(anim_data, &tmp_data); + BLI_assert(BLI_listbase_is_empty(&tmp_data)); + items += tmp_items; + } + + /* return the number of items added to the list */ + return items; +} + /* Helper for Mask Editing - mask layers */ static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode) { @@ -2839,6 +2899,12 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b filter_mode |= ANIMFILTER_SELEDIT; } + /* Cache files level animations (frame duration and such). */ + CacheFile *cache_file = G.main->cachefiles.first; + for (; cache_file; cache_file = cache_file->id.next) { + items += animdata_filter_ds_cachefile(ac, anim_data, ads, cache_file, filter_mode); + } + /* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */ items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode); @@ -2950,7 +3016,11 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD case ANIMTYPE_OBJECT: items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode); break; - + + case ANIMTYPE_DSCACHEFILE: + items += animdata_filter_ds_cachefile(ac, anim_data, ads, channel->data, filter_mode); + break; + case ANIMTYPE_ANIMDATA: items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode); break; diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 6e776953356..5f675e690b9 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -44,6 +44,7 @@ #include "BLI_utildefines.h" #include "DNA_anim_types.h" +#include "DNA_cachefile_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_gpencil_types.h" @@ -965,6 +966,37 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl ANIM_animdata_freelist(&anim_data); } +void cachefile_to_keylist(bDopeSheet *ads, CacheFile *cache_file, DLRBT_Tree *keys, DLRBT_Tree *blocks) +{ + if (cache_file == NULL) { + return; + } + + /* create a dummy wrapper data to work with */ + bAnimListElem dummychan = {NULL}; + dummychan.type = ANIMTYPE_DSCACHEFILE; + dummychan.data = cache_file; + dummychan.id = &cache_file->id; + dummychan.adt = cache_file->adt; + + bAnimContext ac = {NULL}; + ac.ads = ads; + ac.data = &dummychan; + ac.datatype = ANIMCONT_CHANNEL; + + /* get F-Curves to take keyframes from */ + ListBase anim_data = { NULL, NULL }; + int filter = ANIMFILTER_DATA_VISIBLE; // curves only + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop through each F-Curve, grabbing the keyframes */ + for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) { + fcurve_to_keylist(ale->adt, ale->data, keys, blocks); + } + + ANIM_animdata_freelist(&anim_data); +} + void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks) { BezTriple *bezt; diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index bd09616243b..4ef76f5ee25 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -1359,7 +1359,7 @@ static void gp_draw_data_layers( continue; /* get frame to draw */ - gpf = gpencil_layer_getframe(gpl, cfra, 0); + gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0); if (gpf == NULL) continue; @@ -1533,7 +1533,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i if (gpd_source) { ToolSettings *ts = scene->toolsettings; - bGPDbrush *brush = gpencil_brush_getactive(ts); + bGPDbrush *brush = BKE_gpencil_brush_getactive(ts); if (brush != NULL) { gp_draw_data(brush, ts->gp_sculpt.alpha, gpd_source, offsx, offsy, winx, winy, cfra, dflag); @@ -1546,7 +1546,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i * if gpd_source == gpd, we don't have any object/track data and we can skip */ if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) { ToolSettings *ts = scene->toolsettings; - bGPDbrush *brush = gpencil_brush_getactive(ts); + bGPDbrush *brush = BKE_gpencil_brush_getactive(ts); if (brush != NULL) { gp_draw_data(brush, ts->gp_sculpt.alpha, gpd, offsx, offsy, winx, winy, cfra, dflag); diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 738496a67c6..bd4856f1b93 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -253,7 +253,7 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl) gpfn = gpf->next; if (gpf->flag & GP_FRAME_SELECT) - changed |= gpencil_layer_delframe(gpl, gpf); + changed |= BKE_gpencil_layer_delframe(gpl, gpf); } return changed; @@ -277,7 +277,7 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl) bGPDframe *gpfd; /* duplicate frame, and deselect self */ - gpfd = gpencil_frame_duplicate(gpf); + gpfd = BKE_gpencil_frame_duplicate(gpf); gpf->flag &= ~GP_FRAME_SELECT; BLI_insertlinkafter(&gpl->frames, gpf, gpfd); @@ -323,7 +323,7 @@ static int gp_anim_copy_cfra = 0; /* This function frees any MEM_calloc'ed copy/paste buffer data */ void ED_gpencil_anim_copybuf_free(void) { - free_gpencil_layers(&gp_anim_copybuf); + BKE_gpencil_free_layers(&gp_anim_copybuf); BLI_listbase_clear(&gp_anim_copybuf); gp_anim_copy_firstframe = 999999999; @@ -364,7 +364,7 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) /* if frame is selected, make duplicate it and its strokes */ if (gpf->flag & GP_FRAME_SELECT) { /* make a copy of this frame */ - bGPDframe *new_frame = gpencil_frame_duplicate(gpf); + bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf); BLI_addtail(&copied_frames, new_frame); /* extend extents for keyframes encountered */ @@ -475,7 +475,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) gpfs->framenum += offset; /* get frame to copy data into (if no frame returned, then just ignore) */ - gpf = gpencil_layer_getframe(gpld, gpfs->framenum, 1); + gpf = BKE_gpencil_layer_getframe(gpld, gpfs->framenum, 1); if (gpf) { bGPDstroke *gps, *gpsn; @@ -498,7 +498,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) /* if no strokes (i.e. new frame) added, free gpf */ if (BLI_listbase_is_empty(&gpf->strokes)) - gpencil_layer_delframe(gpld, gpf); + BKE_gpencil_layer_delframe(gpld, gpf); } /* unapply offset from buffer-frame */ diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index 1bb3b7e1ae7..fcb2ce02bde 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -841,7 +841,7 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) Scene *scene = gso->scene; bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); - bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, true); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true); bGPDstroke *gps; float delta[3]; @@ -1185,7 +1185,7 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso) */ // XXX: should this be allowed when framelock is enabled? if (gpf->framenum != cfra) { - gpencil_frame_addcopy(gpl, cfra); + BKE_gpencil_frame_addcopy(gpl, cfra); } } } diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 95ea13c399a..c502ed1aa83 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1123,7 +1123,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG struct Main *bmain = CTX_data_main(C); View3D *v3d = CTX_wm_view3d(C); /* may be NULL */ Scene *scene = CTX_data_scene(C); - bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0); bGPDstroke *gps, *prev_gps = NULL; Object *ob; Curve *cu; @@ -1235,7 +1235,7 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe int i; bool valid = true; - if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first)) + if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first)) return false; do { @@ -1292,8 +1292,8 @@ static int gp_convert_poll(bContext *C) * and if we are not in edit mode! */ return ((sa && sa->spacetype == SPACE_VIEW3D) && - (gpl = gpencil_layer_getactive(gpd)) && - (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) && + (gpl = BKE_gpencil_layer_getactive(gpd)) && + (gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0)) && (gpf->strokes.first) && (scene->obedit == NULL)); } @@ -1302,7 +1302,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); Scene *scene = CTX_data_scene(C); const int mode = RNA_enum_get(op->ptr, "type"); const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights"); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index e915446e461..9560ab188a4 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -75,9 +75,6 @@ #include "gpencil_intern.h" -/* maximum sizes of gp-session buffer */ -#define GP_STROKE_BUFFER_MAX 5000 - /* ************************************************ */ /* Datablock Operators */ @@ -97,7 +94,7 @@ static int gp_data_add_exec(bContext *C, wmOperator *op) bGPdata *gpd = (*gpd_ptr); id_us_min(&gpd->id); - *gpd_ptr = gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); } /* notifiers */ @@ -184,10 +181,10 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); /* add new layer now */ - gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true); + BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -214,7 +211,7 @@ void GPENCIL_OT_layer_add(wmOperatorType *ot) static int gp_layer_remove_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); /* sanity checks */ if (ELEM(NULL, gpd, gpl)) @@ -230,12 +227,12 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op) * - if this is the only layer, this naturally becomes NULL */ if (gpl->prev) - gpencil_layer_setactive(gpd, gpl->prev); + BKE_gpencil_layer_setactive(gpd, gpl->prev); else - gpencil_layer_setactive(gpd, gpl->next); + BKE_gpencil_layer_setactive(gpd, gpl->next); /* delete the layer now... */ - gpencil_layer_delete(gpd, gpl); + BKE_gpencil_layer_delete(gpd, gpl); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -267,7 +264,7 @@ enum { static int gp_layer_move_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); int direction = RNA_enum_get(op->ptr, "type"); @@ -321,7 +318,7 @@ void GPENCIL_OT_layer_move(wmOperatorType *ot) static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); bGPDlayer *new_layer; /* sanity checks */ @@ -329,12 +326,12 @@ static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; /* make copy of layer, and add it immediately after the existing layer */ - new_layer = gpencil_layer_duplicate(gpl); + new_layer = BKE_gpencil_layer_duplicate(gpl); BLI_insertlinkafter(&gpd->layers, gpl, new_layer); /* ensure new layer has a unique name, and is now the active layer */ BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info)); - gpencil_layer_setactive(gpd, new_layer); + BKE_gpencil_layer_setactive(gpd, new_layer); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -362,7 +359,7 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) static int gp_hide_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *layer = gpencil_layer_getactive(gpd); + bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd); bool unselected = RNA_boolean_get(op->ptr, "unselected"); /* sanity checks */ @@ -530,7 +527,7 @@ void GPENCIL_OT_unlock_all(wmOperatorType *ot) static int gp_isolate_layer_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *layer = gpencil_layer_getactive(gpd); + bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd); bGPDlayer *gpl; int flags = GP_LAYER_LOCKED; bool isolate = false; @@ -606,7 +603,7 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot) static int gp_merge_layer_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl_current = gpencil_layer_getactive(gpd); + bGPDlayer *gpl_current = BKE_gpencil_layer_getactive(gpd); bGPDlayer *gpl_next = gpl_current->next; if (ELEM(NULL, gpd, gpl_current, gpl_next)) { @@ -626,13 +623,13 @@ static int gp_merge_layer_exec(bContext *C, wmOperator *op) bGPDframe *frame = BLI_ghash_lookup(gh_frames_cur, SET_INT_IN_POINTER(gpf->framenum)); if (!frame) { /* nothing found, create new */ - frame = gpencil_frame_addnew(gpl_current, gpf->framenum); + frame = BKE_gpencil_frame_addnew(gpl_current, gpf->framenum); } /* add to tail all strokes */ BLI_movelisttolist(&frame->strokes, &gpf->strokes); } /* Now delete next layer */ - gpencil_layer_delete(gpd, gpl_next); + BKE_gpencil_layer_delete(gpd, gpl_next); BLI_ghash_free(gh_frames_cur, NULL, NULL); /* notifiers */ @@ -681,7 +678,7 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op) /* Get layer or create new one */ if (layer_num == -1) { /* Create layer */ - gpl = gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); + gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); } else { /* Try to get layer */ @@ -694,7 +691,7 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op) } /* Set active layer */ - gpencil_layer_setactive(gpd, gpl); + BKE_gpencil_layer_setactive(gpd, gpl); /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -736,7 +733,7 @@ enum { static int gp_stroke_arrange_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); bGPDstroke *gps; /* sanity checks */ @@ -747,7 +744,7 @@ static int gp_stroke_arrange_exec(bContext *C, wmOperator *op) bGPDframe *gpf = gpl->actframe; /* temp listbase to store selected strokes */ ListBase selected = {NULL}; - const int direction = RNA_enum_get(op->ptr, "type"); + const int direction = RNA_enum_get(op->ptr, "direction"); /* verify if any selected stroke is in the extreme of the stack and select to move */ for (gps = gpf->strokes.first; gps; gps = gps->next) { @@ -861,8 +858,8 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - palette = gpencil_palette_getactive(gpd); - color = gpencil_palettecolor_getactive(palette); + palette = BKE_gpencil_palette_getactive(gpd); + color = BKE_gpencil_palettecolor_getactive(palette); if (ELEM(NULL, palette, color)) { return OPERATOR_CANCELLED; } @@ -882,9 +879,9 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *UNUSED(op)) continue; /* asign new color (only if different) */ - if (STREQ(gps->colorname, color->info) == false) { - strcpy(gps->colorname, color->info); - gps->flag |= GP_STROKE_RECALC_COLOR; + if ((STREQ(gps->colorname, color->info) == false) || (gps->palcolor != color)) { + BLI_strncpy(gps->colorname, color->info, sizeof(gps->colorname)); + gps->palcolor = color; } } } @@ -919,7 +916,7 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op)) if (ELEM(NULL, gpd)) return OPERATOR_CANCELLED; - palette = gpencil_palette_getactive(gpd); + palette = BKE_gpencil_palette_getactive(gpd); if (ELEM(NULL, palette)) return OPERATOR_CANCELLED; @@ -965,430 +962,6 @@ void GPENCIL_OT_stroke_lock_color(wmOperatorType *ot) ot->poll = gp_active_layer_poll; } -/* ******************* Apply layer thickness change to Strokes ************************** */ - -static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op)) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - - /* sanity checks */ - if (ELEM(NULL, gpd, gpl, gpl->frames.first)) - return OPERATOR_CANCELLED; - - /* loop all strokes */ - for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - /* Apply thickness */ - gps->thickness = gps->thickness + gpl->thickness; - } - } - /* clear value */ - gpl->thickness = 0.0f; - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_stroke_apply_thickness(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Apply Stroke Thickness"; - ot->idname = "GPENCIL_OT_stroke_apply_thickness"; - ot->description = "Apply the thickness change of the layer to its strokes"; - - /* api callbacks */ - ot->exec = gp_stroke_apply_thickness_exec; - ot->poll = gp_active_layer_poll; -} - -/* ******************* Close Strokes ************************** */ - -enum { - GP_STROKE_CYCLIC_CLOSE = 1, - GP_STROKE_CYCLIC_OPEN = 2, - GP_STROKE_CYCLIC_TOGGLE = 3 -}; - -static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - const int type = RNA_enum_get(op->ptr, "type"); - - /* sanity checks */ - if (ELEM(NULL, gpd)) - return OPERATOR_CANCELLED; - - /* loop all selected strokes */ - CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) - { - for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) { - bGPDpalettecolor *palcolor = gps->palcolor; - - /* skip strokes that are not selected or invalid for current view */ - if (((gps->flag & GP_STROKE_SELECT) == 0) || ED_gpencil_stroke_can_use(C, gps) == false) - continue; - /* skip hidden or locked colors */ - if (!palcolor || (palcolor->flag & PC_COLOR_HIDE) || (palcolor->flag & PC_COLOR_LOCKED)) - continue; - - switch (type) { - case GP_STROKE_CYCLIC_CLOSE: - /* Close all (enable) */ - gps->flag |= GP_STROKE_CYCLIC; - break; - case GP_STROKE_CYCLIC_OPEN: - /* Open all (disable) */ - gps->flag &= ~GP_STROKE_CYCLIC; - break; - case GP_STROKE_CYCLIC_TOGGLE: - /* Just toggle flag... */ - gps->flag ^= GP_STROKE_CYCLIC; - break; - default: - BLI_assert(0); - break; - } - } - } - CTX_DATA_END; - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -/** - * Similar to #CURVE_OT_cyclic_toggle or #MASK_OT_cyclic_toggle, but with - * option to force opened/closed strokes instead of just toggle behavior. - */ -void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) -{ - static EnumPropertyItem cyclic_type[] = { - {GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close all", ""}, - {GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open all", ""}, - {GP_STROKE_CYCLIC_TOGGLE, "TOGGLE", 0, "Toggle", ""}, - {0, NULL, 0, NULL, NULL} - }; - - /* identifiers */ - ot->name = "Set Cyclical State"; - ot->idname = "GPENCIL_OT_stroke_cyclical_set"; - ot->description = "Close or open the selected stroke adding an edge from last to first point"; - - /* api callbacks */ - ot->exec = gp_stroke_cyclical_set_exec; - ot->poll = gp_active_layer_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - ot->prop = RNA_def_enum(ot->srna, "type", cyclic_type, GP_STROKE_CYCLIC_TOGGLE, "Type", ""); -} - -/* ******************* Stroke join ************************** */ - -/* Helper: flip stroke */ -static void gpencil_flip_stroke(bGPDstroke *gps) -{ - bGPDspoint pt, *point, *point2; - int end = gps->totpoints - 1; - - for (int i = 0; i < gps->totpoints / 2; i++) { - /* save first point */ - point = &gps->points[i]; - pt.x = point->x; - pt.y = point->y; - pt.z = point->z; - pt.flag = point->flag; - pt.pressure = point->pressure; - pt.strength = point->strength; - pt.time = point->time; - - /* replace first point with last point */ - point2 = &gps->points[end]; - point->x = point2->x; - point->y = point2->y; - point->z = point2->z; - point->flag = point2->flag; - point->pressure = point2->pressure; - point->strength = point2->strength; - point->time = point2->time; - - /* replace last point with first saved before */ - point = &gps->points[end]; - point->x = pt.x; - point->y = pt.y; - point->z = pt.z; - point->flag = pt.flag; - point->pressure = pt.pressure; - point->strength = pt.strength; - point->time = pt.time; - - end--; - } -} - -/* Helper: copy point between strokes */ -static void gpencil_stroke_copy_point(bGPDstroke *gps, bGPDspoint *point, float delta[3], - float pressure, float strength, float deltatime) -{ - bGPDspoint *newpoint; - - gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); - gps->totpoints++; - - newpoint = &gps->points[gps->totpoints - 1]; - newpoint->x = point->x * delta[0]; - newpoint->y = point->y * delta[1]; - newpoint->z = point->z * delta[2]; - newpoint->flag = point->flag; - newpoint->pressure = pressure; - newpoint->strength = strength; - newpoint->time = point->time + deltatime; -} - -/* Helper: join two strokes using the shortest distance (reorder stroke if necessary ) */ -static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, bGPDstroke *gps_b) -{ - bGPDspoint point, *pt; - int i; - float delta[3] = {1.0f, 1.0f, 1.0f}; - float deltatime = 0.0f; - - /* sanity checks */ - if (ELEM(NULL, gps_a, gps_b)) - return; - - if ((gps_a->totpoints == 0) || (gps_b->totpoints == 0)) - return; - - /* define start and end points of each stroke */ - float sa[3], sb[3], ea[3], eb[3]; - pt = &gps_a->points[0]; - copy_v3_v3(sa, &pt->x); - - pt = &gps_a->points[gps_a->totpoints - 1]; - copy_v3_v3(ea, &pt->x); - - pt = &gps_b->points[0]; - copy_v3_v3(sb, &pt->x); - - pt = &gps_b->points[gps_b->totpoints - 1]; - copy_v3_v3(eb, &pt->x); - /* review if need flip stroke B */ - float ea_sb = len_squared_v3v3(ea, sb); - float ea_eb = len_squared_v3v3(ea, eb); - /* flip if distance to end point is shorter */ - if (ea_eb < ea_sb) { - gpencil_flip_stroke(gps_b); - } - - /* 1st: add one tail point to start invisible area */ - point = gps_a->points[gps_a->totpoints - 1]; - deltatime = point.time; - gpencil_stroke_copy_point(gps_a, &point, delta, 0.0f, 0.0f, 0.0f); - - /* 2nd: add one head point to finish invisible area */ - point = gps_b->points[0]; - gpencil_stroke_copy_point(gps_a, &point, delta, 0.0f, 0.0f, deltatime); - - /* 3rd: add all points */ - for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) { - /* check if still room in buffer */ - if (gps_a->totpoints <= GP_STROKE_BUFFER_MAX - 2) { - gpencil_stroke_copy_point(gps_a, pt, delta, pt->pressure, pt->strength, deltatime); - } - } -} - -enum { - GP_STROKE_JOIN = -1, - GP_STROKE_JOINCOPY = 1 -}; - -static int gp_stroke_join_exec(bContext *C, wmOperator *op) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *activegpl = gpencil_layer_getactive(gpd); - bGPDstroke *gps, *gpsn; - bGPDpalette *palette = gpencil_palette_getactive(gpd); - bGPDpalettecolor *palcolor = gpencil_palettecolor_getactive(palette); - - bGPDframe *gpf_a = NULL; - bGPDstroke *stroke_a = NULL; - bGPDstroke *stroke_b = NULL; - bGPDstroke *new_stroke = NULL; - - int type = RNA_enum_get(op->ptr, "type"); - - /* sanity checks */ - if (ELEM(NULL, gpd)) - return OPERATOR_CANCELLED; - - if (activegpl->flag & GP_LAYER_LOCKED) - return OPERATOR_CANCELLED; - - BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY)); - - - /* read all selected strokes */ - bool first = false; - CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) - { - bGPDframe *gpf = gpl->actframe; - for (gps = gpf->strokes.first; gps; gps = gpsn) { - gpsn = gps->next; - if (gps->flag & GP_STROKE_SELECT) { - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) { - continue; - } - /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(gpl, gps) == false) { - continue; - } - /* to join strokes, cyclic must be disabled */ - gps->flag &= ~GP_STROKE_CYCLIC; - /* saves first frame and stroke */ - if (!first) { - first = true; - gpf_a = gpf; - stroke_a = gps; - } - else { - stroke_b = gps; - /* create a new stroke if was not created before (only created if something to join) */ - if (new_stroke == NULL) { - new_stroke = MEM_dupallocN(stroke_a); - new_stroke->points = MEM_dupallocN(stroke_a->points); - new_stroke->triangles = NULL; - new_stroke->tot_triangles = 0; - new_stroke->flag |= GP_STROKE_RECALC_CACHES; - /* if new, set current color */ - if (type == GP_STROKE_JOINCOPY) { - new_stroke->palcolor = palcolor; - strcpy(new_stroke->colorname, palcolor->info); - new_stroke->flag |= GP_STROKE_RECALC_COLOR; - } - } - /* join new_stroke and stroke B. New stroke will contain all the previous data */ - gpencil_stroke_join_strokes(new_stroke, stroke_b); - - /* if join only, delete old strokes */ - if (type == GP_STROKE_JOIN) { - if (stroke_a) { - BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke); - BLI_remlink(&gpf->strokes, stroke_a); - free_gpencil_stroke(stroke_a); - stroke_a = NULL; - } - if (stroke_b) { - BLI_remlink(&gpf->strokes, stroke_b); - free_gpencil_stroke(stroke_b); - stroke_b = NULL; - } - } - } - } - } - } - CTX_DATA_END; - /* add new stroke if was not added before */ - if (type == GP_STROKE_JOINCOPY) { - if (new_stroke) { - /* Add a new frame if needed */ - if (activegpl->actframe == NULL) - activegpl->actframe = gpencil_frame_addnew(activegpl, gpf_a->framenum); - - BLI_addtail(&activegpl->actframe->strokes, new_stroke); - } - } - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_stroke_join(wmOperatorType *ot) -{ - static EnumPropertyItem join_type[] = { - {GP_STROKE_JOIN, "JOIN", 0, "Join", ""}, - {GP_STROKE_JOINCOPY, "JOINCOPY", 0, "Join and Copy", ""}, - {0, NULL, 0, NULL, NULL} - }; - - /* identifiers */ - ot->name = "Join Strokes"; - ot->idname = "GPENCIL_OT_stroke_join"; - ot->description = "Join selected strokes (optionally as new stroke)"; - - /* api callbacks */ - ot->exec = gp_stroke_join_exec; - ot->poll = gp_active_layer_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - ot->prop = RNA_def_enum(ot->srna, "type", join_type, GP_STROKE_JOIN, "Type", ""); -} - -/* ******************* Stroke flip ************************** */ - -static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op)) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - - /* sanity checks */ - if (ELEM(NULL, gpd)) - return OPERATOR_CANCELLED; - - /* read all selected strokes */ - CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) - { - bGPDframe *gpf = gpl->actframe; - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - if (gps->flag & GP_STROKE_SELECT) { - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) { - continue; - } - /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(gpl, gps) == false) { - continue; - } - /* flip stroke */ - gpencil_flip_stroke(gps); - } - } - } - CTX_DATA_END; - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_stroke_flip(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Flip Stroke"; - ot->idname = "GPENCIL_OT_stroke_flip"; - ot->description = "Change drawing direction of selected strokes"; - - /* api callbacks */ - ot->exec = gp_stroke_flip_exec; - ot->poll = gp_active_layer_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - /* ************************************************ */ /* Drawing Brushes Operators */ @@ -1405,7 +978,7 @@ static int gp_brush_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } /* add new brush now */ - gpencil_brush_addnew(ts, DATA_("GP_Brush"), true); + BKE_gpencil_brush_addnew(ts, DATA_("GP_Brush"), true); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1432,14 +1005,14 @@ void GPENCIL_OT_brush_add(wmOperatorType *ot) static int gp_brush_remove_exec(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); - bGPDbrush *brush = gpencil_brush_getactive(ts); + bGPDbrush *brush = BKE_gpencil_brush_getactive(ts); /* sanity checks */ if (ELEM(NULL, ts, brush)) return OPERATOR_CANCELLED; - if (BLI_listbase_count(&ts->gp_brushes) < 2) { - BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a brush. Unable to delete brush"); + if (BLI_listbase_count_ex(&ts->gp_brushes, 2) < 2) { + BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a brush, unable to delete the last one"); return OPERATOR_CANCELLED; } @@ -1449,12 +1022,12 @@ static int gp_brush_remove_exec(bContext *C, wmOperator *op) * - if this is the only brush, this naturally becomes NULL */ if (brush->prev) - gpencil_brush_setactive(ts, brush->prev); + BKE_gpencil_brush_setactive(ts, brush->prev); else - gpencil_brush_setactive(ts, brush->next); + BKE_gpencil_brush_setactive(ts, brush->next); /* delete the brush now... */ - gpencil_brush_delete(ts, brush); + BKE_gpencil_brush_delete(ts, brush); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1465,7 +1038,7 @@ static int gp_brush_remove_exec(bContext *C, wmOperator *op) void GPENCIL_OT_brush_remove(wmOperatorType *ot) { /* identifiers */ - ot->name = "Remove brush"; + ot->name = "Remove Brush"; ot->idname = "GPENCIL_OT_brush_remove"; ot->description = "Remove active Grease Pencil drawing brush"; @@ -1501,7 +1074,7 @@ static int gp_brush_change_exec(bContext *C, wmOperator *op) /* Get brush or create new one */ if (brush_num == -1) { /* Create brush */ - brush = gpencil_brush_addnew(ts, DATA_("GP_Brush"), true); + brush = BKE_gpencil_brush_addnew(ts, DATA_("GP_Brush"), true); } else { /* Try to get brush */ @@ -1514,7 +1087,7 @@ static int gp_brush_change_exec(bContext *C, wmOperator *op) } /* Set active brush */ - gpencil_brush_setactive(ts, brush); + BKE_gpencil_brush_setactive(ts, brush); /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1552,7 +1125,7 @@ enum { static int gp_brush_move_exec(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); - bGPDbrush *brush = gpencil_brush_getactive(ts); + bGPDbrush *brush = BKE_gpencil_brush_getactive(ts); int direction = RNA_enum_get(op->ptr, "type"); @@ -1610,7 +1183,7 @@ void GPENCIL_OT_brush_move(wmOperatorType *ot) static int gp_brush_presets_create_exec(bContext *C, wmOperator *UNUSED(op)) { ToolSettings *ts = CTX_data_tool_settings(C); - gpencil_brush_init_presets(ts); + BKE_gpencil_brush_init_presets(ts); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1645,7 +1218,7 @@ static int gp_brush_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - bGPDbrush *brush = gpencil_brush_getactive(ts); + bGPDbrush *brush = BKE_gpencil_brush_getactive(ts); bGPDbrush *newbrush; /* sanity checks */ @@ -1653,7 +1226,7 @@ static int gp_brush_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* create a brush and duplicate data */ - newbrush = gpencil_brush_addnew(ts, brush->info, true); + newbrush = BKE_gpencil_brush_addnew(ts, brush->info, true); newbrush->thickness = brush->thickness; newbrush->draw_smoothfac = brush->draw_smoothfac; newbrush->draw_smoothlvl = brush->draw_smoothlvl; @@ -1677,7 +1250,7 @@ static int gp_brush_copy_exec(bContext *C, wmOperator *op) newbrush->cur_strength = curvemapping_copy(brush->cur_strength); newbrush->cur_jitter = curvemapping_copy(brush->cur_jitter); - gpencil_brush_setactive(ts, newbrush); + BKE_gpencil_brush_setactive(ts, newbrush); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1718,7 +1291,7 @@ static int gp_brush_select_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - gpencil_brush_setactive(ts, brush); + BKE_gpencil_brush_setactive(ts, brush); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1760,10 +1333,10 @@ static int gp_palette_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); /* add new palette now */ - gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true); + BKE_gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1790,14 +1363,14 @@ void GPENCIL_OT_palette_add(wmOperatorType *ot) static int gp_palette_remove_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); /* sanity checks */ if (ELEM(NULL, gpd, palette)) return OPERATOR_CANCELLED; - if (BLI_listbase_count(&gpd->palettes) < 2) { - BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a palette. Unable to delete palette"); + if (BLI_listbase_count_ex(&gpd->palettes, 2) < 2) { + BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a palette, unable to delete the last one"); return OPERATOR_CANCELLED; } @@ -1807,12 +1380,12 @@ static int gp_palette_remove_exec(bContext *C, wmOperator *op) * - if this is the only palette, this naturally becomes NULL */ if (palette->prev) - gpencil_palette_setactive(gpd, palette->prev); + BKE_gpencil_palette_setactive(gpd, palette->prev); else - gpencil_palette_setactive(gpd, palette->next); + BKE_gpencil_palette_setactive(gpd, palette->next); /* delete the palette now... */ - gpencil_palette_delete(gpd, palette); + BKE_gpencil_palette_delete(gpd, palette); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1859,7 +1432,7 @@ static int gp_palette_change_exec(bContext *C, wmOperator *op) /* Get palette or create new one */ if (palette_num == -1) { /* Create palette */ - palette = gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true); + palette = BKE_gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true); } else { /* Try to get palette */ @@ -1872,7 +1445,7 @@ static int gp_palette_change_exec(bContext *C, wmOperator *op) } /* Set active palette */ - gpencil_palette_setactive(gpd, palette); + BKE_gpencil_palette_setactive(gpd, palette); /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -1911,7 +1484,7 @@ static int gp_palette_lock_layer_exec(bContext *C, wmOperator *UNUSED(op)) if (ELEM(NULL, gpd)) return OPERATOR_CANCELLED; - palette = gpencil_palette_getactive(gpd); + palette = BKE_gpencil_palette_getactive(gpd); if (ELEM(NULL, palette)) return OPERATOR_CANCELLED; @@ -1972,15 +1545,15 @@ static int gp_palettecolor_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); /* verify palette */ - bGPDpalette *palette = gpencil_palette_getactive(*gpd_ptr); + bGPDpalette *palette = BKE_gpencil_palette_getactive(*gpd_ptr); if (palette == NULL) - palette = gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true); + palette = BKE_gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true); /* add new palette color now */ - gpencil_palettecolor_addnew(palette, DATA_("Color"), true); + BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -2007,8 +1580,8 @@ void GPENCIL_OT_palettecolor_add(wmOperatorType *ot) static int gp_palettecolor_remove_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); - bGPDpalettecolor *color = gpencil_palettecolor_getactive(palette); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + bGPDpalettecolor *color = BKE_gpencil_palettecolor_getactive(palette); /* sanity checks */ if (ELEM(NULL, gpd, palette, color)) @@ -2019,15 +1592,15 @@ static int gp_palettecolor_remove_exec(bContext *C, wmOperator *UNUSED(op)) * - if this is the only color, this naturally becomes NULL */ if (color->prev) - gpencil_palettecolor_setactive(palette, color->prev); + BKE_gpencil_palettecolor_setactive(palette, color->prev); else - gpencil_palettecolor_setactive(palette, color->next); + BKE_gpencil_palettecolor_setactive(palette, color->next); /* delete the strokes */ - gpencil_palettecolor_delete_strokes(gpd, color->info); + BKE_gpencil_palettecolor_delete_strokes(gpd, color->info); /* delete the palette color now... */ - gpencil_palettecolor_delete(palette, color); + BKE_gpencil_palettecolor_delete(palette, color); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -2054,8 +1627,8 @@ void GPENCIL_OT_palettecolor_remove(wmOperatorType *ot) static int gp_isolate_palettecolor_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); - bGPDpalettecolor *active_color = gpencil_palettecolor_getactive(palette); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + bGPDpalettecolor *active_color = BKE_gpencil_palettecolor_getactive(palette); bGPDpalettecolor *palcolor; int flags = PC_COLOR_LOCKED; @@ -2131,8 +1704,8 @@ void GPENCIL_OT_palettecolor_isolate(wmOperatorType *ot) static int gp_palettecolor_hide_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); - bGPDpalettecolor *palcolor = gpencil_palettecolor_getactive(palette); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); bool unselected = RNA_boolean_get(op->ptr, "unselected"); @@ -2190,7 +1763,7 @@ static int gp_palettecolor_reveal_poll(bContext *C) static int gp_palettecolor_reveal_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); bGPDpalettecolor *palcolor; /* sanity checks */ @@ -2228,7 +1801,7 @@ void GPENCIL_OT_palettecolor_reveal(wmOperatorType *ot) static int gp_palettecolor_lock_all_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); bGPDpalettecolor *palcolor; /* sanity checks */ @@ -2266,7 +1839,7 @@ void GPENCIL_OT_palettecolor_lock_all(wmOperatorType *ot) static int gp_palettecolor_unlock_all_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); bGPDpalettecolor *palcolor; /* sanity checks */ @@ -2309,8 +1882,8 @@ enum { static int gp_palettecolor_move_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); - bGPDpalettecolor *palcolor = gpencil_palettecolor_getactive(palette); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); int direction = RNA_enum_get(op->ptr, "direction"); @@ -2367,8 +1940,8 @@ void GPENCIL_OT_palettecolor_move(wmOperatorType *ot) static int gp_palettecolor_select_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); - bGPDpalettecolor *palcolor = gpencil_palettecolor_getactive(palette); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); /* sanity checks */ if (ELEM(NULL, gpd, palette, palcolor)) @@ -2426,8 +1999,8 @@ void GPENCIL_OT_palettecolor_select(wmOperatorType *ot) static int gp_palettecolor_copy_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); - bGPDpalettecolor *palcolor = gpencil_palettecolor_getactive(palette); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); bGPDpalettecolor *newcolor; /* sanity checks */ @@ -2435,7 +2008,7 @@ static int gp_palettecolor_copy_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; /* create a new color and duplicate data */ - newcolor = gpencil_palettecolor_addnew(palette, palcolor->info, true); + newcolor = BKE_gpencil_palettecolor_addnew(palette, palcolor->info, true); copy_v4_v4(newcolor->color, palcolor->color); copy_v4_v4(newcolor->fill, palcolor->fill); newcolor->flag = palcolor->flag; diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 621ebea6603..9f700e8716c 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -72,6 +72,7 @@ #include "ED_gpencil.h" #include "ED_object.h" +#include "ED_screen.h" #include "ED_view3d.h" #include "gpencil_intern.h" @@ -207,7 +208,7 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co /* make a stupid copy first of the entire stroke (to get the flags too) */ gpsd = MEM_dupallocN(gps); - strcpy(gpsd->tmp_layerinfo, layername); /* saves original layer name */ + BLI_strncpy(gpsd->tmp_layerinfo, layername, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */ /* initialize triangle memory - will be calculated on next redraw */ gpsd->triangles = NULL; @@ -266,7 +267,7 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op) /* make direct copies of the stroke and its points */ gpsd = MEM_dupallocN(gps); - strcpy(gpsd->tmp_layerinfo, gpl->info); + BLI_strncpy(gpsd->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo)); gpsd->points = MEM_dupallocN(gps->points); /* triangle information - will be calculated on next redraw */ @@ -386,7 +387,7 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) /* make direct copies of the stroke and its points */ gpsd = MEM_dupallocN(gps); - strcpy(gpsd->tmp_layerinfo, gpl->info); /* saves original layer name */ + BLI_strncpy(gpsd->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */ gpsd->points = MEM_dupallocN(gps->points); /* triangles cache - will be recalculated on next redraw */ @@ -431,16 +432,18 @@ void GPENCIL_OT_copy(wmOperatorType *ot) static int gp_strokes_paste_poll(bContext *C) { - /* 1) Must have GP layer to paste to... + /* 1) Must have GP datablock to paste to + * - We don't need to have an active layer though, as that can easily get added + * - If the active layer is locked, we can't paste there, but that should prompt a warning instead * 2) Copy buffer must at least have something (though it may be the wrong sort...) */ - return (CTX_data_active_gpencil_layer(C) != NULL) && (!BLI_listbase_is_empty(&gp_strokes_copypastebuf)); + return (ED_gpencil_data_get_active(C) != NULL) && (!BLI_listbase_is_empty(&gp_strokes_copypastebuf)); } -enum { +typedef enum eGP_PasteMode { GP_COPY_ONLY = -1, GP_COPY_MERGE = 1 -}; +} eGP_PasteMode; static int gp_strokes_paste_exec(bContext *C, wmOperator *op) { @@ -448,9 +451,9 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); /* only use active for copy merge */ bGPDframe *gpf; - - int type = RNA_enum_get(op->ptr, "type"); - + + eGP_PasteMode type = RNA_enum_get(op->ptr, "type"); + /* check for various error conditions */ if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); @@ -462,7 +465,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) } else if (gpl == NULL) { /* no active layer - let's just create one */ - gpl = gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); + gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); } else if ((gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_MERGE)) { BKE_report(op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked"); @@ -507,39 +510,37 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - /* Ensure we have a frame to draw into - * NOTE: Since this is an op which creates strokes, - * we are obliged to add a new frame if one - * doesn't exist already - */ - - bGPDstroke *gps; - /* Copy each stroke into the layer */ - for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { - if (ED_gpencil_stroke_can_use(C, gps)) { - /* need to verify if layer exist nad frame */ - if (type != GP_COPY_MERGE) { - gpl = BLI_findstring(&gpd->layers, gps->tmp_layerinfo, offsetof(bGPDlayer, info)); - if (gpl == NULL) { - /* no layer - use active (only if layer deleted before paste) */ - gpl = CTX_data_active_gpencil_layer(C); - } - } - gpf = gpencil_layer_getframe(gpl, CFRA, true); - if (gpf) { - bGPDstroke *new_stroke = MEM_dupallocN(gps); - new_stroke->tmp_layerinfo[0] = '\0'; - - new_stroke->points = MEM_dupallocN(gps->points); - - new_stroke->flag |= GP_STROKE_RECALC_CACHES; - new_stroke->triangles = NULL; - - new_stroke->next = new_stroke->prev = NULL; - BLI_addtail(&gpf->strokes, new_stroke); + for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { + if (ED_gpencil_stroke_can_use(C, gps)) { + /* Need to verify if layer exists */ + if (type != GP_COPY_MERGE) { + gpl = BLI_findstring(&gpd->layers, gps->tmp_layerinfo, offsetof(bGPDlayer, info)); + if (gpl == NULL) { + /* no layer - use active (only if layer deleted before paste) */ + gpl = CTX_data_active_gpencil_layer(C); } } + + /* Ensure we have a frame to draw into + * NOTE: Since this is an op which creates strokes, + * we are obliged to add a new frame if one + * doesn't exist already + */ + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true); + if (gpf) { + bGPDstroke *new_stroke = MEM_dupallocN(gps); + new_stroke->tmp_layerinfo[0] = '\0'; + + new_stroke->points = MEM_dupallocN(gps->points); + + new_stroke->flag |= GP_STROKE_RECALC_CACHES; + new_stroke->triangles = NULL; + + new_stroke->next = new_stroke->prev = NULL; + BLI_addtail(&gpf->strokes, new_stroke); + } } + } /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -554,7 +555,7 @@ void GPENCIL_OT_paste(wmOperatorType *ot) {GP_COPY_MERGE, "MERGE", 0, "Merge", ""}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Paste Strokes"; ot->idname = "GPENCIL_OT_paste"; @@ -566,7 +567,8 @@ void GPENCIL_OT_paste(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + + /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", copy_type, 0, "Type", ""); } @@ -597,7 +599,7 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) /* Get layer or create new one */ if (layer_num == -1) { /* Create layer */ - target_layer = gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); + target_layer = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); } else { /* Try to get layer */ @@ -642,7 +644,7 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) /* Paste them all in one go */ if (strokes.first) { Scene *scene = CTX_data_scene(C); - bGPDframe *gpf = gpencil_layer_getframe(target_layer, CFRA, true); + bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, CFRA, true); BLI_movelisttolist(&gpf->strokes, &strokes); BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL)); @@ -679,7 +681,7 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot) static int gp_actframe_delete_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); /* only if there's an active layer with an active frame */ return (gpl && gpl->actframe); @@ -690,8 +692,8 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0); /* if there's no existing Grease-Pencil data there, add some */ if (gpd == NULL) { @@ -704,7 +706,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op) } /* delete it... */ - gpencil_layer_delframe(gpl, gpf); + BKE_gpencil_layer_delframe(gpl, gpf); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -746,13 +748,13 @@ static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { /* try to get the "active" frame - but only if it actually occurs on this frame */ - bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0); if (gpf == NULL) continue; /* delete it... */ - gpencil_layer_delframe(gpl, gpf); + BKE_gpencil_layer_delframe(gpl, gpf); /* we successfully modified something */ success = true; @@ -1188,40 +1190,35 @@ static int gp_snap_poll(bContext *C) static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) { + bGPdata *gpd = ED_gpencil_data_get_active(C); RegionView3D *rv3d = CTX_wm_region_data(C); const float gridf = rv3d->gridview; - bGPdata *gpd = ED_gpencil_data_get_active(C); - float diff_mat[4][4]; - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { - + bGPDframe *gpf = gpl->actframe; + float diff_mat[4][4]; + /* calculate difference matrix if parent object */ if (gpl->parent != NULL) { ED_gpencil_parent_location(gpl, diff_mat); } - - bGPDframe *gpf = gpl->actframe; - bGPDstroke *gps; - for (gps = gpf->strokes.first; gps; gps = gps->next) { + + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + bGPDspoint *pt; + int i; + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(gpl, gps) == false) { + if (ED_gpencil_stroke_color_use(gpl, gps) == false) continue; - } - - bGPDspoint *pt; - int i; - - // TOOD: if entire stroke is selected, offset entire stroke by same amount? - + + // TODO: if entire stroke is selected, offset entire stroke by same amount? for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - - /* only if point is selected.. */ + /* only if point is selected */ if (pt->flag & GP_SPOINT_SELECT) { if (gpl->parent == NULL) { pt->x = gridf * floorf(0.5f + pt->x / gridf); @@ -1232,19 +1229,17 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) /* apply parent transformations */ float fpt[3]; mul_v3_m4v3(fpt, diff_mat, &pt->x); - + fpt[0] = gridf * floorf(0.5f + fpt[0] / gridf); fpt[1] = gridf * floorf(0.5f + fpt[1] / gridf); fpt[2] = gridf * floorf(0.5f + fpt[2] / gridf); - + /* return data */ copy_v3_v3(&pt->x, fpt); gp_apply_parent_point(gpl, pt); } - } } - } } } @@ -1272,49 +1267,46 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot) static int gp_snap_to_cursor(bContext *C, wmOperator *op) { + bGPdata *gpd = ED_gpencil_data_get_active(C); + Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - + const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); const float *cursor_global = ED_view3d_cursor3d_get(scene, v3d); - - bGPdata *gpd = ED_gpencil_data_get_active(C); - float diff_mat[4][4]; - + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { - + bGPDframe *gpf = gpl->actframe; + float diff_mat[4][4]; + /* calculate difference matrix if parent object */ if (gpl->parent != NULL) { ED_gpencil_parent_location(gpl, diff_mat); } - - bGPDframe *gpf = gpl->actframe; - bGPDstroke *gps; - for (gps = gpf->strokes.first; gps; gps = gps->next) { + + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + bGPDspoint *pt; + int i; + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(gpl, gps) == false) { + if (ED_gpencil_stroke_color_use(gpl, gps) == false) continue; - } - - bGPDspoint *pt; - int i; - /* only continue if this stroke is selected (editable doesn't guarantee this)... */ if ((gps->flag & GP_STROKE_SELECT) == 0) continue; - + if (use_offset) { float offset[3]; - + /* compute offset from first point of stroke to cursor */ /* TODO: Allow using midpoint instead? */ sub_v3_v3v3(offset, cursor_global, &gps->points->x); - + /* apply offset to all points in the stroke */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { add_v3_v3(&pt->x, offset); @@ -1331,9 +1323,8 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op) } } } - - } + } } @@ -1364,6 +1355,8 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot) static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) { + bGPdata *gpd = ED_gpencil_data_get_active(C); + Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); @@ -1375,36 +1368,31 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) INIT_MINMAX(min, max); /* calculate midpoints from selected points */ - bGPdata *gpd = ED_gpencil_data_get_active(C); - float diff_mat[4][4]; - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { - + bGPDframe *gpf = gpl->actframe; + float diff_mat[4][4]; + /* calculate difference matrix if parent object */ if (gpl->parent != NULL) { ED_gpencil_parent_location(gpl, diff_mat); } - - bGPDframe *gpf = gpl->actframe; - bGPDstroke *gps; - for (gps = gpf->strokes.first; gps; gps = gps->next) { + + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + bGPDspoint *pt; + int i; + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(gpl, gps) == false) { + if (ED_gpencil_stroke_color_use(gpl, gps) == false) continue; - } - - bGPDspoint *pt; - int i; - /* only continue if this stroke is selected (editable doesn't guarantee this)... */ if ((gps->flag & GP_STROKE_SELECT) == 0) continue; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (pt->flag & GP_SPOINT_SELECT) { if (gpl->parent == NULL) { @@ -1415,14 +1403,14 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) /* apply parent transformations */ float fpt[3]; mul_v3_m4v3(fpt, diff_mat, &pt->x); - + add_v3_v3(centroid, fpt); minmax_v3v3_v3(min, max, fpt); } count++; } } - + } } } @@ -1455,5 +1443,529 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* ******************* Apply layer thickness change to strokes ************************** */ + +static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op)) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); + + /* sanity checks */ + if (ELEM(NULL, gpd, gpl, gpl->frames.first)) + return OPERATOR_CANCELLED; + + /* loop all strokes */ + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + /* Apply thickness */ + gps->thickness = gps->thickness + gpl->thickness; + } + } + /* clear value */ + gpl->thickness = 0.0f; + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_stroke_apply_thickness(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Apply Stroke Thickness"; + ot->idname = "GPENCIL_OT_stroke_apply_thickness"; + ot->description = "Apply the thickness change of the layer to its strokes"; + + /* api callbacks */ + ot->exec = gp_stroke_apply_thickness_exec; + ot->poll = gp_active_layer_poll; +} + +/* ******************* Close Strokes ************************** */ + +enum { + GP_STROKE_CYCLIC_CLOSE = 1, + GP_STROKE_CYCLIC_OPEN = 2, + GP_STROKE_CYCLIC_TOGGLE = 3 +}; + +static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + const int type = RNA_enum_get(op->ptr, "type"); + + /* sanity checks */ + if (ELEM(NULL, gpd)) + return OPERATOR_CANCELLED; + + /* loop all selected strokes */ + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) + { + for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) { + bGPDpalettecolor *palcolor = gps->palcolor; + + /* skip strokes that are not selected or invalid for current view */ + if (((gps->flag & GP_STROKE_SELECT) == 0) || ED_gpencil_stroke_can_use(C, gps) == false) + continue; + /* skip hidden or locked colors */ + if (!palcolor || (palcolor->flag & PC_COLOR_HIDE) || (palcolor->flag & PC_COLOR_LOCKED)) + continue; + + switch (type) { + case GP_STROKE_CYCLIC_CLOSE: + /* Close all (enable) */ + gps->flag |= GP_STROKE_CYCLIC; + break; + case GP_STROKE_CYCLIC_OPEN: + /* Open all (disable) */ + gps->flag &= ~GP_STROKE_CYCLIC; + break; + case GP_STROKE_CYCLIC_TOGGLE: + /* Just toggle flag... */ + gps->flag ^= GP_STROKE_CYCLIC; + break; + default: + BLI_assert(0); + break; + } + } + } + CTX_DATA_END; + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +/** + * Similar to #CURVE_OT_cyclic_toggle or #MASK_OT_cyclic_toggle, but with + * option to force opened/closed strokes instead of just toggle behavior. + */ +void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) +{ + static EnumPropertyItem cyclic_type[] = { + {GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close all", ""}, + {GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open all", ""}, + {GP_STROKE_CYCLIC_TOGGLE, "TOGGLE", 0, "Toggle", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Set Cyclical State"; + ot->idname = "GPENCIL_OT_stroke_cyclical_set"; + ot->description = "Close or open the selected stroke adding an edge from last to first point"; + + /* api callbacks */ + ot->exec = gp_stroke_cyclical_set_exec; + ot->poll = gp_active_layer_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", cyclic_type, GP_STROKE_CYCLIC_TOGGLE, "Type", ""); +} + +/* ******************* Stroke join ************************** */ + +/* Helper: flip stroke */ +static void gpencil_flip_stroke(bGPDstroke *gps) +{ + int end = gps->totpoints - 1; + + for (int i = 0; i < gps->totpoints / 2; i++) { + bGPDspoint *point, *point2; + bGPDspoint pt; + + /* save first point */ + point = &gps->points[i]; + pt.x = point->x; + pt.y = point->y; + pt.z = point->z; + pt.flag = point->flag; + pt.pressure = point->pressure; + pt.strength = point->strength; + pt.time = point->time; + + /* replace first point with last point */ + point2 = &gps->points[end]; + point->x = point2->x; + point->y = point2->y; + point->z = point2->z; + point->flag = point2->flag; + point->pressure = point2->pressure; + point->strength = point2->strength; + point->time = point2->time; + + /* replace last point with first saved before */ + point = &gps->points[end]; + point->x = pt.x; + point->y = pt.y; + point->z = pt.z; + point->flag = pt.flag; + point->pressure = pt.pressure; + point->strength = pt.strength; + point->time = pt.time; + + end--; + } +} + +/* Helper: copy point between strokes */ +static void gpencil_stroke_copy_point(bGPDstroke *gps, bGPDspoint *point, float delta[3], + float pressure, float strength, float deltatime) +{ + bGPDspoint *newpoint; + + gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); + gps->totpoints++; + + newpoint = &gps->points[gps->totpoints - 1]; + newpoint->x = point->x * delta[0]; + newpoint->y = point->y * delta[1]; + newpoint->z = point->z * delta[2]; + newpoint->flag = point->flag; + newpoint->pressure = pressure; + newpoint->strength = strength; + newpoint->time = point->time + deltatime; +} + +/* Helper: join two strokes using the shortest distance (reorder stroke if necessary ) */ +static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, bGPDstroke *gps_b, const bool leave_gaps) +{ + bGPDspoint point; + bGPDspoint *pt; + int i; + float delta[3] = {1.0f, 1.0f, 1.0f}; + float deltatime = 0.0f; + + /* sanity checks */ + if (ELEM(NULL, gps_a, gps_b)) + return; + + if ((gps_a->totpoints == 0) || (gps_b->totpoints == 0)) + return; + + /* define start and end points of each stroke */ + float sa[3], sb[3], ea[3], eb[3]; + pt = &gps_a->points[0]; + copy_v3_v3(sa, &pt->x); + + pt = &gps_a->points[gps_a->totpoints - 1]; + copy_v3_v3(ea, &pt->x); + + pt = &gps_b->points[0]; + copy_v3_v3(sb, &pt->x); + + pt = &gps_b->points[gps_b->totpoints - 1]; + copy_v3_v3(eb, &pt->x); + + /* review if need flip stroke B */ + float ea_sb = len_squared_v3v3(ea, sb); + float ea_eb = len_squared_v3v3(ea, eb); + /* flip if distance to end point is shorter */ + if (ea_eb < ea_sb) { + gpencil_flip_stroke(gps_b); + } + + /* don't visibly link the first and last points? */ + if (leave_gaps) { + /* 1st: add one tail point to start invisible area */ + point = gps_a->points[gps_a->totpoints - 1]; + deltatime = point.time; + gpencil_stroke_copy_point(gps_a, &point, delta, 0.0f, 0.0f, 0.0f); + + /* 2nd: add one head point to finish invisible area */ + point = gps_b->points[0]; + gpencil_stroke_copy_point(gps_a, &point, delta, 0.0f, 0.0f, deltatime); + } + + /* 3rd: add all points */ + for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) { + /* check if still room in buffer */ + if (gps_a->totpoints <= GP_STROKE_BUFFER_MAX - 2) { + gpencil_stroke_copy_point(gps_a, pt, delta, pt->pressure, pt->strength, deltatime); + } + } +} + +static int gp_stroke_join_exec(bContext *C, wmOperator *op) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *activegpl = BKE_gpencil_layer_getactive(gpd); + bGPDstroke *gps, *gpsn; + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); + + bGPDframe *gpf_a = NULL; + bGPDstroke *stroke_a = NULL; + bGPDstroke *stroke_b = NULL; + bGPDstroke *new_stroke = NULL; + + const int type = RNA_enum_get(op->ptr, "type"); + const bool leave_gaps = RNA_boolean_get(op->ptr, "leave_gaps"); + + /* sanity checks */ + if (ELEM(NULL, gpd)) + return OPERATOR_CANCELLED; + + if (activegpl->flag & GP_LAYER_LOCKED) + return OPERATOR_CANCELLED; + + BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY)); + + + /* read all selected strokes */ + bool first = false; + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) + { + bGPDframe *gpf = gpl->actframe; + for (gps = gpf->strokes.first; gps; gps = gpsn) { + gpsn = gps->next; + if (gps->flag & GP_STROKE_SELECT) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(gpl, gps) == false) { + continue; + } + + /* to join strokes, cyclic must be disabled */ + gps->flag &= ~GP_STROKE_CYCLIC; + + /* saves first frame and stroke */ + if (!first) { + first = true; + gpf_a = gpf; + stroke_a = gps; + } + else { + stroke_b = gps; + + /* create a new stroke if was not created before (only created if something to join) */ + if (new_stroke == NULL) { + new_stroke = MEM_dupallocN(stroke_a); + new_stroke->points = MEM_dupallocN(stroke_a->points); + new_stroke->triangles = NULL; + new_stroke->tot_triangles = 0; + new_stroke->flag |= GP_STROKE_RECALC_CACHES; + + /* if new, set current color */ + if (type == GP_STROKE_JOINCOPY) { + new_stroke->palcolor = palcolor; + BLI_strncpy(new_stroke->colorname, palcolor->info, sizeof(new_stroke->colorname)); + new_stroke->flag |= GP_STROKE_RECALC_COLOR; + } + } + + /* join new_stroke and stroke B. New stroke will contain all the previous data */ + gpencil_stroke_join_strokes(new_stroke, stroke_b, leave_gaps); + + /* if join only, delete old strokes */ + if (type == GP_STROKE_JOIN) { + if (stroke_a) { + BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke); + BLI_remlink(&gpf->strokes, stroke_a); + BKE_gpencil_free_stroke(stroke_a); + stroke_a = NULL; + } + if (stroke_b) { + BLI_remlink(&gpf->strokes, stroke_b); + BKE_gpencil_free_stroke(stroke_b); + stroke_b = NULL; + } + } + } + } + } + } + CTX_DATA_END; + + /* add new stroke if was not added before */ + if (type == GP_STROKE_JOINCOPY) { + if (new_stroke) { + /* Add a new frame if needed */ + if (activegpl->actframe == NULL) + activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum); + + BLI_addtail(&activegpl->actframe->strokes, new_stroke); + } + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_stroke_join(wmOperatorType *ot) +{ + static EnumPropertyItem join_type[] = { + {GP_STROKE_JOIN, "JOIN", 0, "Join", ""}, + {GP_STROKE_JOINCOPY, "JOINCOPY", 0, "Join and Copy", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Join Strokes"; + ot->idname = "GPENCIL_OT_stroke_join"; + ot->description = "Join selected strokes (optionally as new stroke)"; + + /* api callbacks */ + ot->exec = gp_stroke_join_exec; + ot->poll = gp_active_layer_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", join_type, GP_STROKE_JOIN, "Type", ""); + RNA_def_boolean(ot->srna, "leave_gaps", false, "Leave Gaps", "Leave gaps between joined strokes instead of linking them"); +} + +/* ******************* Stroke flip ************************** */ + +static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op)) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + + /* sanity checks */ + if (ELEM(NULL, gpd)) + return OPERATOR_CANCELLED; + + /* read all selected strokes */ + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) + { + bGPDframe *gpf = gpl->actframe; + if (gpf == NULL) + continue; + + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + if (gps->flag & GP_STROKE_SELECT) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(gpl, gps) == false) { + continue; + } + + /* flip stroke */ + gpencil_flip_stroke(gps); + } + } + } + CTX_DATA_END; + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_stroke_flip(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Flip Stroke"; + ot->idname = "GPENCIL_OT_stroke_flip"; + ot->description = "Change direction of the points of the selected strokes"; + + /* api callbacks */ + ot->exec = gp_stroke_flip_exec; + ot->poll = gp_active_layer_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ***************** Reproject Strokes ********************** */ + +static int gp_strokes_reproject_poll(bContext *C) +{ + /* 2 Requirements: + * - 1) Editable GP data + * - 2) 3D View only (2D editors don't have projection issues) + */ + return (gp_stroke_edit_poll(C) && ED_operator_view3d_active(C)); +} + +static int gp_strokes_reproject_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + GP_SpaceConversion gsc = {NULL}; + + /* init space conversion stuff */ + gp_point_conversion_init(C, &gsc); + + /* Go through each editable + selected stroke, adjusting each of its points one by one... */ + GP_EDITABLE_STROKES_BEGIN(C, gpl, gps) + { + if (gps->flag & GP_STROKE_SELECT) { + bGPDspoint *pt; + int i; + float inverse_diff_mat[4][4]; + + /* Compute inverse matrix for unapplying parenting once instead of doing per-point */ + /* TODO: add this bit to the iteration macro? */ + if (gpl->parent) { + invert_m4_m4(inverse_diff_mat, diff_mat); + } + + /* Adjust each point */ + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + float xy[2]; + + /* 3D to Screenspace */ + /* Note: We can't use gp_point_to_xy() here because that uses ints for the screenspace + * coordinates, resulting in lost precision, which in turn causes stairstepping + * artifacts in the final points. + */ + if (gpl->parent == NULL) { + gp_point_to_xy_fl(&gsc, gps, pt, &xy[0], &xy[1]); + } + else { + bGPDspoint pt2; + gp_point_to_parent_space(pt, diff_mat, &pt2); + gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); + } + + /* Project screenspace back to 3D space (from current perspective) + * so that all points have been treated the same way + */ + gp_point_xy_to_3d(&gsc, scene, xy, &pt->x); + + /* Unapply parent corrections */ + if (gpl->parent) { + mul_m4_v3(inverse_diff_mat, &pt->x); + } + } + } + } + GP_EDITABLE_STROKES_END; + + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_reproject(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Reproject Strokes"; + ot->idname = "GPENCIL_OT_reproject"; + ot->description = "Reproject the selected strokes from the current viewpoint to get all points on the same plane again " + "(e.g. to fix problems from accidental 3D cursor movement, or viewport changes)"; + + /* callbacks */ + ot->exec = gp_strokes_reproject_exec; + ot->poll = gp_strokes_reproject_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} /* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 0ff0878d4ce..4178d49d652 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -101,6 +101,18 @@ void gp_point_to_xy(GP_SpaceConversion *settings, struct bGPDstroke *gps, struct int *r_x, int *r_y); /** + * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D) + * + * Just like gp_point_to_xy(), except the resulting coordinates are floats not ints. + * Use this version to solve "stair-step" artifacts which may arise when roundtripping the calculations. + * + * \param[out] r_x The screen-space x-coordinate of the point + * \param[out] r_y The screen-space y-coordinate of the point + */ +void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, + float *r_x, float *r_y); + +/** * Convert point to parent space * * \param pt Original point @@ -183,7 +195,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints); /** * Add randomness to stroke * \param gps Stroke data -* \param brsuh Brush data +* \param brush Brush data */ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush); @@ -199,6 +211,7 @@ EnumPropertyItem *ED_gpencil_brushes_enum_itemf(bContext *C, PointerRNA *UNUSED( /* Enums of GP palettes */ EnumPropertyItem *ED_gpencil_palettes_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free); + /* ***************************************************** */ /* Operator Defines */ @@ -206,7 +219,7 @@ EnumPropertyItem *ED_gpencil_palettes_enum_itemf(bContext *C, PointerRNA *UNUSED void GPENCIL_OT_draw(struct wmOperatorType *ot); -/* Paint Modes for operator*/ +/* Paint Modes for operator */ typedef enum eGPencil_PaintModes { GP_PAINTMODE_DRAW = 0, GP_PAINTMODE_ERASER, @@ -214,6 +227,9 @@ typedef enum eGPencil_PaintModes { GP_PAINTMODE_DRAW_POLY } eGPencil_PaintModes; +/* maximum sizes of gp-session buffer */ +#define GP_STROKE_BUFFER_MAX 5000 + /* stroke editing ----- */ void GPENCIL_OT_editmode_toggle(struct wmOperatorType *ot); @@ -246,6 +262,7 @@ void GPENCIL_OT_snap_to_cursor(struct wmOperatorType *ot); void GPENCIL_OT_snap_cursor_to_selected(struct wmOperatorType *ot); void GPENCIL_OT_snap_cursor_to_center(struct wmOperatorType *ot); +void GPENCIL_OT_reproject(struct wmOperatorType *ot); /* stroke sculpting -- */ @@ -275,6 +292,11 @@ void GPENCIL_OT_active_frames_delete_all(struct wmOperatorType *ot); void GPENCIL_OT_convert(struct wmOperatorType *ot); +enum { + GP_STROKE_JOIN = -1, + GP_STROKE_JOINCOPY = 1 +}; + void GPENCIL_OT_stroke_arrange(struct wmOperatorType *ot); void GPENCIL_OT_stroke_change_color(struct wmOperatorType *ot); void GPENCIL_OT_stroke_lock_color(struct wmOperatorType *ot); @@ -295,10 +317,10 @@ void GPENCIL_OT_palette_add(struct wmOperatorType *ot); void GPENCIL_OT_palette_remove(struct wmOperatorType *ot); void GPENCIL_OT_palette_change(struct wmOperatorType *ot); void GPENCIL_OT_palette_lock_layer(struct wmOperatorType *ot); + void GPENCIL_OT_palettecolor_add(struct wmOperatorType *ot); void GPENCIL_OT_palettecolor_remove(struct wmOperatorType *ot); void GPENCIL_OT_palettecolor_isolate(struct wmOperatorType *ot); - void GPENCIL_OT_palettecolor_hide(struct wmOperatorType *ot); void GPENCIL_OT_palettecolor_reveal(struct wmOperatorType *ot); void GPENCIL_OT_palettecolor_lock_all(struct wmOperatorType *ot); @@ -313,7 +335,7 @@ void gpencil_undo_init(struct bGPdata *gpd); void gpencil_undo_push(struct bGPdata *gpd); void gpencil_undo_finish(void); -/******************************************************* */ +/* ****************************************************** */ /* FILTERED ACTION DATA - TYPES ---> XXX DEPRECEATED OLD ANIM SYSTEM CODE! */ /* XXX - TODO: replace this with the modern bAnimListElem... */ @@ -335,7 +357,7 @@ typedef struct bActListElem { short ownertype; /* type of owner */ } bActListElem; -/******************************************************* */ +/* ****************************************************** */ /* FILTER ACTION DATA - METHODS/TYPES */ /* filtering flags - under what circumstances should a channel be added */ @@ -358,6 +380,9 @@ typedef enum ACTCONT_TYPES { ACTCONT_GPENCIL } ACTCONT_TYPES; +/* ****************************************************** */ +/* Stroke Iteration Utilities */ + /** * Iterate over all editable strokes in the current context, * stopping on each usable layer + stroke pair (i.e. gpl and gps) @@ -393,4 +418,6 @@ typedef enum ACTCONT_TYPES { CTX_DATA_END; \ } (void)0 +/* ****************************************************** */ + #endif /* __GPENCIL_INTERN_H__ */ diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 6bbb8f7c965..ae1c5554521 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -240,6 +240,12 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, KM_SHIFT, 0); + /* join strokes */ + WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, KM_CTRL, 0); + + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", GP_STROKE_JOINCOPY); + /* copy + paste */ WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0); @@ -369,6 +375,8 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_snap_to_cursor); WM_operatortype_append(GPENCIL_OT_snap_cursor_to_selected); + WM_operatortype_append(GPENCIL_OT_reproject); + WM_operatortype_append(GPENCIL_OT_brush_paint); /* Editing (Buttons) ------------ */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 403d632b5da..cc45cbd82af 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -164,9 +164,6 @@ typedef struct tGPsdata { /* ------ */ -/* maximum sizes of gp-session buffer */ -#define GP_STROKE_BUFFER_MAX 5000 - /* Macros for accessing sensitivity thresholds... */ /* minimum number of pixels mouse should move before new point created */ #define MIN_MANHATTEN_PX (U.gp_manhattendist) @@ -544,7 +541,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); /* get pointer to destination point */ pt = (tGPspoint *)(gpd->sbuffer); @@ -692,6 +689,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) bGPDspoint *pt; tGPspoint *ptc; bGPDbrush *brush = p->brush; + ToolSettings *ts = p->scene->toolsettings; int i, totelem; /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */ @@ -920,13 +918,21 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) MEM_freeN(depth_arr); } /* Save palette color */ - bGPDpalette *palette = gpencil_palette_getactive(p->gpd); - bGPDpalettecolor *palcolor = gpencil_palettecolor_getactive(palette); + bGPDpalette *palette = BKE_gpencil_palette_getactive(p->gpd); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); gps->palcolor = palcolor; - strcpy(gps->colorname, palcolor->info); + BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname)); - /* add stroke to frame */ - BLI_addtail(&p->gpf->strokes, gps); + /* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke is added on listbase head + * because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist + * when drawing the background + */ + if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) && (p->paintmode != GP_PAINTMODE_DRAW_POLY)) { + BLI_addhead(&p->gpf->strokes, gps); + } + else { + BLI_addtail(&p->gpf->strokes, gps); + } gp_stroke_added_enable(p); } @@ -1221,7 +1227,7 @@ static bGPDpalettecolor *gp_create_new_color(bGPDpalette *palette) { bGPDpalettecolor *palcolor; - palcolor = gpencil_palettecolor_addnew(palette, DATA_("Color"), true); + palcolor = BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true); return palcolor; } @@ -1234,12 +1240,12 @@ static void gp_init_drawing_brush(ToolSettings *ts, tGPsdata *p) /* if not exist, create a new one */ if (BLI_listbase_is_empty(&ts->gp_brushes)) { /* create new brushes */ - gpencil_brush_init_presets(ts); - brush = gpencil_brush_getactive(ts); + BKE_gpencil_brush_init_presets(ts); + brush = BKE_gpencil_brush_getactive(ts); } else { /* Use the current */ - brush = gpencil_brush_getactive(ts); + brush = BKE_gpencil_brush_getactive(ts); } /* be sure curves are initializated */ curvemapping_initialize(brush->cur_sensitivity); @@ -1263,23 +1269,23 @@ static void gp_init_palette(tGPsdata *p) /* if not exist, create a new palette */ if (BLI_listbase_is_empty(&gpd->palettes)) { /* create new palette */ - palette = gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true); + palette = BKE_gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true); /* now create a default color */ palcolor = gp_create_new_color(palette); } else { /* Use the current palette and color */ - palette = gpencil_palette_getactive(gpd); + palette = BKE_gpencil_palette_getactive(gpd); /* the palette needs one color */ if (BLI_listbase_is_empty(&palette->colors)) { palcolor = gp_create_new_color(palette); } else { - palcolor = gpencil_palettecolor_getactive(palette); + palcolor = BKE_gpencil_palettecolor_getactive(palette); } /* in some situations can be null, so use first */ if (palcolor == NULL) { - gpencil_palettecolor_setactive(palette, palette->colors.first); + BKE_gpencil_palettecolor_setactive(palette, palette->colors.first); palcolor = palette->colors.first; } } @@ -1439,7 +1445,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) else { /* if no existing GPencil block exists, add one */ if (*gpd_ptr == NULL) - *gpd_ptr = gpencil_data_addnew("GPencil"); + *gpd_ptr = BKE_gpencil_data_addnew("GPencil"); p->gpd = *gpd_ptr; } @@ -1514,9 +1520,9 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) ToolSettings *ts = scene->toolsettings; /* get active layer (or add a new one if non-existent) */ - p->gpl = gpencil_layer_getactive(p->gpd); + p->gpl = BKE_gpencil_layer_getactive(p->gpd); if (p->gpl == NULL) { - p->gpl = gpencil_layer_addnew(p->gpd, "GP_Layer", true); + p->gpl = BKE_gpencil_layer_addnew(p->gpd, "GP_Layer", true); if (p->custom_color[3]) copy_v3_v3(p->gpl->color, p->custom_color); @@ -1544,7 +1550,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) /* Add a new frame if needed (and based off the active frame, * as we need some existing strokes to erase) */ - gpl->actframe = gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY); + gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY); /* XXX: we omit GP_FRAME_PAINT here for now, * as it is only really useful for doing @@ -1580,7 +1586,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) else add_frame_mode = GP_GETFRAME_ADD_NEW; - p->gpf = gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode); + p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode); if (p->gpf == NULL) { p->status = GP_STATUS_ERROR; @@ -2278,10 +2284,33 @@ static void gpencil_stroke_end(wmOperator *op) p->gpf = NULL; } +/* Move last stroke in the listbase to the head to be drawn below all previous strokes in the layer */ +static void gpencil_move_last_stroke_to_back(bContext *C) +{ + /* move last stroke (the polygon) to head of the listbase stroke to draw on back of all previous strokes */ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); + + /* sanity checks */ + if (ELEM(NULL, gpd, gpl, gpl->actframe)) { + return; + } + + bGPDframe *gpf = gpl->actframe; + bGPDstroke *gps = gpf->strokes.last; + if (ELEM(NULL, gps)) { + return; + } + + BLI_remlink(&gpf->strokes, gps); + BLI_insertlinkbefore(&gpf->strokes, gpf->strokes.first, gps); +} + /* events handling during interactive drawing part of operator */ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p = op->customdata; + ToolSettings *ts = CTX_data_tool_settings(C); int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */ /* if (event->type == NDOF_MOTION) @@ -2334,6 +2363,14 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, EKEY)) { /* exit() ends the current stroke before cleaning up */ /* printf("\t\tGP - end of paint op + end of stroke\n"); */ + /* if drawing polygon and enable on back, must move stroke */ + if (ts) { + if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) && (p->paintmode == GP_PAINTMODE_DRAW_POLY)) { + if (p->flags & GP_PAINTFLAG_STROKEADDED) { + gpencil_move_last_stroke_to_back(C); + } + } + } p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -2390,9 +2427,14 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } else { /* printf("\t\tGP - end of stroke + op\n"); */ - /* disable paint session */ - p->scene->toolsettings->gpencil_flags &= ~GP_TOOL_FLAG_PAINTSESSIONS_ON; - + /* if drawing polygon and enable on back, must move stroke */ + if (ts) { + if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) && (p->paintmode == GP_PAINTMODE_DRAW_POLY)) { + if (p->flags & GP_PAINTFLAG_STROKEADDED) { + gpencil_move_last_stroke_to_back(C); + } + } + } p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -2422,9 +2464,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) in_bounds = true; } else { - /* disable paint session */ - p->scene->toolsettings->gpencil_flags &= ~GP_TOOL_FLAG_PAINTSESSIONS_ON; - /* Out of bounds, or invalid in some other way */ p->status = GP_STATUS_ERROR; estate = OPERATOR_CANCELLED; @@ -2441,9 +2480,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) in_bounds = BLI_rcti_isect_pt_v(®ion_rect, event->mval); } else { - /* disable paint session */ - p->scene->toolsettings->gpencil_flags &= ~GP_TOOL_FLAG_PAINTSESSIONS_ON; - /* No region */ p->status = GP_STATUS_ERROR; estate = OPERATOR_CANCELLED; @@ -2471,9 +2507,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) p = gpencil_stroke_begin(C, op); if (p->status == GP_STATUS_ERROR) { - /* disable paint session */ - p->scene->toolsettings->gpencil_flags &= ~GP_TOOL_FLAG_PAINTSESSIONS_ON; - estate = OPERATOR_CANCELLED; } } @@ -2482,9 +2515,14 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * NOTE: Don't eter this case if an error occurred while finding the * region (as above) */ - /* disable paint session */ - p->scene->toolsettings->gpencil_flags &= ~GP_TOOL_FLAG_PAINTSESSIONS_ON; - + /* if drawing polygon and enable on back, must move stroke */ + if (ts) { + if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) && (p->paintmode == GP_PAINTMODE_DRAW_POLY)) { + if (p->flags & GP_PAINTFLAG_STROKEADDED) { + gpencil_move_last_stroke_to_back(C); + } + } + } p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 612b35aa608..45dbde80284 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -36,6 +36,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_lasso.h" #include "BLI_utildefines.h" #include "BLI_math_vector.h" @@ -253,6 +254,9 @@ typedef enum eGP_SelectGrouped { /* Select strokes in the same layer */ GP_SEL_SAME_LAYER = 0, + /* Select strokes with the same color */ + GP_SEL_SAME_COLOR = 1, + /* TODO: All with same prefix - Useful for isolating all layers for a particular character for instance */ /* TODO: All with same appearance - colour/opacity/volumetric/fills ? */ } eGP_SelectGrouped; @@ -266,7 +270,7 @@ static void gp_select_same_layer(bContext *C) CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { - bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0); bGPDstroke *gps; bool found = false; @@ -302,6 +306,43 @@ static void gp_select_same_layer(bContext *C) CTX_DATA_END; } +/* Select all strokes with same colors as selected ones */ +static void gp_select_same_color(bContext *C) +{ + /* First, build set containing all the colors of selected strokes + * - We use the palette names, so that we can select all strokes with one + * (potentially missing) color, and remap them to something else + */ + GSet *selected_colors = BLI_gset_str_new("GP Selected Colors"); + + CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) + { + if (gps->flag & GP_STROKE_SELECT) { + /* add instead of insert here, otherwise the uniqueness check gets skipped, + * and we get many duplicate entries... + */ + BLI_gset_add(selected_colors, gps->colorname); + } + } + CTX_DATA_END; + + /* Second, select any visible stroke that uses these colors */ + CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) + { + if (BLI_gset_haskey(selected_colors, gps->colorname)) { + /* select this stroke */ + bGPDspoint *pt; + int i; + + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + pt->flag |= GP_SPOINT_SELECT; + } + + gps->flag |= GP_STROKE_SELECT; + } + } + CTX_DATA_END; +} /* ----------------------------------- */ @@ -314,6 +355,9 @@ static int gpencil_select_grouped_exec(bContext *C, wmOperator *op) case GP_SEL_SAME_LAYER: gp_select_same_layer(C); break; + case GP_SEL_SAME_COLOR: + gp_select_same_color(C); + break; default: BLI_assert(!"unhandled select grouped gpencil mode"); @@ -329,6 +373,7 @@ void GPENCIL_OT_select_grouped(wmOperatorType *ot) { static EnumPropertyItem prop_select_grouped_types[] = { {GP_SEL_SAME_LAYER, "LAYER", 0, "Layer", "Shared layers"}, + {GP_SEL_SAME_COLOR, "COLOR", 0, "Color", "Shared colors"}, {0, NULL, 0, NULL, NULL} }; @@ -338,7 +383,7 @@ void GPENCIL_OT_select_grouped(wmOperatorType *ot) ot->description = "Select all strokes with similar characteristics"; /* callbacks */ - //ot->invoke = WM_menu_invoke; + ot->invoke = WM_menu_invoke; ot->exec = gpencil_select_grouped_exec; ot->poll = gpencil_select_poll; @@ -709,7 +754,7 @@ static bool gp_stroke_do_circle_sel( } /* Ensure that stroke selection is in sync with its points */ - gpencil_stroke_sync_selection(gps); + BKE_gpencil_stroke_sync_selection(gps); } return changed; @@ -871,7 +916,7 @@ static int gpencil_border_select_exec(bContext *C, wmOperator *op) } /* Ensure that stroke selection is in sync with its points */ - gpencil_stroke_sync_selection(gps); + BKE_gpencil_stroke_sync_selection(gps); } GP_EDITABLE_STROKES_END; @@ -981,7 +1026,7 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op) } /* Ensure that stroke selection is in sync with its points */ - gpencil_stroke_sync_selection(gps); + BKE_gpencil_stroke_sync_selection(gps); } GP_EDITABLE_STROKES_END; @@ -1152,7 +1197,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) hit_point->flag &= ~GP_SPOINT_SELECT; /* ensure that stroke is selected correctly */ - gpencil_stroke_sync_selection(hit_stroke); + BKE_gpencil_stroke_sync_selection(hit_stroke); } } diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c index 1d7582eb18b..793ed2a07d0 100644 --- a/source/blender/editors/gpencil/gpencil_undo.c +++ b/source/blender/editors/gpencil/gpencil_undo.c @@ -100,14 +100,14 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name) bGPdata *gpd = *gpd_ptr; bGPDlayer *gpl, *gpld; - free_gpencil_layers(&gpd->layers); + BKE_gpencil_free_layers(&gpd->layers); /* copy layers */ BLI_listbase_clear(&gpd->layers); for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) { /* make a copy of source layer and its data */ - gpld = gpencil_layer_duplicate(gpl); + gpld = BKE_gpencil_layer_duplicate(gpl); BLI_addtail(&gpd->layers, gpld); } } @@ -153,7 +153,7 @@ void gpencil_undo_push(bGPdata *gpd) /* create new undo node */ undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node"); - undo_node->gpd = gpencil_data_duplicate(G.main, gpd, true); + undo_node->gpd = BKE_gpencil_data_duplicate(G.main, gpd, true); cur_node = undo_node; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index f2c542da0aa..564ba639983 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -225,7 +225,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra) /* just check both for now... */ // XXX: this could get confusing (e.g. if only on the object, but other places don't show this) if (scene->gpd) { - bGPDlayer *gpl = gpencil_layer_getactive(scene->gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(scene->gpd); if (gpl) { if (gpl->actframe) { // XXX: assumes that frame has been fetched already @@ -239,7 +239,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra) } if (ob && ob->gpd) { - bGPDlayer *gpl = gpencil_layer_getactive(ob->gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->gpd); if (gpl) { if (gpl->actframe) { // XXX: assumes that frame has been fetched already @@ -269,7 +269,7 @@ int gp_add_poll(bContext *C) int gp_active_layer_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); return (gpl != NULL); } @@ -278,7 +278,7 @@ int gp_active_layer_poll(bContext *C) int gp_active_brush_poll(bContext *C) { ToolSettings *ts = CTX_data_tool_settings(C); - bGPDbrush *brush = gpencil_brush_getactive(ts); + bGPDbrush *brush = BKE_gpencil_brush_getactive(ts); return (brush != NULL); } @@ -287,7 +287,7 @@ int gp_active_brush_poll(bContext *C) int gp_active_palette_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); return (palette != NULL); } @@ -296,8 +296,8 @@ int gp_active_palette_poll(bContext *C) int gp_active_palettecolor_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDpalette *palette = gpencil_palette_getactive(gpd); - bGPDpalettecolor *palcolor = gpencil_palettecolor_getactive(palette); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); return (palcolor != NULL); } @@ -470,20 +470,20 @@ bGPDpalettecolor *ED_gpencil_stroke_getcolor(bGPdata *gpd, bGPDstroke *gps) return gps->palcolor; /* get palette */ - palette = gpencil_palette_getactive(gpd); + palette = BKE_gpencil_palette_getactive(gpd); if (palette == NULL) { - palette = gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true); + palette = BKE_gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true); } /* get color */ - palcolor = gpencil_palettecolor_getbyname(palette, gps->colorname); + palcolor = BKE_gpencil_palettecolor_getbyname(palette, gps->colorname); if (palcolor == NULL) { if (gps->palcolor == NULL) { - palcolor = gpencil_palettecolor_addnew(palette, DATA_("Color"), true); + palcolor = BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true); /* set to a different color */ ARRAY_SET_ITEMS(palcolor->color, 1.0f, 0.0f, 1.0f, 0.9f); } else { - palcolor = gpencil_palettecolor_addnew(palette, gps->colorname, true); + palcolor = BKE_gpencil_palettecolor_addnew(palette, gps->colorname, true); /* set old color and attributes */ bGPDpalettecolor *gpscolor = gps->palcolor; copy_v4_v4(palcolor->color, gpscolor->color); @@ -628,6 +628,63 @@ void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, } } +/* Convert Grease Pencil points to screen-space values (as floats) + * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn + */ +void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, + float *r_x, float *r_y) +{ + ARegion *ar = gsc->ar; + View2D *v2d = gsc->v2d; + rctf *subrect = gsc->subrect; + float xyval[2]; + + /* sanity checks */ + BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D)); + BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D)); + + + if (gps->flag & GP_STROKE_3DSPACE) { + if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + *r_x = xyval[0]; + *r_y = xyval[1]; + } + else { + *r_x = 0.0f; + *r_y = 0.0f; + } + } + else if (gps->flag & GP_STROKE_2DSPACE) { + float vec[3] = {pt->x, pt->y, 0.0f}; + int t_x, t_y; + + mul_m4_v3(gsc->mat, vec); + UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y); + + if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) { + /* XXX: Or should we just always use the values as-is? */ + *r_x = 0.0f; + *r_y = 0.0f; + } + else { + *r_x = (float)t_x; + *r_y = (float)t_y; + } + } + else { + if (subrect == NULL) { + /* normal 3D view (or view space) */ + *r_x = (pt->x / 100.0f * ar->winx); + *r_y = (pt->y / 100.0f * ar->winy); + } + else { + /* camera view, use subrect */ + *r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin; + *r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin; + } + } +} + /** * Project screenspace coordinates to 3D-space * @@ -883,10 +940,12 @@ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush) float normal[3]; cross_v3_v3v3(normal, v1, v2); normalize_v3(normal); + /* get orthogonal vector to plane to rotate random effect */ float ortho[3]; cross_v3_v3v3(ortho, v1, normal); normalize_v3(ortho); + /* Read all points and apply shift vector (first and last point not modified) */ for (int i = 1; i < gps->totpoints - 1; ++i) { bGPDspoint *pt = &gps->points[i]; @@ -955,8 +1014,8 @@ bool ED_gpencil_stroke_minmax( } return changed; } -/* Dynamic Enums of GP Brushes */ +/* Dynamic Enums of GP Brushes */ EnumPropertyItem *ED_gpencil_brushes_enum_itemf( bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) @@ -990,8 +1049,8 @@ EnumPropertyItem *ED_gpencil_brushes_enum_itemf( return item; } -/* Dynamic Enums of GP Palettes */ +/* Dynamic Enums of GP Palettes */ EnumPropertyItem *ED_gpencil_palettes_enum_itemf( bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 0940f594482..bfd89e90fce 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -156,6 +156,7 @@ typedef enum eAnim_ChannelType { ANIMTYPE_DSMAT, ANIMTYPE_DSLAM, ANIMTYPE_DSCAM, + ANIMTYPE_DSCACHEFILE, ANIMTYPE_DSCUR, ANIMTYPE_DSSKEY, ANIMTYPE_DSWOR, @@ -275,6 +276,7 @@ typedef enum eAnimFilter_Flags { #define FILTER_MAT_OBJD(ma) (CHECK_TYPE_INLINE(ma, Material *), ((ma->flag & MA_DS_EXPAND))) #define FILTER_LAM_OBJD(la) (CHECK_TYPE_INLINE(la, Lamp *), ((la->flag & LA_DS_EXPAND))) #define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera *), ((ca->flag & CAM_DS_EXPAND))) +#define FILTER_CACHEFILE_OBJD(cf) (CHECK_TYPE_INLINE(cf, CacheFile *), ((cf->flag & CACHEFILE_DS_EXPAND))) #define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve *), ((cu->flag & CU_DS_EXPAND))) #define FILTER_PART_OBJD(part) (CHECK_TYPE_INLINE(part, ParticleSettings *), ((part->flag & PART_DS_EXPAND))) #define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall *), ((mb->flag2 & MB_DS_EXPAND))) diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index b1f3f012e09..c478a8b17e5 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -34,6 +34,7 @@ struct bAnimContext; struct AnimData; +struct CacheFile; struct FCurve; struct bDopeSheet; struct bAction; @@ -141,6 +142,8 @@ void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, struct D void action_to_keylist(struct AnimData *adt, struct bAction *act, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks); /* Object */ void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks); +/* Cache File */ +void cachefile_to_keylist(struct bDopeSheet *ads, struct CacheFile *cache_file, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks); /* Scene */ void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks); /* DopeSheet Summary */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index f77e795adca..49e5845e3ca 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -393,6 +393,8 @@ struct uiLayout *UI_popup_menu_layout(uiPopupMenu *head); void UI_popup_menu_reports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL(); int UI_popup_menu_invoke(struct bContext *C, const char *idname, struct ReportList *reports) ATTR_NONNULL(1, 2); +void UI_popup_menu_retval_set(const uiBlock *block, const int retval, const bool enable); + /* Pie menus */ typedef struct uiPieMenu uiPieMenu; @@ -945,6 +947,7 @@ void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr); void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name); void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color); +void uiTemplateCacheFile(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname); /* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */ #define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list" diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 79831cefde6..4972e16bf2e 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -5415,6 +5415,7 @@ static bool ui_numedit_but_HSVCUBE( return changed; } +#ifdef WITH_INPUT_NDOF static void ui_ndofedit_but_HSVCUBE( uiBut *but, uiHandleButtonData *data, const wmNDOFMotionData *ndof, @@ -5487,6 +5488,7 @@ static void ui_ndofedit_but_HSVCUBE( copy_v3_v3(data->vec, rgb); ui_but_v3_set(but, data->vec); } +#endif /* WITH_INPUT_NDOF */ static int ui_do_but_HSVCUBE( bContext *C, uiBlock *block, uiBut *but, @@ -5514,6 +5516,7 @@ static int ui_do_but_HSVCUBE( return WM_UI_HANDLER_BREAK; } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { const wmNDOFMotionData *ndof = event->customdata; const enum eSnapType snap = ui_event_to_snap(event); @@ -5525,6 +5528,7 @@ static int ui_do_but_HSVCUBE( return WM_UI_HANDLER_BREAK; } +#endif /* WITH_INPUT_NDOF */ /* XXX hardcoded keymap check.... */ else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) { if (ELEM(but->a1, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) { @@ -5680,6 +5684,7 @@ static bool ui_numedit_but_HSVCIRCLE( return changed; } +#ifdef WITH_INPUT_NDOF static void ui_ndofedit_but_HSVCIRCLE( uiBut *but, uiHandleButtonData *data, const wmNDOFMotionData *ndof, @@ -5750,7 +5755,7 @@ static void ui_ndofedit_but_HSVCIRCLE( ui_but_v3_set(but, data->vec); } - +#endif /* WITH_INPUT_NDOF */ static int ui_do_but_HSVCIRCLE( bContext *C, uiBlock *block, uiBut *but, @@ -5778,6 +5783,7 @@ static int ui_do_but_HSVCIRCLE( return WM_UI_HANDLER_BREAK; } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { const enum eSnapType snap = ui_event_to_snap(event); const wmNDOFMotionData *ndof = event->customdata; @@ -5789,6 +5795,7 @@ static int ui_do_but_HSVCIRCLE( return WM_UI_HANDLER_BREAK; } +#endif /* WITH_INPUT_NDOF */ /* XXX hardcoded keymap check.... */ else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) { int len; @@ -9914,6 +9921,17 @@ static int ui_handle_menus_recursive( return retval; } +/** + * Allow setting menu return value from externals. E.g. WM might need to do this for exiting files correctly. + */ +void UI_popup_menu_retval_set(const uiBlock *block, const int retval, const bool enable) +{ + uiPopupBlockHandle *menu = block->handle; + if (menu) { + menu->menuretval = enable ? (menu->menuretval | retval) : (menu->menuretval & retval); + } +} + /* *************** UI event handlers **************** */ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(userdata)) @@ -10156,7 +10174,11 @@ static void ui_popup_handler_remove(bContext *C, void *userdata) { uiPopupBlockHandle *menu = userdata; - if (menu->cancel_func) { + /* More correct would be to expect UI_RETURN_CANCEL here, but not wanting to + * cancel when removing handlers because of file exit is a rare exception. + * So instead of setting cancel flag for all menus before removing handlers, + * just explicitly flag menu with UI_RETURN_OK to avoid cancelling it. */ + if ((menu->menuretval & UI_RETURN_OK) == 0 && menu->cancel_func) { menu->cancel_func(C, menu->popup_arg); } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 4107414a240..22a450d2523 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1541,6 +1541,8 @@ int UI_idcode_icon_get(const int idcode) return ICON_BRUSH_DATA; case ID_CA: return ICON_CAMERA_DATA; + case ID_CF: + return ICON_FILE; case ID_CU: return ICON_CURVE_DATA; case ID_GD: diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index c621fcf493d..c507401b9a0 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1380,6 +1380,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe rect_pre.xmax = rect_post.xmin = rect.xmin + ((rect.xmax - rect.xmin) / 4); /* widget itself */ + /* NOTE: i18n messages extracting tool does the same, please keep it in sync. */ { wmOperatorType *ot = data->items.pointers[a]; @@ -1400,7 +1401,8 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe } rect_pre.xmax += 4; /* sneaky, avoid showing ugly margin */ - ui_draw_menu_item(&data->fstyle, &rect_pre, text_pre, data->items.icons[a], state, false); + ui_draw_menu_item(&data->fstyle, &rect_pre, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, text_pre), + data->items.icons[a], state, false); ui_draw_menu_item(&data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep); } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 58cadf5587a..50dd219b53c 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -32,6 +32,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_cachefile_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -325,7 +326,9 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } else { if (id) { + Main *bmain = CTX_data_main(C); id_single_user(C, id, &template->ptr, template->prop); + DAG_relations_tag_update(bmain); } } } @@ -368,6 +371,7 @@ static const char *template_id_browse_tip(StructRNA *type) case ID_MSK: return N_("Browse Mask to be linked"); case ID_PAL: return N_("Browse Palette Data to be linked"); case ID_PC: return N_("Browse Paint Curve Data to be linked"); + case ID_CF: return N_("Browse Cache Files to be linked"); } } return N_("Browse ID data to be linked"); @@ -872,8 +876,8 @@ static uiLayout *draw_modifier( /* mode enabling buttons */ UI_block_align_begin(block); - /* Softbody not allowed in this situation, enforce! */ - if (((md->type != eModifierType_Softbody && md->type != eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && + /* Collision and Surface are always enabled, hide buttons! */ + if (((md->type != eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type != eModifierType_Surface) ) { uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE); @@ -3848,3 +3852,73 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color) UI_block_align_end(block); } + +/********************************* Cache File *********************************/ + +void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname) +{ + if (!ptr->data) { + return; + } + + PropertyRNA *prop = RNA_struct_find_property(ptr, propname); + + if (!prop) { + printf("%s: property not found: %s.%s\n", + __func__, RNA_struct_identifier(ptr->type), propname); + return; + } + + if (RNA_property_type(prop) != PROP_POINTER) { + printf("%s: expected pointer property for %s.%s\n", + __func__, RNA_struct_identifier(ptr->type), propname); + return; + } + + PointerRNA fileptr = RNA_property_pointer_get(ptr, prop); + CacheFile *file = fileptr.data; + + uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr); + + uiTemplateID(layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL); + + if (!file) { + return; + } + + uiLayout *row = uiLayoutRow(layout, false); + uiBlock *block = uiLayoutGetBlock(row); + uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, ""); + + row = uiLayoutRow(layout, false); + uiLayout *split = uiLayoutSplit(row, 0.0f, false); + row = uiLayoutRow(split, true); + + uiItemR(row, &fileptr, "filepath", 0, "", ICON_NONE); + uiItemO(row, "", ICON_FILE_REFRESH, "cachefile.reload"); + + row = uiLayoutRow(layout, false); + uiItemR(row, &fileptr, "is_sequence", 0, "Is Sequence", ICON_NONE); + + row = uiLayoutRow(layout, false); + uiItemR(row, &fileptr, "override_frame", 0, "Override Frame", ICON_NONE); + + row = uiLayoutRow(layout, false); + uiLayoutSetEnabled(row, RNA_boolean_get(&fileptr, "override_frame")); + uiItemR(row, &fileptr, "frame", 0, "Frame", ICON_NONE); + + row = uiLayoutRow(layout, false); + uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE); + + row = uiLayoutRow(layout, false); + uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE); + + /* TODO: unused for now, so no need to expose. */ +#if 0 + row = uiLayoutRow(layout, false); + uiItemR(row, &fileptr, "forward_axis", 0, "Forward Axis", ICON_NONE); + + row = uiLayoutRow(layout, false); + uiItemR(row, &fileptr, "up_axis", 0, "Up Axis", ICON_NONE); +#endif +} diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index f60fed398ec..d2b2f12c1a5 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -127,6 +127,7 @@ static int view_pan_init(bContext *C, wmOperator *op) return 1; } +#ifdef WITH_INPUT_NDOF static int view_pan_poll(bContext *C) { ARegion *ar = CTX_wm_region(C); @@ -144,6 +145,7 @@ static int view_pan_poll(bContext *C) /* view can pan */ return 1; } +#endif /* apply transform to view (i.e. adjust 'cur' rect) */ static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float dy) @@ -1296,7 +1298,7 @@ static void VIEW2D_OT_zoom_border(wmOperatorType *ot) WM_operator_properties_gesture_border(ot, false); } - +#ifdef WITH_INPUT_NDOF static int view2d_ndof_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type != NDOF_MOTION) { @@ -1369,6 +1371,7 @@ static void VIEW2D_OT_ndof(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_LOCK_BYPASS; } +#endif /* WITH_INPUT_NDOF */ /* ********************************************************* */ /* SMOOTH VIEW */ @@ -2067,7 +2070,9 @@ void ED_operatortypes_view2d(void) WM_operatortype_append(VIEW2D_OT_zoom); WM_operatortype_append(VIEW2D_OT_zoom_border); +#ifdef WITH_INPUT_NDOF WM_operatortype_append(VIEW2D_OT_ndof); +#endif WM_operatortype_append(VIEW2D_OT_smoothview); @@ -2097,7 +2102,9 @@ void ED_keymap_view2d(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "VIEW2D_OT_ndof", NDOF_MOTION, 0, 0, 0); +#endif /* zoom - single step */ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt index 828cb494eab..b3bbce939a5 100644 --- a/source/blender/editors/io/CMakeLists.txt +++ b/source/blender/editors/io/CMakeLists.txt @@ -28,6 +28,8 @@ set(INC ../../makesrna ../../windowmanager ../../collada + ../../alembic + ../../../../intern/guardedalloc ) set(INC_SYS @@ -35,9 +37,13 @@ set(INC_SYS ) set(SRC + io_alembic.c + io_cache.c io_collada.c io_ops.c + io_alembic.h + io_cache.h io_collada.h io_ops.h ) @@ -46,6 +52,14 @@ if(WITH_OPENCOLLADA) add_definitions(-DWITH_COLLADA) endif() +if(WITH_ALEMBIC) + add_definitions(-DWITH_ALEMBIC) + + if(WITH_ALEMBIC_HDF5) + add_definitions(-DWITH_ALEMBIC_HDF5) + endif() +endif() + if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c new file mode 100644 index 00000000000..cd75983e0a0 --- /dev/null +++ b/source/blender/editors/io/io_alembic.c @@ -0,0 +1,484 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifdef WITH_ALEMBIC + +/* needed for directory lookup */ +#ifndef WIN32 +# include <dirent.h> +#else +# include "BLI_winstuff.h" +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_report.h" + +#include "BLI_listbase.h" +#include "BLI_math_vector.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "io_alembic.h" + +#include "ABC_alembic.h" + +static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + Main *bmain = CTX_data_main(C); + char filepath[FILE_MAX]; + + if (bmain->name[0] == '\0') { + BLI_strncpy(filepath, "untitled", sizeof(filepath)); + } + else { + BLI_strncpy(filepath, bmain->name, sizeof(filepath)); + } + + BLI_replace_extension(filepath, sizeof(filepath), ".abc"); + RNA_string_set(op->ptr, "filepath", filepath); + } + + WM_event_add_fileselect(C, op); + + return OPERATOR_RUNNING_MODAL; + + UNUSED_VARS(event); +} + +static int wm_alembic_export_exec(bContext *C, wmOperator *op) +{ + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + BKE_report(op->reports, RPT_ERROR, "No filename given"); + return OPERATOR_CANCELLED; + } + + char filename[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filename); + + const struct AlembicExportParams params = { + .frame_start = RNA_int_get(op->ptr, "start"), + .frame_end = RNA_int_get(op->ptr, "end"), + + .frame_step_xform = 1.0 / (double)RNA_int_get(op->ptr, "xsamples"), + .frame_step_shape = 1.0 / (double)RNA_int_get(op->ptr, "gsamples"), + + .shutter_open = RNA_float_get(op->ptr, "sh_open"), + .shutter_close = RNA_float_get(op->ptr, "sh_close"), + + .selected_only = RNA_boolean_get(op->ptr, "selected"), + .uvs = RNA_boolean_get(op->ptr, "uvs"), + .normals = RNA_boolean_get(op->ptr, "normals"), + .vcolors = RNA_boolean_get(op->ptr, "vcolors"), + .apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"), + .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"), + .visible_layers_only = RNA_boolean_get(op->ptr, "visible_layers_only"), + .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"), + .face_sets = RNA_boolean_get(op->ptr, "face_sets"), + .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), + .compression_type = RNA_enum_get(op->ptr, "compression_type"), + .packuv = RNA_boolean_get(op->ptr, "packuv"), + + .global_scale = RNA_float_get(op->ptr, "global_scale"), + }; + + ABC_export(CTX_data_scene(C), C, filename, ¶ms); + + return OPERATOR_FINISHED; +} + +static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) +{ + uiLayout *box; + uiLayout *row; + +#ifdef WITH_ALEMBIC_HDF5 + box = uiLayoutBox(layout); + row = uiLayoutRow(box, false); + uiItemL(row, IFACE_("Archive Options:"), ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "compression_type", 0, NULL, ICON_NONE); +#endif + + box = uiLayoutBox(layout); + row = uiLayoutRow(box, false); + uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "global_scale", 0, NULL, ICON_NONE); + + /* Scene Options */ + box = uiLayoutBox(layout); + row = uiLayoutRow(box, false); + uiItemL(row, IFACE_("Scene Options:"), ICON_SCENE_DATA); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "start", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "end", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "xsamples", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "gsamples", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "sh_open", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "sh_close", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "renderable_only", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "visible_layers_only", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "flatten", 0, NULL, ICON_NONE); + + /* Object Data */ + box = uiLayoutBox(layout); + row = uiLayoutRow(box, false); + uiItemL(row, IFACE_("Object Options:"), ICON_OBJECT_DATA); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "uvs", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "packuv", 0, NULL, ICON_NONE); + uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "uvs")); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "normals", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "vcolors", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "face_sets", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "subdiv_schema", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "apply_subdiv", 0, NULL, ICON_NONE); +} + +static void wm_alembic_export_draw(bContext *UNUSED(C), wmOperator *op) +{ + PointerRNA ptr; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + ui_alembic_export_settings(op->layout, &ptr); +} + +static bool wm_alembic_export_check(bContext *UNUSED(C), wmOperator *op) +{ + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); + + if (!BLI_testextensie(filepath, ".abc")) { + BLI_ensure_extension(filepath, FILE_MAX, ".abc"); + RNA_string_set(op->ptr, "filepath", filepath); + return true; + } + + return false; +} + +void WM_OT_alembic_export(wmOperatorType *ot) +{ + ot->name = "Export Alembic"; + ot->description = "Export current scene in an Alembic archive"; + ot->idname = "WM_OT_alembic_export"; + + ot->invoke = wm_alembic_export_invoke; + ot->exec = wm_alembic_export_exec; + ot->poll = WM_operator_winactive; + ot->ui = wm_alembic_export_draw; + ot->check = wm_alembic_export_check; + + WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC, + FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); + + RNA_def_int(ot->srna, "start", 1, INT_MIN, INT_MAX, + "Start Frame", "Start Frame", INT_MIN, INT_MAX); + + RNA_def_int(ot->srna, "end", 1, INT_MIN, INT_MAX, + "End Frame", "End Frame", INT_MIN, INT_MAX); + + RNA_def_int(ot->srna, "xsamples", 1, 1, 128, + "Transform Samples", "Number of times per frame transformations are sampled", 1, 128); + + RNA_def_int(ot->srna, "gsamples", 1, 1, 128, + "Geometry Samples", "Number of times per frame object data are sampled", 1, 128); + + RNA_def_float(ot->srna, "sh_open", 0.0f, -1.0f, 1.0f, + "Shutter Open", "Time at which the shutter is open", -1.0f, 1.0f); + + RNA_def_float(ot->srna, "sh_close", 1.0f, -1.0f, 1.0f, + "Shutter Close", "Time at which the shutter is closed", -1.0f, 1.0f); + + RNA_def_boolean(ot->srna, "selected", 0, + "Selected Objects Only", "Export only selected objects"); + + RNA_def_boolean(ot->srna, "renderable_only", 1, + "Renderable Objects Only", + "Export only objects marked renderable in the outliner"); + + RNA_def_boolean(ot->srna, "visible_layers_only", 0, + "Visible Layers Only", "Export only objects in visible layers"); + + RNA_def_boolean(ot->srna, "flatten", 0, + "Flatten Hierarchy", + "Do not preserve objects' parent/children relationship"); + + RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Export UVs"); + + RNA_def_boolean(ot->srna, "packuv", 1, "Pack UV Islands", + "Export UVs with packed island"); + + RNA_def_boolean(ot->srna, "normals", 1, "Normals", "Export normals"); + + RNA_def_boolean(ot->srna, "vcolors", 0, "Vertex Colors", "Export vertex colors"); + + RNA_def_boolean(ot->srna, "face_sets", 0, "Face Sets", "Export per face shading group assignments"); + + RNA_def_boolean(ot->srna, "subdiv_schema", 0, + "Use Subdivision Schema", + "Export meshes using Alembic's subdivision schema"); + + RNA_def_boolean(ot->srna, "apply_subdiv", 0, + "Apply Subsurf", "Export subdivision surfaces as meshes"); + + RNA_def_enum(ot->srna, "compression_type", rna_enum_abc_compression_items, + ABC_ARCHIVE_OGAWA, "Compression", ""); + + RNA_def_float(ot->srna, "global_scale", 1.0f, 0.0001f, 1000.0f, "Scale", + "Value by which to enlarge or shrink the objects with respect to the world's origin", + 0.0001f, 1000.0f); +} + +/* ************************************************************************** */ + +/* TODO(kevin): check on de-duplicating all this with code in image_ops.c */ + +typedef struct CacheFrame { + struct CacheFrame *next, *prev; + int framenr; +} CacheFrame; + +static int cmp_frame(const void *a, const void *b) +{ + const CacheFrame *frame_a = a; + const CacheFrame *frame_b = b; + + if (frame_a->framenr < frame_b->framenr) return -1; + if (frame_a->framenr > frame_b->framenr) return 1; + return 0; +} + +static int get_sequence_len(char *filename, int *ofs) +{ + int frame; + int numdigit; + + if (!BLI_path_frame_get(filename, &frame, &numdigit)) { + return 1; + } + + char path[FILE_MAX]; + BLI_split_dir_part(filename, path, FILE_MAX); + + DIR *dir = opendir(path); + + const char *ext = ".abc"; + const char *basename = BLI_path_basename(filename); + const int len = strlen(basename) - (numdigit + strlen(ext)); + + ListBase frames; + BLI_listbase_clear(&frames); + + struct dirent *fname; + while ((fname = readdir(dir)) != NULL) { + /* do we have the right extension? */ + if (!strstr(fname->d_name, ext)) { + continue; + } + + if (!STREQLEN(basename, fname->d_name, len)) { + continue; + } + + CacheFrame *cache_frame = MEM_callocN(sizeof(CacheFrame), "abc_frame"); + + BLI_path_frame_get(fname->d_name, &cache_frame->framenr, &numdigit); + + BLI_addtail(&frames, cache_frame); + } + + closedir(dir); + + BLI_listbase_sort(&frames, cmp_frame); + + CacheFrame *cache_frame = frames.first; + + if (cache_frame) { + int frame_curr = cache_frame->framenr; + (*ofs) = frame_curr; + + while (cache_frame && (cache_frame->framenr == frame_curr)) { + ++frame_curr; + cache_frame = cache_frame->next; + } + + BLI_freelistN(&frames); + + return frame_curr - (*ofs); + } + + return 1; +} + +/* ************************************************************************** */ + +static void ui_alembic_import_settings(uiLayout *layout, PointerRNA *imfptr) +{ + uiLayout *box = uiLayoutBox(layout); + uiLayout *row = uiLayoutRow(box, false); + uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "scale", 0, NULL, ICON_NONE); + + box = uiLayoutBox(layout); + row = uiLayoutRow(box, false); + uiItemL(row, IFACE_("Options:"), ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "set_frame_range", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "is_sequence", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "validate_meshes", 0, NULL, ICON_NONE); +} + +static void wm_alembic_import_draw(bContext *UNUSED(C), wmOperator *op) +{ + PointerRNA ptr; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + ui_alembic_import_settings(op->layout, &ptr); +} + +static int wm_alembic_import_exec(bContext *C, wmOperator *op) +{ + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + BKE_report(op->reports, RPT_ERROR, "No filename given"); + return OPERATOR_CANCELLED; + } + + char filename[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filename); + + const float scale = RNA_float_get(op->ptr, "scale"); + const bool is_sequence = RNA_boolean_get(op->ptr, "is_sequence"); + const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range"); + const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes"); + + int offset = 0; + int sequence_len = 1; + + if (is_sequence) { + sequence_len = get_sequence_len(filename, &offset); + } + + ABC_import(C, filename, scale, is_sequence, set_frame_range, sequence_len, offset, validate_meshes); + + return OPERATOR_FINISHED; +} + +void WM_OT_alembic_import(wmOperatorType *ot) +{ + ot->name = "Import Alembic"; + ot->description = "Load an Alembic archive"; + ot->idname = "WM_OT_alembic_import"; + + ot->invoke = WM_operator_filesel; + ot->exec = wm_alembic_import_exec; + ot->poll = WM_operator_winactive; + ot->ui = wm_alembic_import_draw; + + WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC, + FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); + + RNA_def_float(ot->srna, "scale", 1.0f, 0.0001f, 1000.0f, "Scale", + "Value by which to enlarge or shrink the objects with respect to the world's origin", + 0.0001f, 1000.0f); + + RNA_def_boolean(ot->srna, "set_frame_range", true, + "Set Frame Range", + "If checked, update scene's start and end frame to match those of the Alembic archive"); + + RNA_def_boolean(ot->srna, "validate_meshes", 0, + "Validate Meshes", "Check imported mesh objects for invalid data (slow)"); + + RNA_def_boolean(ot->srna, "is_sequence", false, "Is Sequence", + "Set to true if the cache is split into separate files"); +} + +#endif diff --git a/source/blender/editors/io/io_alembic.h b/source/blender/editors/io/io_alembic.h new file mode 100644 index 00000000000..5eefabef4be --- /dev/null +++ b/source/blender/editors/io/io_alembic.h @@ -0,0 +1,37 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef __IO_ALEMBIC_H__ +#define __IO_ALEMBIC_H__ + +/** \file blender/editors/io/io_alembic.h + * \ingroup editor/io + */ + +struct wmOperatorType; + +void WM_OT_alembic_export(struct wmOperatorType *ot); +void WM_OT_alembic_import(struct wmOperatorType *ot); + +#endif /* __IO_ALEMBIC_H__ */ diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c new file mode 100644 index 00000000000..c5eea94f5e1 --- /dev/null +++ b/source/blender/editors/io/io_cache.c @@ -0,0 +1,163 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_cachefile_types.h" +#include "DNA_space_types.h" + +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" + +#include "BKE_cachefile.h" +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_report.h" + +#include "RNA_access.h" + +#include "UI_interface.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "io_cache.h" + +static void cachefile_init(bContext *C, wmOperator *op) +{ + PropertyPointerRNA *pprop; + + op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA"); + UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop); +} + +static int cachefile_open_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + char filepath[FILE_MAX]; + BLI_strncpy(filepath, G.main->name, sizeof(filepath)); + BLI_replace_extension(filepath, sizeof(filepath), ".abc"); + RNA_string_set(op->ptr, "filepath", filepath); + } + + cachefile_init(C, op); + + WM_event_add_fileselect(C, op); + + return OPERATOR_RUNNING_MODAL; + + UNUSED_VARS(event); +} + +static void open_cancel(bContext *UNUSED(C), wmOperator *op) +{ + MEM_freeN(op->customdata); + op->customdata = NULL; +} + +static int cachefile_open_exec(bContext *C, wmOperator *op) +{ + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + BKE_report(op->reports, RPT_ERROR, "No filename given"); + return OPERATOR_CANCELLED; + } + + char filename[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filename); + + Main *bmain = CTX_data_main(C); + + CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename)); + BLI_strncpy(cache_file->filepath, filename, FILE_MAX); + BKE_cachefile_reload(bmain, cache_file); + + /* hook into UI */ + PropertyPointerRNA *pprop = op->customdata; + + if (pprop->prop) { + /* when creating new ID blocks, use is already 1, but RNA + * pointer se also increases user, so this compensates it */ + id_us_min(&cache_file->id); + + PointerRNA idptr; + RNA_id_pointer_create(&cache_file->id, &idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); + RNA_property_update(C, &pprop->ptr, pprop->prop); + } + + MEM_freeN(op->customdata); + + return OPERATOR_FINISHED; +} + +void CACHEFILE_OT_open(wmOperatorType *ot) +{ + ot->name = "Open Cache File"; + ot->description = "Load a cache file"; + ot->idname = "CACHEFILE_OT_open"; + + ot->invoke = cachefile_open_invoke; + ot->exec = cachefile_open_exec; + ot->cancel = open_cancel; + + WM_operator_properties_filesel(ot, FILE_TYPE_ALEMBIC | FILE_TYPE_FOLDER, + FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); +} + +/* ***************************** Reload Operator **************************** */ + +static int cachefile_reload_exec(bContext *C, wmOperator *op) +{ + CacheFile *cache_file = CTX_data_edit_cachefile(C); + + if (!cache_file) { + return OPERATOR_CANCELLED; + } + + Main *bmain = CTX_data_main(C); + + BLI_listbase_clear(&cache_file->object_paths); + BKE_cachefile_reload(bmain, cache_file); + + return OPERATOR_FINISHED; + + UNUSED_VARS(op); +} + +void CACHEFILE_OT_reload(wmOperatorType *ot) +{ + ot->name = "Refresh Archive"; + ot->description = "Update objects paths list with new data from the archive"; + ot->idname = "CACHEFILE_OT_reload"; + + /* api callbacks */ + ot->exec = cachefile_reload_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/io/io_cache.h b/source/blender/editors/io/io_cache.h new file mode 100644 index 00000000000..ea270c2aba1 --- /dev/null +++ b/source/blender/editors/io/io_cache.h @@ -0,0 +1,37 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef __IO_CACHE_H__ +#define __IO_CACHE_H__ + +/** \file blender/editors/io/io_cache.h + * \ingroup editor/io + */ + +struct wmOperatorType; + +void CACHEFILE_OT_open(struct wmOperatorType *ot); +void CACHEFILE_OT_reload(struct wmOperatorType *ot); + +#endif /* __IO_CACHE_H__ */ diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index d62651cef81..8659100df87 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -280,6 +280,20 @@ static void wm_collada_export_draw(bContext *UNUSED(C), wmOperator *op) uiCollada_exportSettings(op->layout, &ptr); } +static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op) +{ + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); + + if (!BLI_testextensie(filepath, ".dae")) { + BLI_ensure_extension(filepath, FILE_MAX, ".dae"); + RNA_string_set(op->ptr, "filepath", filepath); + return true; + } + + return false; +} + void WM_OT_collada_export(wmOperatorType *ot) { static EnumPropertyItem prop_bc_export_mesh_type[] = { @@ -302,6 +316,7 @@ void WM_OT_collada_export(wmOperatorType *ot) ot->invoke = wm_collada_export_invoke; ot->exec = wm_collada_export_exec; ot->poll = WM_operator_winactive; + ot->check = wm_collada_export_check; ot->flag |= OPTYPE_PRESET; diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c index a70a51a60be..d1e933517a9 100644 --- a/source/blender/editors/io/io_ops.c +++ b/source/blender/editors/io/io_ops.c @@ -30,11 +30,18 @@ #include "io_ops.h" /* own include */ +#include "WM_api.h" + #ifdef WITH_COLLADA # include "io_collada.h" -# include "WM_api.h" #endif +#ifdef WITH_ALEMBIC +# include "io_alembic.h" +#endif + +#include "io_cache.h" + void ED_operatortypes_io(void) { #ifdef WITH_COLLADA @@ -42,4 +49,11 @@ void ED_operatortypes_io(void) WM_operatortype_append(WM_OT_collada_export); WM_operatortype_append(WM_OT_collada_import); #endif +#ifdef WITH_ALEMBIC + WM_operatortype_append(WM_OT_alembic_import); + WM_operatortype_append(WM_OT_alembic_export); +#endif + + WM_operatortype_append(CACHEFILE_OT_open); + WM_operatortype_append(CACHEFILE_OT_reload); } diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 302ca407add..a81add7a86e 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -145,6 +145,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) opdata->em = em; opdata->is_modal = is_modal; opdata->value_mode = OFFSET_VALUE; + opdata->segments = (float) RNA_int_get(op->ptr, "segments"); pixels_per_inch = U.dpi * U.pixelsize; for (i = 0; i < NUM_VALUE_KINDS; i++) { diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 281a8b2a02d..de93211bec4 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -439,7 +439,7 @@ static void bm_face_split_by_edges_island_connect( LinkNode *e_link, const int e_link_len, MemArena *mem_arena_edgenet) { - BMEdge **edge_arr = BLI_memarena_alloc(mem_arena_edgenet, sizeof(BMEdge **) * e_link_len); + BMEdge **edge_arr = BLI_memarena_alloc(mem_arena_edgenet, sizeof(*edge_arr) * e_link_len); int edge_arr_len = 0; while (e_link) { diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 1a14fad8650..7e31deba2c7 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3080,7 +3080,7 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag) * \note This could be used for split-by-material for non mesh types. * \note This could take material data from another object or args. */ -static void mesh_separate_material_assign_mat_nr(Object *ob, const short mat_nr) +static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const short mat_nr) { ID *obdata = ob->data; @@ -3116,18 +3116,20 @@ static void mesh_separate_material_assign_mat_nr(Object *ob, const short mat_nr) ma_obdata = NULL; } - BKE_material_clear_id(obdata, true); - BKE_material_resize_object(ob, 1, true); - BKE_material_resize_id(obdata, 1, true); + BKE_material_clear_id(bmain, obdata, true); + BKE_material_resize_object(bmain, ob, 1, true); + BKE_material_resize_id(bmain, obdata, 1, true); ob->mat[0] = ma_ob; + id_us_plus((ID *)ma_ob); ob->matbits[0] = matbit; (*matarar)[0] = ma_obdata; + id_us_plus((ID *)ma_obdata); } else { - BKE_material_clear_id(obdata, true); - BKE_material_resize_object(ob, 0, true); - BKE_material_resize_id(obdata, 0, true); + BKE_material_clear_id(bmain, obdata, true); + BKE_material_resize_object(bmain, ob, 0, true); + BKE_material_resize_id(bmain, obdata, 0, true); } } @@ -3162,7 +3164,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM /* leave the current object with some materials */ if (tot == bm_old->totface) { - mesh_separate_material_assign_mat_nr(base_old->object, mat_nr); + mesh_separate_material_assign_mat_nr(bmain, base_old->object, mat_nr); /* since we're in editmode, must set faces here */ BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) { @@ -3174,7 +3176,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM /* Move selection into a separate object */ base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old); if (base_new) { - mesh_separate_material_assign_mat_nr(base_new->object, mat_nr); + mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr); } result |= (base_new != NULL); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 57e08d36f85..0cb91fd0269 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -999,7 +999,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op) Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer); ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; - id_lib_extern(&group->id); + id_us_plus(&group->id); /* works without this except if you try render right after, see: 22027 */ DAG_relations_tag_update(bmain); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index db8a4c1960f..59d78f13ccb 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -416,6 +416,13 @@ static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL)) con->flag |= CONSTRAINT_DISABLE; } + else if (con->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) { + bTransformCacheConstraint *data = con->data; + + if ((data->cache_file == NULL) || (data->object_path[0] == '\0')) { + con->flag |= CONSTRAINT_DISABLE; + } + } /* Check targets for constraints */ if (check_targets && cti && cti->get_constraint_targets) { diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 3dc7d8ebd4b..111afcdc7a7 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -910,7 +910,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) base->object->dup_group = ob->dup_group; if (ob->dup_group) - id_lib_extern(&ob->dup_group->id); + id_us_plus(&ob->dup_group->id); } else if (event == 7) { /* mass */ base->object->mass = ob->mass; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index ff2accf9d82..82c6a14eb7f 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1382,7 +1382,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) /* upper byte is used for local view */ local = base->lay & 0xFF000000; base->lay = lay + local; - base->object->lay = lay; + base->object->lay = base->lay; /* if (base->object->type == OB_LAMP) is_lamp = true; */ } CTX_DATA_END; @@ -1609,7 +1609,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) case MAKE_LINKS_DUPLIGROUP: ob_dst->dup_group = ob_src->dup_group; if (ob_dst->dup_group) { - id_lib_extern(&ob_dst->dup_group->id); + id_us_plus(&ob_dst->dup_group->id); ob_dst->transflag |= OB_DUPLIGROUP; } break; @@ -1764,10 +1764,13 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in /* copy already clears */ } /* remap gpencil parenting */ - bGPdata *gpd = scene->gpd; - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->parent == ob) { - gpl->parent = obn; + + if (scene->gpd) { + bGPdata *gpd = scene->gpd; + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->parent == ob) { + gpl->parent = obn; + } } } @@ -2103,6 +2106,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo } BKE_main_id_clear_newpoins(bmain); + DAG_relations_tag_update(bmain); } /******************************* Make Local ***********************************/ diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index b4f3426677a..ddbf59b2cf7 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -526,7 +526,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true); } } - + return sce; } @@ -863,8 +863,6 @@ static void shader_preview_free(void *customdata) /* get rid of copied world */ BLI_remlink(&pr_main->world, sp->worldcopy); - /* T32865 - we need to unlink the texture copies, unlike for materials */ - BKE_libblock_relink_ex(pr_main, sp->worldcopy, NULL, NULL, true); BKE_world_free(sp->worldcopy); properties = IDP_GetProperties((ID *)sp->worldcopy, false); @@ -881,7 +879,6 @@ static void shader_preview_free(void *customdata) /* get rid of copied lamp */ BLI_remlink(&pr_main->lamp, sp->lampcopy); - BKE_libblock_relink_ex(pr_main, sp->lampcopy, NULL, NULL, true); BKE_lamp_free(sp->lampcopy); properties = IDP_GetProperties((ID *)sp->lampcopy, false); diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 22d95d77d55..34c51914027 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -117,7 +117,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { const unsigned int lay = context_layers(sc, scene, sa); - int visible_objects = CTX_data_equals(member, "visible_objects"); + const bool visible_objects = CTX_data_equals(member, "visible_objects"); for (base = scene->base.first; base; base = base->next) { if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) { @@ -132,7 +132,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { const unsigned int lay = context_layers(sc, scene, sa); - int selectable_objects = CTX_data_equals(member, "selectable_objects"); + const bool selectable_objects = CTX_data_equals(member, "selectable_objects"); for (base = scene->base.first; base; base = base->next) { if (base->lay & lay) { @@ -149,7 +149,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { const unsigned int lay = context_layers(sc, scene, sa); - int selected_objects = CTX_data_equals(member, "selected_objects"); + const bool selected_objects = CTX_data_equals(member, "selected_objects"); for (base = scene->base.first; base; base = base->next) { if ((base->flag & SELECT) && (base->lay & lay)) { @@ -164,7 +164,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { const unsigned int lay = context_layers(sc, scene, sa); - int selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); + const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); for (base = scene->base.first; base; base = base->next) { if ((base->flag & SELECT) && (base->lay & lay)) { @@ -183,7 +183,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "editable_objects") || CTX_data_equals(member, "editable_bases")) { const unsigned int lay = context_layers(sc, scene, sa); - int editable_objects = CTX_data_equals(member, "editable_objects"); + const bool editable_objects = CTX_data_equals(member, "editable_objects"); /* Visible + Editable, but not necessarily selected */ for (base = scene->base.first; base; base = base->next) { @@ -202,7 +202,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "visible_bones") || CTX_data_equals(member, "editable_bones")) { bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL; EditBone *ebone, *flipbone = NULL; - int editable_bones = CTX_data_equals(member, "editable_bones"); + const bool editable_bones = CTX_data_equals(member, "editable_bones"); if (arm && arm->edbo) { /* Attention: X-Axis Mirroring is also handled here... */ @@ -244,7 +244,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "selected_bones") || CTX_data_equals(member, "selected_editable_bones")) { bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL; EditBone *ebone, *flipbone = NULL; - int selected_editable_bones = CTX_data_equals(member, "selected_editable_bones"); + const bool selected_editable_bones = CTX_data_equals(member, "selected_editable_bones"); if (arm && arm->edbo) { /* Attention: X-Axis Mirroring is also handled here... */ @@ -467,7 +467,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); if (gpd) { - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); if (gpl) { CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl); @@ -480,7 +480,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); if (gpd) { - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); if (palette) { CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilPalette, palette); @@ -493,10 +493,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); if (gpd) { - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); if (palette) { - bGPDpalettecolor *palcolor = gpencil_palettecolor_getactive(palette); + bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); if (palcolor) { CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilPaletteColor, palcolor); return 1; @@ -506,7 +506,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "active_gpencil_brush")) { /* XXX: see comment for gpencil_data case... */ - bGPDbrush *brush = gpencil_brush_getactive(scene->toolsettings); + bGPDbrush *brush = BKE_gpencil_brush_getactive(scene->toolsettings); if (brush) { CTX_data_pointer_set(result, NULL, &RNA_GPencilBrush, brush); @@ -518,7 +518,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); if (gpd) { - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); if (gpl) { CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 1431958501d..05270dbfa09 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -88,7 +88,6 @@ typedef struct PaintStroke { /* Cached values */ ViewContext vc; - bglMats mats; Brush *brush; UnifiedPaintSettings *ups; @@ -675,8 +674,6 @@ PaintStroke *paint_stroke_new(bContext *C, float zoomx, zoomy; view3d_set_viewcontext(C, &stroke->vc); - if (stroke->vc.v3d) - view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats); stroke->get_location = get_location; stroke->test_start = test_start; @@ -1102,12 +1099,14 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure); paint_stroke_sample_average(stroke, &sample_average); +#ifdef WITH_INPUT_NDOF /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously! * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it * since the 2D deltas are zero -- code in this file needs to be updated to use the * post-NDOF_MOTION MOUSEMOVE */ if (event->type == NDOF_MOTION) return OPERATOR_PASS_THROUGH; +#endif /* one time initialization */ if (!stroke->stroke_init) { diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 03f2e146b7d..ac3fc769ea1 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -348,10 +348,10 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) BLI_path_abs(filename, bmain->name); if (split) - result = AUD_mixdown_per_channel(scene->sound_scene, SFRA * specs.rate / FPS, (EFRA - SFRA) * specs.rate / FPS, + result = AUD_mixdown_per_channel(scene->sound_scene, SFRA * specs.rate / FPS, (EFRA - SFRA + 1) * specs.rate / FPS, accuracy, filename, specs, container, codec, bitrate); else - result = AUD_mixdown(scene->sound_scene, SFRA * specs.rate / FPS, (EFRA - SFRA) * specs.rate / FPS, + result = AUD_mixdown(scene->sound_scene, SFRA * specs.rate / FPS, (EFRA - SFRA + 1) * specs.rate / FPS, accuracy, filename, specs, container, codec, bitrate); if (result) { diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 55b087c40e7..f8db35e2311 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -750,7 +750,7 @@ static void insert_gpencil_keys(bAnimContext *ac, short mode) /* insert gp frames */ for (ale = anim_data.first; ale; ale = ale->next) { bGPDlayer *gpl = (bGPDlayer *)ale->data; - gpencil_layer_getframe(gpl, CFRA, add_frame_mode); + BKE_gpencil_layer_getframe(gpl, CFRA, add_frame_mode); } ANIM_animdata_update(ac, &anim_data); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index a261202b690..718a4fd3c38 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -240,7 +240,9 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* auto-set range */ WM_keymap_add_item(keymap, "ACTION_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "ACTION_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "ACTION_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "ACTION_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_view_frame", PAD0, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 2a5d959bb84..14393c6968b 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -106,7 +106,9 @@ void CLIP_OT_change_frame(wmOperatorType *ot); void CLIP_OT_rebuild_proxy(struct wmOperatorType *ot); void CLIP_OT_mode_set(struct wmOperatorType *ot); +#ifdef WITH_INPUT_NDOF void CLIP_OT_view_ndof(struct wmOperatorType *ot); +#endif void CLIP_OT_prefetch(struct wmOperatorType *ot); @@ -185,7 +187,10 @@ void CLIP_OT_detect_features(struct wmOperatorType *ot); void CLIP_OT_stabilize_2d_add(struct wmOperatorType *ot); void CLIP_OT_stabilize_2d_remove(struct wmOperatorType *ot); void CLIP_OT_stabilize_2d_select(struct wmOperatorType *ot); -void CLIP_OT_stabilize_2d_set_rotation(struct wmOperatorType *ot); + +void CLIP_OT_stabilize_2d_rotation_add(struct wmOperatorType *ot); +void CLIP_OT_stabilize_2d_rotation_remove(struct wmOperatorType *ot); +void CLIP_OT_stabilize_2d_rotation_select(struct wmOperatorType *ot); void CLIP_OT_clean_tracks(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 83876ae2669..6778a0b1805 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1405,6 +1405,7 @@ void CLIP_OT_mode_set(wmOperatorType *ot) RNA_def_enum(ot->srna, "mode", rna_enum_clip_editor_mode_items, SC_MODE_TRACKING, "Mode", ""); } +#ifdef WITH_INPUT_NDOF /********************** NDOF operator *********************/ /* Combined pan/zoom from a 3D mouse device. @@ -1451,6 +1452,7 @@ void CLIP_OT_view_ndof(wmOperatorType *ot) ot->invoke = clip_view_ndof_invoke; ot->poll = ED_space_clip_view_clip_poll; } +#endif /* WITH_INPUT_NDOF */ /********************** Prefetch operator *********************/ diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 5964e9a898b..547c2fba66f 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -175,21 +175,14 @@ void clip_graph_tracking_iterate(SpaceClip *sc, bool selected_only, bool include void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) { MovieTracking *tracking = &clip->tracking; - MovieTrackingStabilization *stab = &tracking->stabilization; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); - bool has_bundle = false, update_stab = false; + bool has_bundle = false; char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2]; if (track == act_track) tracking->act_track = NULL; - if (track == stab->rot_track) { - stab->rot_track = NULL; - - update_stab = true; - } - /* handle reconstruction display in 3d viewport */ if (track->flag & TRACK_HAS_BUNDLE) has_bundle = true; @@ -207,8 +200,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); - if (update_stab) { - tracking->stabilization.ok = false; + if (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT)) { WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 396d71f0a20..05e69968e35 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -225,18 +225,6 @@ static void clip_scopes_check_gpencil_change(ScrArea *sa) } } -static void clip_stabilization_tag_refresh(ScrArea *sa) -{ - SpaceClip *sc = (SpaceClip *) sa->spacedata.first; - MovieClip *clip = ED_space_clip_get_clip(sc); - - if (clip) { - MovieTrackingStabilization *stab = &clip->tracking.stabilization; - - stab->ok = false; - } -} - /* ******************** default callbacks for clip space ***************** */ static SpaceLink *clip_new(const bContext *C) @@ -368,7 +356,6 @@ static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) case NA_REMOVED: case NA_EDITED: case NA_EVALUATED: - clip_stabilization_tag_refresh(sa); /* fall-through */ case NA_SELECTED: @@ -412,7 +399,6 @@ static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) case NC_SPACE: if (wmn->data == ND_SPACE_CLIP) { clip_scopes_tag_refresh(sa); - clip_stabilization_tag_refresh(sa); ED_area_tag_redraw(sa); } break; @@ -443,7 +429,9 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_change_frame); WM_operatortype_append(CLIP_OT_rebuild_proxy); WM_operatortype_append(CLIP_OT_mode_set); +#ifdef WITH_INPUT_NDOF WM_operatortype_append(CLIP_OT_view_ndof); +#endif WM_operatortype_append(CLIP_OT_prefetch); WM_operatortype_append(CLIP_OT_set_scene_frames); WM_operatortype_append(CLIP_OT_cursor_set); @@ -457,7 +445,7 @@ static void clip_operatortypes(void) /* navigation */ WM_operatortype_append(CLIP_OT_frame_jump); - /* foorage */ + /* set optical center to frame center */ WM_operatortype_append(CLIP_OT_set_center_principal); /* selection */ @@ -505,7 +493,9 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_stabilize_2d_add); WM_operatortype_append(CLIP_OT_stabilize_2d_remove); WM_operatortype_append(CLIP_OT_stabilize_2d_select); - WM_operatortype_append(CLIP_OT_stabilize_2d_set_rotation); + WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_add); + WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_remove); + WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_select); /* clean-up */ WM_operatortype_append(CLIP_OT_clear_track_path); @@ -634,8 +624,10 @@ static void clip_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CLIP_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "CLIP_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "CLIP_OT_view_ndof", NDOF_MOTION, 0, 0, 0); +#endif /* jump to special frame */ kmi = WM_keymap_add_item(keymap, "CLIP_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); @@ -791,7 +783,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf) /* view */ WM_keymap_add_item(keymap, "CLIP_OT_graph_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "CLIP_OT_graph_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "CLIP_OT_graph_center_current_frame", PADPERIOD, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", LKEY, KM_PRESS, 0, 0); @@ -822,7 +816,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "extend", true); /* toggle */ WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif } const char *clip_context_dir[] = {"edit_movieclip", "edit_mask", NULL}; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 61bfa5b315b..d28cbe5fb1d 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1509,8 +1509,10 @@ static int join_tracks_exec(bContext *C, wmOperator *op) SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; + MovieTrackingStabilization *stab = &tracking->stabilization; ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); + bool update_stabilization = false; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); if (act_track == NULL) { @@ -1528,8 +1530,23 @@ static int join_tracks_exec(bContext *C, wmOperator *op) if (TRACK_VIEW_SELECTED(sc, track) && track != act_track) { BKE_tracking_tracks_join(tracking, act_track, track); - if (tracking->stabilization.rot_track == track) { - tracking->stabilization.rot_track = act_track; + if (track->flag & TRACK_USE_2D_STAB) { + update_stabilization = true; + if ((act_track->flag & TRACK_USE_2D_STAB) == 0) { + act_track->flag |= TRACK_USE_2D_STAB; + } else { + stab->tot_track--; + } + BLI_assert(0 <= stab->tot_track); + } + if (track->flag & TRACK_USE_2D_STAB_ROT) { + update_stabilization = true; + if ((act_track->flag & TRACK_USE_2D_STAB_ROT) == 0) { + act_track->flag |= TRACK_USE_2D_STAB_ROT; + } else { + stab->tot_rot_track--; + } + BLI_assert(0 <= stab->tot_rot_track); } for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; @@ -1551,6 +1568,10 @@ static int join_tracks_exec(bContext *C, wmOperator *op) } } + if (update_stabilization) { + WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); + } + GSetIterator gs_iter; int framenr = ED_space_clip_get_clip_frame_number(sc); GSET_ITER (gs_iter, point_tracks) { diff --git a/source/blender/editors/space_clip/tracking_ops_stabilize.c b/source/blender/editors/space_clip/tracking_ops_stabilize.c index 8d6173e1cea..35b1aead343 100644 --- a/source/blender/editors/space_clip/tracking_ops_stabilize.c +++ b/source/blender/editors/space_clip/tracking_ops_stabilize.c @@ -84,7 +84,6 @@ static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op)) } if (update) { - stab->ok = 0; DAG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -96,7 +95,7 @@ void CLIP_OT_stabilize_2d_add(wmOperatorType *ot) { /* identifiers */ ot->name = "Add Stabilization Tracks"; - ot->description = "Add selected tracks to 2D stabilization tool"; + ot->description = "Add selected tracks to 2D translation stabilization"; ot->idname = "CLIP_OT_stabilize_2d_add"; /* api callbacks */ @@ -139,7 +138,6 @@ static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op)) } if (update) { - stab->ok = 0; DAG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -151,7 +149,7 @@ void CLIP_OT_stabilize_2d_remove(wmOperatorType *ot) { /* identifiers */ ot->name = "Remove Stabilization Track"; - ot->description = "Remove selected track from stabilization"; + ot->description = "Remove selected track from translation stabilization"; ot->idname = "CLIP_OT_stabilize_2d_remove"; /* api callbacks */ @@ -193,7 +191,7 @@ void CLIP_OT_stabilize_2d_select(wmOperatorType *ot) { /* identifiers */ ot->name = "Select Stabilization Tracks"; - ot->description = "Select tracks which are used for stabilization"; + ot->description = "Select tracks which are used for translation stabilization"; ot->idname = "CLIP_OT_stabilize_2d_select"; /* api callbacks */ @@ -204,20 +202,85 @@ void CLIP_OT_stabilize_2d_select(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************** set 2d stabilization rotation track operator ****************/ +/********************** add 2d stabilization tracks for rotation operator ****************/ -static int stabilize_2d_set_rotation_exec(bContext *C, wmOperator *UNUSED(op)) +static int stabilize_2d_rotation_add_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; - MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); + MovieTrackingStabilization *stab = &tracking->stabilization; + + bool update = false; + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + if (TRACK_VIEW_SELECTED(sc, track) && + (track->flag & TRACK_USE_2D_STAB_ROT) == 0) + { + track->flag |= TRACK_USE_2D_STAB_ROT; + stab->tot_rot_track++; + update = true; + } + } + + if (update) { + DAG_id_tag_update(&clip->id, 0); + WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); + } + + return OPERATOR_FINISHED; +} + +void CLIP_OT_stabilize_2d_rotation_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Stabilization Rotation Tracks"; + ot->description = "Add selected tracks to 2D rotation stabilization"; + ot->idname = "CLIP_OT_stabilize_2d_rotation_add"; + + /* api callbacks */ + ot->exec = stabilize_2d_rotation_add_exec; + ot->poll = stabilize_2d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/********************** remove 2d stabilization tracks for rotation operator *************/ + +static int stabilize_2d_rotation_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTracking *tracking = &clip->tracking; + MovieTrackingStabilization *stab = &tracking->stabilization; + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); + int a = 0; + bool update = false; - if (act_track != NULL) { - MovieTrackingStabilization *stab = &tracking->stabilization; - stab->rot_track = act_track; - stab->ok = 0; + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + if (track->flag & TRACK_USE_2D_STAB_ROT) { + if (a == stab->act_rot_track) { + track->flag &= ~TRACK_USE_2D_STAB_ROT; + stab->act_rot_track--; + stab->tot_rot_track--; + if (stab->act_rot_track < 0) { + stab->act_rot_track = 0; + } + update = true; + break; + } + a++; + } + } + if (update) { DAG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -225,18 +288,60 @@ static int stabilize_2d_set_rotation_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -void CLIP_OT_stabilize_2d_set_rotation(wmOperatorType *ot) +void CLIP_OT_stabilize_2d_rotation_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Stabilization Rotation Track"; + ot->description = "Remove selected track from rotation stabilization"; + ot->idname = "CLIP_OT_stabilize_2d_rotation_remove"; + + /* api callbacks */ + ot->exec = stabilize_2d_rotation_remove_exec; + ot->poll = stabilize_2d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/********************** select 2d stabilization rotation tracks operator *****************/ + +static int stabilize_2d_rotation_select_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTracking *tracking = &clip->tracking; + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); + bool update = false; + + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + if (track->flag & TRACK_USE_2D_STAB_ROT) { + BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT); + update = true; + } + } + + if (update) { + WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip); + } + + return OPERATOR_FINISHED; +} + +void CLIP_OT_stabilize_2d_rotation_select(wmOperatorType *ot) { /* identifiers */ - ot->name = "Set Rotation Track"; - ot->description = "Use active track to compensate rotation when " - "doing 2D stabilization"; - ot->idname = "CLIP_OT_stabilize_2d_set_rotation"; + ot->name = "Select Stabilization Rotation Tracks"; + ot->description = "Select tracks which are used for rotation stabilization"; + ot->idname = "CLIP_OT_stabilize_2d_rotation_select"; /* api callbacks */ - ot->exec = stabilize_2d_set_rotation_exec; + ot->exec = stabilize_2d_rotation_select_exec; ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index a55b18a2212..71e38f72a7a 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -128,7 +128,6 @@ void file_panels_register(struct ARegionType *art); /* file_utils.c */ void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds); -bool file_is_dir(struct SpaceFile *sfile, const char *path); #endif /* __FILE_INTERN_H__ */ diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index c42ff120102..9f5e98d2431 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -1894,7 +1894,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN file_expand_directory(C); /* special case, user may have pasted a filepath into the directory */ - if (!file_is_dir(sfile, sfile->params->dir)) { + if (!filelist_is_dir(sfile->files, sfile->params->dir)) { char tdir[FILE_MAX_LIBEXTRA]; char *group, *name; @@ -1920,7 +1920,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN BLI_cleanup_dir(G.main->name, sfile->params->dir); - if (file_is_dir(sfile, sfile->params->dir)) { + if (filelist_is_dir(sfile->files, sfile->params->dir)) { /* if directory exists, enter it immediately */ ED_file_change_dir(C); @@ -1993,7 +1993,7 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg BLI_join_dirfile(filepath, sizeof(sfile->params->dir), sfile->params->dir, sfile->params->file); /* if directory, open it and empty filename field */ - if (file_is_dir(sfile, filepath)) { + if (filelist_is_dir(sfile->files, filepath)) { BLI_cleanup_dir(G.main->name, filepath); BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir)); sfile->params->file[0] = '\0'; diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c index f19e301064d..c1caf5ae8ac 100644 --- a/source/blender/editors/space_file/file_utils.c +++ b/source/blender/editors/space_file/file_utils.c @@ -48,17 +48,3 @@ void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, r BLI_rcti_init(r_bounds, xmin, xmin + layout->tile_w + layout->tile_border_x, ymax - layout->tile_h - layout->tile_border_y, ymax); } - -/* Cannot directly use BLI_is_dir in libloading context... */ -bool file_is_dir(struct SpaceFile *sfile, const char *path) -{ - if (sfile->params->type == FILE_LOADLIB) { - char tdir[FILE_MAX_LIBEXTRA]; - char *name; - if (BLO_library_path_explode(sfile->params->dir, tdir, NULL, &name) && BLI_is_file(tdir)) { - /* .blend file itself and group are considered as directories, not final datablock names. */ - return name ? false : true; - } - } - return BLI_is_dir(path); -} diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 5e9eb1f9207..14719322bf7 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -309,8 +309,9 @@ typedef struct FileList { struct BlendHandle *libfiledata; - /* Set given path as root directory, may change given string in place to a valid value. */ - void (*checkdirf)(struct FileList *, char *); + /* Set given path as root directory, if last bool is true may change given string in place to a valid value. + * Returns True if valid dir. */ + bool (*checkdirf)(struct FileList *, char *, const bool); /* Fill filelist (to be called by read job). */ void (*read_jobf)(struct FileList *, const char *, short *, short *, float *, ThreadMutex *); @@ -920,6 +921,8 @@ static int filelist_geticon_ex( return ICON_FILE_BLANK; else if (typeflag & FILE_TYPE_COLLADA) return ICON_FILE_BLANK; + else if (typeflag & FILE_TYPE_ALEMBIC) + return ICON_FILE_BLANK; else if (typeflag & FILE_TYPE_TEXT) return ICON_FILE_TEXT; else if (typeflag & FILE_TYPE_BLENDERLIB) { @@ -940,24 +943,37 @@ int filelist_geticon(struct FileList *filelist, const int index, const bool is_m /* ********** Main ********** */ -static void filelist_checkdir_dir(struct FileList *UNUSED(filelist), char *r_dir) +static bool filelist_checkdir_dir(struct FileList *UNUSED(filelist), char *r_dir, const bool do_change) { - BLI_make_exist(r_dir); + if (do_change) { + BLI_make_exist(r_dir); + return true; + } + else { + return BLI_is_dir(r_dir); + } } -static void filelist_checkdir_lib(struct FileList *UNUSED(filelist), char *r_dir) +static bool filelist_checkdir_lib(struct FileList *UNUSED(filelist), char *r_dir, const bool do_change) { - char dir[FILE_MAX_LIBEXTRA]; - if (!BLO_library_path_explode(r_dir, dir, NULL, NULL)) { + char tdir[FILE_MAX_LIBEXTRA]; + char *name; + + const bool is_valid = (BLI_is_dir(r_dir) || + (BLO_library_path_explode(r_dir, tdir, NULL, &name) && BLI_is_file(tdir) && !name)); + + if (do_change && !is_valid) { /* if not a valid library, we need it to be a valid directory! */ BLI_make_exist(r_dir); + return true; } + return is_valid; } -static void filelist_checkdir_main(struct FileList *filelist, char *r_dir) +static bool filelist_checkdir_main(struct FileList *filelist, char *r_dir, const bool do_change) { /* TODO */ - filelist_checkdir_lib(filelist, r_dir); + return filelist_checkdir_lib(filelist, r_dir, do_change); } static void filelist_entry_clear(FileDirEntry *entry) @@ -1376,6 +1392,11 @@ const char *filelist_dir(struct FileList *filelist) return filelist->filelist.root; } +bool filelist_is_dir(struct FileList *filelist, const char *path) +{ + return filelist->checkdirf(filelist, (char *)path, false); +} + /** * May modify in place given r_dir, which is expected to be FILE_MAX_LIBEXTRA length. */ @@ -1384,7 +1405,7 @@ void filelist_setdir(struct FileList *filelist, char *r_dir) BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA); BLI_cleanup_dir(G.main->name, r_dir); - filelist->checkdirf(filelist, r_dir); + BLI_assert(filelist->checkdirf(filelist, r_dir, true)); if (!STREQ(filelist->filelist.root, r_dir)) { BLI_strncpy(filelist->filelist.root, r_dir, sizeof(filelist->filelist.root)); @@ -1952,6 +1973,9 @@ int ED_path_extension_type(const char *path) else if (BLI_testextensie(path, ".dae")) { return FILE_TYPE_COLLADA; } + else if (BLI_testextensie(path, ".abc")) { + return FILE_TYPE_ALEMBIC; + } else if (BLI_testextensie_array(path, imb_ext_image) || (G.have_quicktime && BLI_testextensie_array(path, imb_ext_image_qt))) { @@ -2004,6 +2028,8 @@ int ED_file_extension_icon(const char *path) return ICON_FILE_BLANK; case FILE_TYPE_COLLADA: return ICON_FILE_BLANK; + case FILE_TYPE_ALEMBIC: + return ICON_FILE_BLANK; case FILE_TYPE_TEXT: return ICON_FILE_TEXT; default: diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index d70faab1d6a..f4304681780 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -86,6 +86,7 @@ void filelist_clear_ex(struct FileList *filelist, const bool do_c void filelist_free(struct FileList *filelist); const char * filelist_dir(struct FileList *filelist); +bool filelist_is_dir(struct FileList *filelist, const char *path); void filelist_setdir(struct FileList *filelist, char *r_dir); int filelist_files_ensure(struct FileList *filelist); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index ab33d452d3c..7abe5ff5070 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -185,6 +185,8 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_collada"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_alembic"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_ALEMBIC : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) { /* Protection against pyscripts not setting proper size limit... */ char *tmp = RNA_property_string_get_alloc( @@ -213,7 +215,7 @@ short ED_fileselect_set_params(SpaceFile *sfile) FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA | FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | - FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO; + FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF; if (U.uiflag & USER_HIDE_DOT) { params->flag |= FILE_HIDE_DOT; @@ -590,7 +592,7 @@ void ED_file_change_dir(bContext *C) sfile->params->filter_search[0] = '\0'; sfile->params->active_file = -1; - if (!file_is_dir(sfile, sfile->params->dir)) { + if (!filelist_is_dir(sfile->files, sfile->params->dir)) { BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); /* could return but just refresh the current dir */ } diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 478dbd3d9c0..75f0da83e77 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -632,7 +632,9 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* auto-set range */ WM_keymap_add_item(keymap, "GRAPH_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "GRAPH_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "GRAPH_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "GRAPH_OT_view_frame", PAD0, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 2582ba4be8d..b35d1b2c777 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -687,7 +687,7 @@ static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID return; } - if ((ID *)sgraph->ads->filter_grp == old_id) { + if (sgraph->ads && (ID *)sgraph->ads->filter_grp == old_id) { sgraph->ads->filter_grp = (Group *)new_id; } } diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 69993c3be65..52d04ad4956 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -64,7 +64,9 @@ void IMAGE_OT_view_zoom_in(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_out(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_ratio(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_border(struct wmOperatorType *ot); +#ifdef WITH_INPUT_NDOF void IMAGE_OT_view_ndof(struct wmOperatorType *ot); +#endif void IMAGE_OT_new(struct wmOperatorType *ot); void IMAGE_OT_open(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 1158e692182..1f591b5fb35 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -656,6 +656,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } +#ifdef WITH_INPUT_NDOF /********************** NDOF operator *********************/ /* Combined pan/zoom from a 3D mouse device. @@ -705,6 +706,7 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_LOCK_BYPASS; } +#endif /* WITH_INPUT_NDOF */ /********************** view all operator *********************/ @@ -1611,13 +1613,16 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, if (ima->source == IMA_SRC_GENERATED) { simopts->im_format.imtype = R_IMF_IMTYPE_PNG; simopts->im_format.compress = ibuf->foptions.quality; + simopts->im_format.planes = ibuf->planes; } else { BKE_imbuf_to_image_format(&simopts->im_format, ibuf); } - } - simopts->im_format.planes = ibuf->planes; + /* use the multiview image settings as the default */ + simopts->im_format.stereo3d_format = *ima->stereo3d_format; + simopts->im_format.views_format = ima->views_format; + } //simopts->subimtype = scene->r.subimtype; /* XXX - this is lame, we need to make these available too! */ @@ -1658,10 +1663,6 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, } } - /* use the multiview image settings as the default */ - simopts->im_format.stereo3d_format = *ima->stereo3d_format; - simopts->im_format.views_format = ima->views_format; - /* color management */ BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &scene->display_settings); BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 35a658eac23..6ddf78290aa 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -235,7 +235,9 @@ static void image_operatortypes(void) WM_operatortype_append(IMAGE_OT_view_zoom_out); WM_operatortype_append(IMAGE_OT_view_zoom_ratio); WM_operatortype_append(IMAGE_OT_view_zoom_border); +#ifdef WITH_INPUT_NDOF WM_operatortype_append(IMAGE_OT_view_ndof); +#endif WM_operatortype_append(IMAGE_OT_new); WM_operatortype_append(IMAGE_OT_open); @@ -296,8 +298,10 @@ static void image_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MOUSEPAN, 0, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "IMAGE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); // or view selected? WM_keymap_add_item(keymap, "IMAGE_OT_view_ndof", NDOF_MOTION, 0, 0, 0); +#endif WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index 69966e9bf34..12ca141128b 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -186,7 +186,9 @@ static void logic_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_menu(keymap, "LOGIC_MT_logicbricks_add", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "LOGIC_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "LOGIC_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif } static void logic_refresh(const bContext *UNUSED(C), ScrArea *UNUSED(sa)) diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 9032d286933..3243579f7d0 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -131,6 +131,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ case ANIMTYPE_DSLAM: case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: case ANIMTYPE_DSCUR: case ANIMTYPE_DSSKEY: case ANIMTYPE_DSWOR: diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 9e73e03a664..4f30c049d9d 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -170,6 +170,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ case ANIMTYPE_DSLAM: case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: case ANIMTYPE_DSCUR: case ANIMTYPE_DSSKEY: case ANIMTYPE_DSWOR: diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 386950ead3a..48037a10b2d 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -242,7 +242,9 @@ static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "NLA_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "NLA_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "NLA_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "NLA_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NLA_OT_view_frame", PAD0, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index d9c51e427c8..ab40c55b59d 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -1327,8 +1327,10 @@ void drawnodespace(const bContext *C, ARegion *ar) path = snode->treepath.last; /* update tree path name (drawn in the bottom left) */ - if (snode->id && UNLIKELY(!STREQ(path->node_name, snode->id->name + 2))) { - BLI_strncpy(path->node_name, snode->id->name + 2, sizeof(path->node_name)); + ID *name_id = (path->nodetree && path->nodetree != snode->nodetree) ? &path->nodetree->id : snode->id; + + if (name_id && UNLIKELY(!STREQ(path->node_name, name_id->name + 2))) { + BLI_strncpy(path->node_name, name_id->name + 2, sizeof(path->node_name)); } /* current View2D center, will be set temporarily for parent node trees */ diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 7788173a8ee..5118d52efc4 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -295,7 +295,9 @@ void node_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "NODE_OT_hide_socket_toggle", HKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "NODE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "NODE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "NODE_OT_select_border", BKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index ea3869ef387..5f592431558 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -276,25 +276,16 @@ static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, in return NULL; } -static int snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace) +static bool snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace) { bNodeTree *ntree = snode->edittree; - bNodeLink *link; /* then we can connect */ if (replace) nodeRemSocketLinks(ntree, sock_to); - link = nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to); - /* validate the new link */ - ntreeUpdateTree(G.main, ntree); - if (!(link->flag & NODE_LINK_VALID)) { - nodeRemLink(ntree, link); - return 0; - } - - snode_update(snode, node_to); - return 1; + nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to); + return true; } static void snode_autoconnect(SpaceNode *snode, const bool allow_multiple, const bool replace) diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 09594ab543c..ec525e684b0 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -428,6 +428,20 @@ static int ui_node_item_name_compare(const void *a, const void *b) return BLI_natstrcmp(type_a->ui_name, type_b->ui_name); } +static bool ui_node_item_special_poll(const bNodeTree *UNUSED(ntree), + const bNodeType *ntype) +{ + if (STREQ(ntype->idname, "ShaderNodeUVAlongStroke")) { + /* TODO(sergey): Currently we don't have Freestyle nodes edited from + * the buttons context, so can ignore it's nodes completely. + * + * However, we might want to do some extra checks here later. + */ + return false; + } + return true; +} + static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) { bNodeTree *ntree = arg->ntree; @@ -452,11 +466,17 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) BLI_array_declare(sorted_ntypes); NODE_TYPES_BEGIN(ntype) { - if (compatibility && !(ntype->compatibility & compatibility)) + if (compatibility && !(ntype->compatibility & compatibility)) { continue; + } - if (ntype->nclass != nclass) + if (ntype->nclass != nclass) { continue; + } + + if (!ui_node_item_special_poll(ntree, ntype)) { + continue; + } BLI_array_append(sorted_ntypes, ntype); } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index b57462df53b..d4553b650c5 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1173,6 +1173,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break; case eModifierType_MeshCache: UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ + case eModifierType_MeshSequenceCache: + UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ case eModifierType_Wireframe: UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break; case eModifierType_LaplacianDeform: diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index d2666cd0b6d..ca037cb20cc 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -62,7 +62,7 @@ typedef struct TreeElement { #define TREESTORE_ID_TYPE(_id) \ (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \ ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \ - ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO)) /* Only in 'blendfile' mode ... :/ */ + ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF)) /* Only in 'blendfile' mode ... :/ */ /* TreeElement->flag */ #define TE_ACTIVE 1 diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index b22e6595caf..96bab3d5c1e 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -38,6 +38,7 @@ #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_camera_types.h" +#include "DNA_cachefile_types.h" #include "DNA_gpencil_types.h" #include "DNA_group_types.h" #include "DNA_key_types.h" @@ -746,6 +747,16 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor outliner_add_element(soops, &te->subtree, ca, te, TSE_ANIM_DATA, 0); break; } + case ID_CF: + { + CacheFile *cache_file = (CacheFile *)id; + + if (outliner_animdata_test(cache_file->adt)) { + outliner_add_element(soops, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0); + } + + break; + } case ID_LA: { Lamp *la = (Lamp *)id; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index adb7cf4940c..e1768e4aedc 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -471,7 +471,7 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla } /* draw info text on a sequence strip */ -static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float y1, float y2, const unsigned char background_col[3]) +static void draw_seq_text(View2D *v2d, SpaceSeq *sseq, Sequence *seq, float x1, float x2, float y1, float y2, const unsigned char background_col[3]) { rctf rect; char str[32 + FILE_MAX]; @@ -540,7 +540,12 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float name, seq->len); } else if (seq->type == SEQ_TYPE_SOUND_RAM) { - if (seq->sound) { + /* If a waveform is drawn, we don't want to overlay it with text, + * as it would make both hard to read. */ + if ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)) { + str[0] = 0; + str_len = 0; + } else if (seq->sound) { str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d", name, seq->sound->name, seq->len); } @@ -870,7 +875,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg /* nice text here would require changing the view matrix for texture text */ if ((x2 - x1) / pixelx > 32) { - draw_seq_text(v2d, seq, x1, x2, y1, y2, background_col); + draw_seq_text(v2d, sseq, seq, x1, x2, y1, y2, background_col); } } diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 655e029cfdd..a3cfcae77b8 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -201,7 +201,9 @@ void sequencer_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_separate", GKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "SEQUENCER_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_view_frame", PAD0, KM_PRESS, 0, 0); @@ -340,7 +342,9 @@ void sequencer_keymap(wmKeyConfig *keyconf) /* Preview Region ----------------------------------------------------------- */ keymap = WM_keymap_find(keyconf, "SequencerPreview", SPACE_SEQ, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all_preview", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all_preview", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "SEQUENCER_OT_view_ghost_border", OKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 525d42a1965..15eb154c757 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -32,7 +32,10 @@ #include <string.h> #include <stdio.h> +#include "DNA_cachefile_types.h" +#include "DNA_constraint_types.h" #include "DNA_gpencil_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -42,7 +45,10 @@ #include "BLI_dlrbTree.h" #include "BLI_utildefines.h" +#include "BKE_constraint.h" #include "BKE_context.h" +#include "BKE_main.h" +#include "BKE_modifier.h" #include "BKE_screen.h" #include "BKE_pointcache.h" @@ -320,6 +326,9 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel) case ID_GD: gpencil_to_keylist(&ads, (bGPdata *)id, &keys); break; + case ID_CF: + cachefile_to_keylist(&ads, (CacheFile *)id, &keys, NULL); + break; } /* build linked-list for searching */ @@ -344,6 +353,56 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel) BLI_dlrbTree_free(&keys); } +static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel) +{ + CacheFile *cache_file; + + for (cache_file = bmain->cachefiles.first; + cache_file; + cache_file = cache_file->id.next) + { + cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN; + } + + for (Base *base = scene->base.first; base; base = base->next) { + Object *ob = base->object; + + ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); + + if (md) { + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; + + cache_file = mcmd->cache_file; + + if (!cache_file || (cache_file->draw_flag & CACHEFILE_KEYFRAME_DRAWN) != 0) { + continue; + } + + cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN; + + time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel); + } + + for (bConstraint *con = ob->constraints.first; con; con = con->next) { + if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) { + continue; + } + + bTransformCacheConstraint *data = con->data; + + cache_file = data->cache_file; + + if (!cache_file || (cache_file->draw_flag & CACHEFILE_KEYFRAME_DRAWN) != 0) { + continue; + } + + cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN; + + time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel); + } + } +} + /* draw keyframe lines for timeline */ static void time_draw_keyframes(const bContext *C, ARegion *ar) { @@ -354,7 +413,11 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) /* set this for all keyframe lines once and for all */ glLineWidth(1.0); - + + /* draw cache files keyframes (if available) */ + UI_ThemeColor(TH_TIME_KEYFRAME); + time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel); + /* draw grease pencil keyframes (if available) */ UI_ThemeColor(TH_TIME_GP_KEYFRAME); if (scene->gpd) { @@ -750,6 +813,7 @@ void ED_spacetype_time(void) art->draw = time_main_region_draw; art->listener = time_main_region_listener; art->keymap = time_keymap; + art->lock = 1; /* Due to pointcache, see T4960. */ BLI_addhead(&st->regiontypes, art); /* regions: header */ diff --git a/source/blender/editors/space_time/time_ops.c b/source/blender/editors/space_time/time_ops.c index 7dd45327352..872793128f0 100644 --- a/source/blender/editors/space_time/time_ops.c +++ b/source/blender/editors/space_time/time_ops.c @@ -219,7 +219,9 @@ void time_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "TIME_OT_start_frame_set", SKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "TIME_OT_end_frame_set", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "TIME_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "TIME_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "TIME_OT_view_frame", PAD0, KM_PRESS, 0, 0); } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 614289997c1..d273f898f63 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -1015,12 +1015,18 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d else { userData.me = NULL; - if ((ob->mode & OB_MODE_ALL_PAINT) == 0) { + /* if ((ob->mode & OB_MODE_ALL_PAINT) == 0) */ { /* Note: this isn't efficient and runs on every redraw, * its needed so material colors are used for vertex colors. * In the future we will likely remove 'texface' so, just avoid running this where possible, - * (when vertex paint or weight paint are used). */ + * (when vertex paint or weight paint are used). + * + * Note 2: We disable optimization for now since it causes T48788 + * and it is now too close to release to do something smarter. + * + * TODO(sergey): Find some real solution here. + */ update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT)); } diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index e93d840eddd..06677ef4476 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -288,6 +288,108 @@ static int create_view_aligned_slices(VolumeSlicer *slicer, return num_points; } +static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture *tex_spec, + bool use_fire, const float min[3], + const float ob_sizei[3], const float invsize[3]) +{ + int invsize_location = GPU_shader_get_uniform(shader, "invsize"); + int ob_sizei_location = GPU_shader_get_uniform(shader, "ob_sizei"); + int min_location = GPU_shader_get_uniform(shader, "min_location"); + + int soot_location; + int stepsize_location; + int densityscale_location; + int spec_location, flame_location; + int shadow_location, actcol_location; + + if (use_fire) { + spec_location = GPU_shader_get_uniform(shader, "spectrum_texture"); + flame_location = GPU_shader_get_uniform(shader, "flame_texture"); + } + else { + shadow_location = GPU_shader_get_uniform(shader, "shadow_texture"); + actcol_location = GPU_shader_get_uniform(shader, "active_color"); + soot_location = GPU_shader_get_uniform(shader, "soot_texture"); + stepsize_location = GPU_shader_get_uniform(shader, "step_size"); + densityscale_location = GPU_shader_get_uniform(shader, "density_scale"); + } + + GPU_shader_bind(shader); + + if (use_fire) { + GPU_texture_bind(sds->tex_flame, 2); + GPU_shader_uniform_texture(shader, flame_location, sds->tex_flame); + + GPU_texture_bind(tex_spec, 3); + GPU_shader_uniform_texture(shader, spec_location, tex_spec); + } + else { + float density_scale = 10.0f; + + GPU_shader_uniform_vector(shader, stepsize_location, 1, 1, &sds->dx); + GPU_shader_uniform_vector(shader, densityscale_location, 1, 1, &density_scale); + + GPU_texture_bind(sds->tex, 0); + GPU_shader_uniform_texture(shader, soot_location, sds->tex); + + GPU_texture_bind(sds->tex_shadow, 1); + GPU_shader_uniform_texture(shader, shadow_location, sds->tex_shadow); + + float active_color[3] = { 0.9, 0.9, 0.9 }; + if ((sds->active_fields & SM_ACTIVE_COLORS) == 0) + mul_v3_v3(active_color, sds->active_color); + GPU_shader_uniform_vector(shader, actcol_location, 3, 1, active_color); + } + + GPU_shader_uniform_vector(shader, min_location, 3, 1, min); + GPU_shader_uniform_vector(shader, ob_sizei_location, 3, 1, ob_sizei); + GPU_shader_uniform_vector(shader, invsize_location, 3, 1, invsize); +} + +static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool use_fire) +{ + GPU_shader_unbind(); + + GPU_texture_unbind(sds->tex); + + if (use_fire) { + GPU_texture_unbind(sds->tex_flame); + GPU_texture_unbind(tex_spec); + GPU_texture_free(tex_spec); + } + else { + GPU_texture_unbind(sds->tex_shadow); + } +} + +static void draw_buffer(SmokeDomainSettings *sds, GPUShader *shader, const VolumeSlicer *slicer, + const float ob_sizei[3], const float invsize[3], const int num_points, const bool do_fire) +{ + GPUTexture *tex_spec = (do_fire) ? create_flame_spectrum_texture() : NULL; + + GLuint vertex_buffer; + glGenBuffers(1, &vertex_buffer); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * num_points, &slicer->verts[0][0], GL_STATIC_DRAW); + + bind_shader(sds, shader, tex_spec, do_fire, slicer->min, ob_sizei, invsize); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, NULL); + + glDrawArrays(GL_TRIANGLES, 0, num_points); + + glDisableClientState(GL_VERTEX_ARRAY); + + unbind_shader(sds, tex_spec, do_fire); + + /* cleanup */ + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDeleteBuffers(1, &vertex_buffer); +} + void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, const float min[3], const float max[3], const float viewnormal[3]) @@ -299,14 +401,23 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) && sds->tex_flame; - GPUShader *shader = GPU_shader_get_builtin_shader( - (use_fire) ? GPU_SHADER_SMOKE_FIRE : GPU_SHADER_SMOKE); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_SMOKE); if (!shader) { fprintf(stderr, "Unable to create GLSL smoke shader.\n"); return; } + GPUShader *fire_shader = NULL; + if (use_fire) { + fire_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SMOKE_FIRE); + + if (!fire_shader) { + fprintf(stderr, "Unable to create GLSL fire shader.\n"); + return; + } + } + const float ob_sizei[3] = { 1.0f / fabsf(ob->size[0]), 1.0f / fabsf(ob->size[1]), @@ -320,50 +431,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, TIMEIT_START(draw); #endif - /* setup smoke shader */ - - int soot_location = GPU_shader_get_uniform(shader, "soot_texture"); - int spec_location = GPU_shader_get_uniform(shader, "spectrum_texture"); - int shadow_location = GPU_shader_get_uniform(shader, "shadow_texture"); - int flame_location = GPU_shader_get_uniform(shader, "flame_texture"); - int actcol_location = GPU_shader_get_uniform(shader, "active_color"); - int stepsize_location = GPU_shader_get_uniform(shader, "step_size"); - int densityscale_location = GPU_shader_get_uniform(shader, "density_scale"); - int invsize_location = GPU_shader_get_uniform(shader, "invsize"); - int ob_sizei_location = GPU_shader_get_uniform(shader, "ob_sizei"); - int min_location = GPU_shader_get_uniform(shader, "min_location"); - - GPU_shader_bind(shader); - - GPU_texture_bind(sds->tex, 0); - GPU_shader_uniform_texture(shader, soot_location, sds->tex); - - GPU_texture_bind(sds->tex_shadow, 1); - GPU_shader_uniform_texture(shader, shadow_location, sds->tex_shadow); - - GPUTexture *tex_spec = NULL; - - if (use_fire) { - GPU_texture_bind(sds->tex_flame, 2); - GPU_shader_uniform_texture(shader, flame_location, sds->tex_flame); - - tex_spec = create_flame_spectrum_texture(); - GPU_texture_bind(tex_spec, 3); - GPU_shader_uniform_texture(shader, spec_location, tex_spec); - } - - float active_color[3] = { 0.9, 0.9, 0.9 }; - float density_scale = 10.0f; - if ((sds->active_fields & SM_ACTIVE_COLORS) == 0) - mul_v3_v3(active_color, sds->active_color); - - GPU_shader_uniform_vector(shader, actcol_location, 3, 1, active_color); - GPU_shader_uniform_vector(shader, stepsize_location, 1, 1, &sds->dx); - GPU_shader_uniform_vector(shader, densityscale_location, 1, 1, &density_scale); - GPU_shader_uniform_vector(shader, min_location, 3, 1, min); - GPU_shader_uniform_vector(shader, ob_sizei_location, 3, 1, ob_sizei); - GPU_shader_uniform_vector(shader, invsize_location, 3, 1, invsize); - /* setup slicing information */ const int max_slices = 256; @@ -379,48 +446,32 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, /* setup buffer and draw */ - int gl_depth = 0, gl_blend = 0; + int gl_depth = 0, gl_blend = 0, gl_depth_write = 0; glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); + glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&gl_depth_write); glEnable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - GLuint vertex_buffer; - glGenBuffers(1, &vertex_buffer); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * num_points, &slicer.verts[0][0], GL_STATIC_DRAW); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, NULL); - - glDrawArrays(GL_TRIANGLES, 0, num_points); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + draw_buffer(sds, shader, &slicer, ob_sizei, invsize, num_points, false); - glDisableClientState(GL_VERTEX_ARRAY); + /* Draw fire separately (T47639). */ + if (use_fire) { + glBlendFunc(GL_ONE, GL_ONE); + draw_buffer(sds, fire_shader, &slicer, ob_sizei, invsize, num_points, true); + } #ifdef DEBUG_DRAW_TIME printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw)); TIMEIT_END(draw); #endif - /* cleanup */ - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &vertex_buffer); - - GPU_texture_unbind(sds->tex); - GPU_texture_unbind(sds->tex_shadow); - - if (use_fire) { - GPU_texture_unbind(sds->tex_flame); - GPU_texture_unbind(tex_spec); - GPU_texture_free(tex_spec); - } - MEM_freeN(slicer.verts); - GPU_shader_unbind(); + glDepthMask(gl_depth_write); if (!gl_blend) { glDisable(GL_BLEND); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 6463c137c2b..6a58b41a34f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -647,6 +647,7 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect) glDisable(GL_BLEND); } +#ifdef WITH_INPUT_NDOF /* draw center and axis of rotation for ongoing 3D mouse navigation */ static void draw_rotation_guide(RegionView3D *rv3d) { @@ -751,6 +752,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) glDisable(GL_POINT_SMOOTH); glDepthMask(1); } +#endif /* WITH_INPUT_NDOF */ static void draw_view_icon(RegionView3D *rv3d, rcti *rect) { @@ -951,9 +953,11 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) UI_ThemeColor(TH_TEXT_HI); } else { - /* no object */ - /* color is always white */ - UI_ThemeColor(TH_TEXT_HI); + /* no object */ + if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) + UI_ThemeColor(TH_TIME_GP_KEYFRAME); + else + UI_ThemeColor(TH_TEXT_HI); } if (markern) { @@ -4352,10 +4356,11 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie BDR_drawSketch(C); } +#ifdef WITH_INPUT_NDOF if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB)) /* TODO: draw something else (but not this) during fly mode */ draw_rotation_guide(rv3d); - +#endif } static bool is_cursor_visible(Scene *scene) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 215d90a8878..9b8ca2d26da 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1329,6 +1329,8 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } +#ifdef WITH_INPUT_NDOF + /** \name NDOF Utility Functions * \{ */ @@ -1894,6 +1896,8 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot) ot->flag = 0; } +#endif /* WITH_INPUT_NDOF */ + /* ************************ viewmove ******************************** */ diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 31377d0fce8..04a6aa215f4 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -26,8 +26,10 @@ /* defines VIEW3D_OT_fly modal operator */ -//#define NDOF_FLY_DEBUG -//#define NDOF_FLY_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ +#ifdef WITH_INPUT_NDOF +//# define NDOF_FLY_DEBUG +//# define NDOF_FLY_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ +#endif /* WITH_INPUT_NDOF */ #include "DNA_object_types.h" @@ -203,7 +205,10 @@ typedef struct FlyInfo { int mval[2]; /* latest 2D mouse values */ int center_mval[2]; /* center mouse values */ float width, height; /* camera viewport dimensions */ + +#ifdef WITH_INPUT_NDOF wmNDOFMotionData *ndof; /* latest 3D mouse values */ +#endif /* fly state state */ float speed; /* the speed the view is moving per redraw */ @@ -381,7 +386,10 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); copy_v2_v2_int(fly->mval, event->mval); + +#ifdef WITH_INPUT_NDOF fly->ndof = NULL; +#endif fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer(); @@ -449,8 +457,10 @@ static int flyEnd(bContext *C, FlyInfo *fly) rv3d->rflag &= ~RV3D_NAVIGATING; +#ifdef WITH_INPUT_NDOF if (fly->ndof) MEM_freeN(fly->ndof); +#endif if (fly->state == FLY_CONFIRM) { MEM_freeN(fly); @@ -469,6 +479,7 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e else if (event->type == MOUSEMOVE) { copy_v2_v2_int(fly->mval, event->mval); } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { /* do these automagically get delivered? yes. */ // puts("ndof motion detected in fly mode!"); @@ -478,15 +489,15 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e switch (incoming_ndof->progress) { case P_STARTING: /* start keeping track of 3D mouse position */ -#ifdef NDOF_FLY_DEBUG +# ifdef NDOF_FLY_DEBUG puts("start keeping track of 3D mouse position"); -#endif +# endif /* fall-through */ case P_IN_PROGRESS: /* update 3D mouse position */ -#ifdef NDOF_FLY_DEBUG +# ifdef NDOF_FLY_DEBUG putchar('.'); fflush(stdout); -#endif +# endif if (fly->ndof == NULL) { // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); fly->ndof = MEM_dupallocN(incoming_ndof); @@ -498,9 +509,9 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e break; case P_FINISHING: /* stop keeping track of 3D mouse position */ -#ifdef NDOF_FLY_DEBUG +# ifdef NDOF_FLY_DEBUG puts("stop keeping track of 3D mouse position"); -#endif +# endif if (fly->ndof) { MEM_freeN(fly->ndof); // free(fly->ndof); @@ -513,6 +524,7 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e break; /* should always be one of the above 3 */ } } +#endif /* WITH_INPUT_NDOF */ /* handle modal keymap first */ else if (event->type == EVT_MODAL_MAP) { switch (event->val) { @@ -959,6 +971,7 @@ static int flyApply(bContext *C, FlyInfo *fly) return OPERATOR_FINISHED; } +#ifdef WITH_INPUT_NDOF static void flyApply_ndof(bContext *C, FlyInfo *fly) { Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); @@ -977,6 +990,7 @@ static void flyApply_ndof(bContext *C, FlyInfo *fly) } } } +#endif /* WITH_INPUT_NDOF */ static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -1023,12 +1037,15 @@ static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event) flyEvent(C, op, fly, event); +#ifdef WITH_INPUT_NDOF if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */ if (event->type == NDOF_MOTION) { flyApply_ndof(C, fly); } } - else if (event->type == TIMER && event->customdata == fly->timer) { + else +#endif /* WITH_INPUT_NDOF */ + if (event->type == TIMER && event->customdata == fly->timer) { flyApply(C, fly); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index bdd2702a6ce..314dadbaa52 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -46,7 +46,6 @@ struct bContext; struct bMotionPath; struct bPoseChannel; struct Mesh; -struct wmNDOFMotionData; struct wmOperatorType; struct wmWindowManager; struct wmKeyConfig; @@ -76,10 +75,12 @@ void VIEW3D_OT_dolly(struct wmOperatorType *ot); void VIEW3D_OT_zoom_camera_1_to_1(struct wmOperatorType *ot); void VIEW3D_OT_move(struct wmOperatorType *ot); void VIEW3D_OT_rotate(struct wmOperatorType *ot); +#ifdef WITH_INPUT_NDOF void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot); void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot); void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot); void VIEW3D_OT_ndof_all(struct wmOperatorType *ot); +#endif /* WITH_INPUT_NDOF */ void VIEW3D_OT_view_all(struct wmOperatorType *ot); void VIEW3D_OT_viewnumpad(struct wmOperatorType *ot); void VIEW3D_OT_view_selected(struct wmOperatorType *ot); @@ -111,11 +112,15 @@ void view3d_orbit_apply_dyn_ofs( float r_ofs[3], const float ofs_old[3], const float viewquat_old[4], const float viewquat_new[4], const float dyn_ofs[3]); +#ifdef WITH_INPUT_NDOF +struct wmNDOFMotionData; + void view3d_ndof_fly( const struct wmNDOFMotionData *ndof, struct View3D *v3d, struct RegionView3D *rv3d, const bool use_precision, const short protectflag, bool *r_has_translate, bool *r_has_rotate); +#endif /* WITH_INPUT_NDOF */ /* view3d_fly.c */ void view3d_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index b273f46fca3..cfeb8af280e 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -164,10 +164,12 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_zoom); WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1); WM_operatortype_append(VIEW3D_OT_dolly); +#ifdef WITH_INPUT_NDOF WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom); WM_operatortype_append(VIEW3D_OT_ndof_orbit); WM_operatortype_append(VIEW3D_OT_ndof_pan); WM_operatortype_append(VIEW3D_OT_ndof_all); +#endif /* WITH_INPUT_NDOF */ WM_operatortype_append(VIEW3D_OT_view_all); WM_operatortype_append(VIEW3D_OT_viewnumpad); WM_operatortype_append(VIEW3D_OT_view_orbit); @@ -363,7 +365,7 @@ void view3d_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0); - /* NDOF: begin */ +#ifdef WITH_INPUT_NDOF /* note: positioned here so keymaps show keyboard keys if assigned */ /* 3D mouse */ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit_zoom", NDOF_MOTION, 0, 0, 0); @@ -392,8 +394,7 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP); RNA_boolean_set(kmi->ptr, "align_active", true); - /* NDOF: end */ - +#endif /* WITH_INPUT_NDOF */ /* layers, shift + alt are properties set in invoke() */ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ACCENTGRAVEKEY, KM_PRESS, 0, 0)->ptr, "nr", 0); diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index a55849e5633..3c13ab9d595 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -297,23 +297,36 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) bGPDlayer *gpl; bGPDframe *gpf; bGPDstroke *gps; + bGPDpalette *palette; + bGPDpalettecolor *palcolor; RulerItem *ruler_item; const char *ruler_name = RULER_ID; bool changed = false; if (scene->gpd == NULL) { - scene->gpd = gpencil_data_addnew("GPencil"); + scene->gpd = BKE_gpencil_data_addnew("GPencil"); } gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); if (gpl == NULL) { - gpl = gpencil_layer_addnew(scene->gpd, ruler_name, false); + gpl = BKE_gpencil_layer_addnew(scene->gpd, ruler_name, false); gpl->thickness = 1; gpl->flag |= GP_LAYER_HIDE; } - gpf = gpencil_layer_getframe(gpl, CFRA, true); - free_gpencil_strokes(gpf); + /* try to get active palette or create a new one */ + palette = BKE_gpencil_palette_getactive(scene->gpd); + if (palette == NULL) { + palette = BKE_gpencil_palette_addnew(scene->gpd, DATA_("GP_Palette"), true); + } + /* try to get color with the ruler name or create a new one */ + palcolor = BKE_gpencil_palettecolor_getbyname(palette, (char *)ruler_name); + if (palcolor == NULL) { + palcolor = BKE_gpencil_palettecolor_addnew(palette, (char *)ruler_name, true); + } + + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true); + BKE_gpencil_free_strokes(gpf); for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) { bGPDspoint *pt; @@ -342,6 +355,10 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) } } gps->flag = GP_STROKE_3DSPACE; + gps->thickness = 3; + /* assign color to stroke */ + BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname)); + gps->palcolor = palcolor; BLI_addtail(&gpf->strokes, gps); changed = true; } @@ -360,7 +377,7 @@ static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info) gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); if (gpl) { bGPDframe *gpf; - gpf = gpencil_layer_getframe(gpl, CFRA, false); + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, false); if (gpf) { bGPDstroke *gps; for (gps = gpf->strokes.first; gps; gps = gps->next) { diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index a460d8900b4..3239d07553f 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1954,6 +1954,9 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool int index = buffer[(4 * a) + 3]; if (index != -1) { ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY)); + if ((index & 0xFFFF0000) == 0) { + continue; + } if ((select == false) || ((ebone->flag & BONE_UNSELECTABLE) == 0)) { if (index & BONESEL_TIP) { ebone->flag |= BONE_DONE; diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index c9e4bb301b8..17c08ed4205 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -59,8 +59,10 @@ #include "view3d_intern.h" /* own include */ -//#define NDOF_WALK_DEBUG -//#define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ +#ifdef WITH_INPUT_NDOF +//# define NDOF_WALK_DEBUG +//# define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ +#endif #define USE_TABLET_SUPPORT @@ -254,7 +256,10 @@ typedef struct WalkInfo { int prev_mval[2]; /* previous 2D mouse values */ int center_mval[2]; /* center mouse values */ int moffset[2]; + +#ifdef WITH_INPUT_NDOF wmNDOFMotionData *ndof; /* latest 3D mouse values */ +#endif /* walk state state */ float base_speed; /* the base speed without run/slow down modifications */ @@ -572,7 +577,9 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); +#ifdef WITH_INPUT_NDOF walk->ndof = NULL; +#endif walk->time_lastdraw = PIL_check_seconds_timer(); @@ -639,8 +646,10 @@ static int walkEnd(bContext *C, WalkInfo *walk) rv3d->rflag &= ~RV3D_NAVIGATING; +#ifdef WITH_INPUT_NDOF if (walk->ndof) MEM_freeN(walk->ndof); +#endif /* restore the cursor */ WM_cursor_modal_restore(win); @@ -743,6 +752,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent } } } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { /* do these automagically get delivered? yes. */ // puts("ndof motion detected in walk mode!"); @@ -752,15 +762,15 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent switch (incoming_ndof->progress) { case P_STARTING: /* start keeping track of 3D mouse position */ -#ifdef NDOF_WALK_DEBUG +# ifdef NDOF_WALK_DEBUG puts("start keeping track of 3D mouse position"); -#endif +# endif /* fall-through */ case P_IN_PROGRESS: /* update 3D mouse position */ -#ifdef NDOF_WALK_DEBUG +# ifdef NDOF_WALK_DEBUG putchar('.'); fflush(stdout); -#endif +# endif if (walk->ndof == NULL) { // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); walk->ndof = MEM_dupallocN(incoming_ndof); @@ -772,9 +782,9 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent break; case P_FINISHING: /* stop keeping track of 3D mouse position */ -#ifdef NDOF_WALK_DEBUG +# ifdef NDOF_WALK_DEBUG puts("stop keeping track of 3D mouse position"); -#endif +# endif if (walk->ndof) { MEM_freeN(walk->ndof); // free(walk->ndof); @@ -789,6 +799,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent break; /* should always be one of the above 3 */ } } +#endif /* WITH_INPUT_NDOF */ /* handle modal keymap first */ else if (event->type == EVT_MODAL_MAP) { switch (event->val) { @@ -1323,6 +1334,7 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) #undef WALK_BOOST_FACTOR } +#ifdef WITH_INPUT_NDOF static void walkApply_ndof(bContext *C, WalkInfo *walk) { Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); @@ -1341,6 +1353,7 @@ static void walkApply_ndof(bContext *C, WalkInfo *walk) } } } +#endif /* WITH_INPUT_NDOF */ /****** walk operator ******/ static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -1388,12 +1401,15 @@ static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event) walkEvent(C, op, walk, event); +#ifdef WITH_INPUT_NDOF if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */ if (event->type == NDOF_MOTION) { walkApply_ndof(C, walk); } } - else if (event->type == TIMER && event->customdata == walk->timer) { + else +#endif /* WITH_INPUT_NDOF */ + if (event->type == TIMER && event->customdata == walk->timer) { walkApply(C, op, walk); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index ad2b40bfef8..9c266890d6d 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3292,7 +3292,7 @@ static void posttrans_gpd_clean(bGPdata *gpd) for (gpf = gpl->frames.first; gpf; gpf = gpfn) { gpfn = gpf->next; if (gpfn && gpf->framenum == gpfn->framenum) { - gpencil_layer_delframe(gpl, gpf); + BKE_gpencil_layer_delframe(gpl, gpf); } } } @@ -7755,7 +7755,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) */ // XXX: should this be allowed when framelock is enabled? if (gpf->framenum != cfra) { - gpf = gpencil_frame_addcopy(gpl, cfra); + gpf = BKE_gpencil_frame_addcopy(gpl, cfra); /* in some weird situations (framelock enabled) return NULL */ if (gpf == NULL) { continue; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 6e399d9fde3..cbe58ddf586 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -386,7 +386,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) TransInfo *t = op->customdata; const enum TfmMode mode_prev = t->mode; -#if 0 +#if defined(WITH_INPUT_NDOF) && 0 // stable 2D mouse coords map to different 3D coords while the 3D mouse is active // in other words, 2D deltas are no longer good enough! // disable until individual 'transformers' behave better diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index ea5a55731c3..1f5e2b63bfa 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -807,6 +807,7 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id) // sets the id of the rep rep->setId(Id(id, 0)); rep->setName(obi->ob->id.name + 2); + rep->setLibraryPath(obi->ob->id.lib ? obi->ob->id.lib->name : NULL); const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]), Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2])); diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp index 253bf278478..f2f53159fcf 100644 --- a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp +++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp @@ -296,6 +296,19 @@ static PyObject *ViewShape_name_get(BPy_ViewShape *self, void *UNUSED(closure)) return PyUnicode_FromString(self->vs->getName()); } +PyDoc_STRVAR(ViewShape_library_path_doc, +"The library path of the ViewShape.\n" +"\n" +":type: str, or None if the ViewShape is not part of a library"); + +static PyObject *ViewShape_library_path_get(BPy_ViewShape *self, void *UNUSED(closure)) +{ + const char *name = self->vs->getLibraryPath(); + if (!name) + Py_RETURN_NONE; + return PyUnicode_FromString(name); +} + PyDoc_STRVAR(ViewShape_id_doc, "The Id of this ViewShape.\n" "\n" @@ -313,6 +326,7 @@ static PyGetSetDef BPy_ViewShape_getseters[] = { (char *)ViewShape_vertices_doc, NULL}, {(char *)"edges", (getter)ViewShape_edges_get, (setter)ViewShape_edges_set, (char *)ViewShape_edges_doc, NULL}, {(char *)"name", (getter)ViewShape_name_get, (setter)NULL, (char *)ViewShape_name_doc, NULL}, + {(char *)"library_path", (getter)ViewShape_library_path_get, (setter)NULL, (char *)ViewShape_library_path_doc, NULL}, {(char *)"id", (getter)ViewShape_id_get, (setter)NULL, (char *)ViewShape_id_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; diff --git a/source/blender/freestyle/intern/scene_graph/Rep.h b/source/blender/freestyle/intern/scene_graph/Rep.h index c5036cdb153..773eb2d3278 100644 --- a/source/blender/freestyle/intern/scene_graph/Rep.h +++ b/source/blender/freestyle/intern/scene_graph/Rep.h @@ -48,6 +48,8 @@ public: inline Rep() : BaseObject() { _Id = 0; + _Name = 0; + _LibraryPath = 0; _FrsMaterial = 0; } @@ -55,6 +57,7 @@ public: { _Id = iBrother._Id; _Name = iBrother._Name; + _LibraryPath = iBrother._LibraryPath; if (0 == iBrother._FrsMaterial) _FrsMaterial = 0; else @@ -68,6 +71,7 @@ public: std::swap(_BBox, ioOther._BBox); std::swap(_Id, ioOther._Id); std::swap(_Name, ioOther._Name); + std::swap(_LibraryPath, ioOther._LibraryPath); std::swap(_FrsMaterial, ioOther._FrsMaterial); } @@ -76,6 +80,7 @@ public: if (&iBrother != this) { _Id = iBrother._Id; _Name = iBrother._Name; + _LibraryPath = iBrother._LibraryPath; if (0 == iBrother._FrsMaterial) { _FrsMaterial = 0; } @@ -132,6 +137,11 @@ public: return _Name; } + inline const char *getLibraryPath() const + { + return _LibraryPath; + } + inline const FrsMaterial *frs_material() const { return _FrsMaterial; @@ -153,7 +163,12 @@ public: _Name = name; } - inline void setFrsMaterial(const FrsMaterial& iMaterial) + inline void setLibraryPath(const char *path) + { + _LibraryPath = path; + } + + inline void setFrsMaterial(const FrsMaterial& iMaterial) { _FrsMaterial = new FrsMaterial(iMaterial); } @@ -162,6 +177,7 @@ private: BBox<Vec3f> _BBox; Id _Id; const char *_Name; + const char *_LibraryPath; FrsMaterial *_FrsMaterial; }; diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp index ab06e207331..028127897ff 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRep.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp @@ -135,11 +135,11 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices) int orientationErrors = 0; //special case of first vertex - v = iStrokeVertices.begin(); + v2 = v = iStrokeVertices.begin(); + ++v2; sv = *v; vPrev = v; //in case the stroke has only 2 vertices; - ++v; - sv2 = *v; + sv2 = *v2; Vec2r dir(sv2->getPoint() - sv->getPoint()); Vec2r orthDir(-dir[1], dir[0]); if (orthDir.norm() > ZERO) @@ -189,11 +189,7 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices) int i = 2; // 2 because we have already processed the first vertex - for (vend = iStrokeVertices.end(); v != vend; ++v) { - v2 = v; - ++v2; - if (v2 == vend) - break; + for (vend = iStrokeVertices.end(), ++v, ++v2; v2 != vend; vPrev = v++, ++v2) { sv = (*v); sv2 = (*v2); svPrev = (*vPrev); @@ -289,8 +285,6 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices) { _vertices[i - 1]->setPoint2d(p - thickness[0] * stripDir); } - - vPrev = v; } // end of for //special case of last vertex diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp index ae22a26ec9b..34fa2b14379 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.cpp +++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp @@ -77,11 +77,11 @@ BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real /*epsilon*/) // Find target cell _cell = grid.findCell(_target); #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Searching for occluders of edge centered at " << _target << " in cell [" << - 1_cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << - ", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Searching for occluders of edge centered at " << _target << " in cell [" << + 1_cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << + ", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl; + } #endif // Set iterator diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h index b9924e6ad95..9d373107bfa 100644 --- a/source/blender/freestyle/intern/view_map/Silhouette.h +++ b/source/blender/freestyle/intern/view_map/Silhouette.h @@ -1416,6 +1416,7 @@ private: vector<FEdge*> _edgesList; // list of all edges Id _Id; const char *_Name; + const char *_LibraryPath; BBox<Vec3r> _BBox; vector<FrsMaterial> _FrsMaterials; @@ -1436,6 +1437,7 @@ public: _importance = 0.0f; _ViewShape = NULL; _Name = NULL; + _LibraryPath = NULL; } /*! Copy constructor */ @@ -1444,6 +1446,7 @@ public: userdata = NULL; _Id = iBrother._Id; _Name = iBrother._Name; + _LibraryPath = iBrother._LibraryPath; _BBox = iBrother.bbox(); _FrsMaterials = iBrother._FrsMaterials; _importance = iBrother._importance; @@ -1893,6 +1896,12 @@ public: return _Name; } + /*! Returns the library path of the Shape. */ + inline const char *getLibraryPath() const + { + return _LibraryPath; + } + /* Modififers */ /*! Sets the Id of the shape.*/ inline void setId(Id id) @@ -1906,6 +1915,12 @@ public: _Name = name; } + /*! Sets the library path of the shape.*/ + inline void setLibraryPath(const char *path) + { + _LibraryPath = path; + } + /*! Sets the list of materials for the shape */ inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials) { diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h index 74297e1dbfd..8b73c8aac3a 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.h +++ b/source/blender/freestyle/intern/view_map/ViewMap.h @@ -1565,12 +1565,18 @@ public: return _SShape->getId(); } - /*! Returns the ViewShape id. */ + /*! Returns the ViewShape name. */ inline const char *getName() const { return _SShape->getName(); } + /*! Returns the ViewShape library path. */ + inline const char *getLibraryPath() const + { + return _SShape->getLibraryPath(); + } + /* modifiers */ /*! Sets the SShape on top of which the ViewShape is built. */ inline void setSShape(SShape *iSShape) diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index 9ca021475b2..380bb0dd3ca 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -1204,6 +1204,7 @@ void ViewMapBuilder::computeInitialViewEdges(WingedEdge& we) psShape = new SShape; psShape->setId((*it)->GetId()); psShape->setName((*it)->getName()); + psShape->setLibraryPath((*it)->getLibraryPath()); psShape->setFrsMaterials((*it)->frs_materials()); // FIXME // create the view shape @@ -2098,7 +2099,7 @@ int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real eps } // Find occludee - FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, edge, origin, faceVertices); + FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, origin, edge, faceVertices); return qi; } diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp index 99aa2d22239..7bec5ba1d6e 100644 --- a/source/blender/freestyle/intern/winged_edge/WEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp @@ -471,6 +471,7 @@ WShape::WShape(WShape& iBrother) { _Id = iBrother.GetId(); _Name = iBrother._Name; + _LibraryPath = iBrother._LibraryPath; _FrsMaterials = iBrother._FrsMaterials; #if 0 _meanEdgeSize = iBrother._meanEdgeSize; diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h index 8001342775b..14109fba843 100644 --- a/source/blender/freestyle/intern/winged_edge/WEdge.h +++ b/source/blender/freestyle/intern/winged_edge/WEdge.h @@ -1025,6 +1025,7 @@ protected: vector<WFace *> _FaceList; int _Id; const char *_Name; + const char *_LibraryPath; static unsigned _SceneCurrentId; #if 0 Vec3f _min; @@ -1043,6 +1044,8 @@ public: #endif _Id = _SceneCurrentId; _SceneCurrentId++; + _Name = 0; + _LibraryPath = 0; } /*! copy constructor */ @@ -1127,6 +1130,11 @@ public: return _Name; } + inline const char *getLibraryPath() const + { + return _LibraryPath; + } + /*! modifiers */ static inline void setCurrentId(const unsigned id) { @@ -1176,6 +1184,11 @@ public: _Name = name; } + inline void setLibraryPath(const char *path) + { + _LibraryPath = path; + } + /*! designed to build a specialized WFace for use in MakeFace */ virtual WFace *instanciateFace() const { diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp index 78773a9680d..dfdeedef2e1 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp +++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp @@ -42,6 +42,7 @@ void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs) } shape->setId(ifs.getId().getFirst()); shape->setName(ifs.getName()); + shape->setLibraryPath(ifs.getLibraryPath()); //ifs.setId(shape->GetId()); } diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 6bb94b334b5..d00efc3979c 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -93,6 +93,7 @@ set(SRC shaders/gpu_shader_vsm_store_vert.glsl shaders/gpu_shader_fx_depth_resolve.glsl shaders/gpu_shader_fx_colormanage_frag.glsl + shaders/gpu_shader_fire_frag.glsl shaders/gpu_shader_smoke_frag.glsl shaders/gpu_shader_smoke_vert.glsl shaders/gpu_shader_probe_sh_compute_frag.glsl @@ -123,6 +124,7 @@ set(SRC ) data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC) +data_to_c_simple(shaders/gpu_shader_fire_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_smoke_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_smoke_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_material.glsl SRC) diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h index 2c1728bfff1..61b2bc591ce 100644 --- a/source/blender/gpu/GPU_debug.h +++ b/source/blender/gpu/GPU_debug.h @@ -34,8 +34,6 @@ #include "GPU_glew.h" -#include "BLI_utildefines.h" - #ifdef __cplusplus extern "C" { #endif @@ -62,7 +60,7 @@ void GPU_assert_no_gl_errors(const char *file, int line, const char *str); /* inserts a debug marker message for the debug context messaging system */ -void GPU_string_marker(size_t size, const char *str); +void GPU_string_marker(const char *str); #ifdef __cplusplus } diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 56d6f74bbf0..aeb656b238b 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -908,7 +908,7 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv) if (input->attribtype == CD_MTFACE) { BLI_dynstr_appendf( ds, - "\tINTERP_FACE_VARYING_2(var%d, " + "\tINTERP_FACE_VARYING_ATT_2(var%d, " "int(texelFetch(FVarDataOffsetBuffer, fvar%d_offset).r), st);\n", input->attribid, input->attribid); diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c index be9285727fe..d632e767ca9 100644 --- a/source/blender/gpu/intern/gpu_debug.c +++ b/source/blender/gpu/intern/gpu_debug.c @@ -29,7 +29,9 @@ * \ingroup gpu */ +#include "BLI_utildefines.h" #include "BLI_sys_types.h" +#include "BLI_system.h" #include "BKE_global.h" @@ -159,17 +161,73 @@ const char *gpuErrorString(GLenum err) #endif +static const char* source_name(GLenum source) +{ + switch (source) { + case GL_DEBUG_SOURCE_API: return "API"; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "window system"; + case GL_DEBUG_SOURCE_SHADER_COMPILER: return "shader compiler"; + case GL_DEBUG_SOURCE_THIRD_PARTY: return "3rd party"; + case GL_DEBUG_SOURCE_APPLICATION: return "application"; + case GL_DEBUG_SOURCE_OTHER: return "other"; + default: return "???"; + } +} + +static const char* message_type_name(GLenum message) +{ + switch (message) { + case GL_DEBUG_TYPE_ERROR: return "error"; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "deprecated behavior"; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "undefined behavior"; + case GL_DEBUG_TYPE_PORTABILITY: return "portability"; + case GL_DEBUG_TYPE_PERFORMANCE: return "performance"; + case GL_DEBUG_TYPE_OTHER: return "other"; + case GL_DEBUG_TYPE_MARKER: return "marker"; /* KHR has this, ARB does not */ + default: return "???"; + } +} + +static const char* category_name_amd(GLenum category) +{ + switch (category) { + case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error"; + case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD: return "window system"; + case GL_DEBUG_CATEGORY_DEPRECATION_AMD: return "deprecated behavior"; + case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD: return "undefined behavior"; + case GL_DEBUG_CATEGORY_PERFORMANCE_AMD: return "performance"; + case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD: return "shader compiler"; + case GL_DEBUG_CATEGORY_APPLICATION_AMD: return "application"; + case GL_DEBUG_CATEGORY_OTHER_AMD: return "other"; + default: return "???"; + } +} + + static void APIENTRY gpu_debug_proc( GLenum source, GLenum type, GLuint UNUSED(id), - GLenum UNUSED(severity), GLsizei UNUSED(length), + GLenum severity, GLsizei UNUSED(length), const GLchar *message, const GLvoid *UNUSED(userParm)) { - if (source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) { - fprintf(stderr, "GL: %s\n", message); - fflush(stderr); + if (type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR) { + /* Blender 2.7x uses OpenGL 2.1, we don't care if features are deprecated */ + return; } - else if (G.debug_value == 20) { - fprintf(stderr, "GL: %s\n", message); + + bool backtrace = false; + + switch (severity) { + case GL_DEBUG_SEVERITY_HIGH: + backtrace = true; + /* fall through */ + case GL_DEBUG_SEVERITY_MEDIUM: + case GL_DEBUG_SEVERITY_LOW: + case GL_DEBUG_SEVERITY_NOTIFICATION: /* KHR has this, ARB does not */ + fprintf(stderr, "GL %s %s: %s\n", source_name(source), message_type_name(type), message); + } + + if (backtrace) { + BLI_system_backtrace(stderr); fflush(stderr); } } @@ -177,11 +235,30 @@ static void APIENTRY gpu_debug_proc( #ifndef GLEW_ES_ONLY static void APIENTRY gpu_debug_proc_amd( - GLuint UNUSED(id), GLenum UNUSED(category), - GLenum UNUSED(severity), GLsizei UNUSED(length), + GLuint UNUSED(id), GLenum category, + GLenum severity, GLsizei UNUSED(length), const GLchar *message, GLvoid *UNUSED(userParm)) { - fprintf(stderr, "GL: %s\n", message); + if (category == GL_DEBUG_CATEGORY_DEPRECATION_AMD) { + /* Blender 2.7x uses OpenGL 2.1, we don't care if features are deprecated */ + return; + } + + bool backtrace = false; + + switch (severity) { + case GL_DEBUG_SEVERITY_HIGH: + backtrace = true; + /* fall through */ + case GL_DEBUG_SEVERITY_MEDIUM: + case GL_DEBUG_SEVERITY_LOW: + fprintf(stderr, "GL %s: %s\n", category_name_amd(category), message); + } + + if (backtrace) { + BLI_system_backtrace(stderr); + fflush(stderr); + } } #endif @@ -194,36 +271,44 @@ void gpu_debug_init(void) #if !defined(WITH_GLEW_ES) && !defined(GLEW_ES_ONLY) if (GLEW_VERSION_4_3) { + fprintf(stderr, "Using OpenGL 4.3 debug facilities\n"); glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, mxGetCurrentContext()); glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); - GPU_string_marker(sizeof(success), success); + GPU_string_marker(success); return; } #endif if (GLEW_KHR_debug) { #ifndef GLEW_ES_ONLY + fprintf(stderr, "Using KHR_debug extension\n"); + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, mxGetCurrentContext()); glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); - GPU_string_marker(sizeof(success), success); + GPU_string_marker(success); #endif return; } #ifndef GLEW_ES_ONLY if (GLEW_ARB_debug_output) { + fprintf(stderr, "Using ARB_debug_output extension\n"); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glDebugMessageCallbackARB((GLDEBUGPROCARB)gpu_debug_proc, mxGetCurrentContext()); glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); - GPU_string_marker(sizeof(success), success); + GPU_string_marker(success); return; } if (GLEW_AMD_debug_output) { + fprintf(stderr, "Using AMD_debug_output extension\n"); glDebugMessageCallbackAMD(gpu_debug_proc_amd, mxGetCurrentContext()); glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); - GPU_string_marker(sizeof(success), success); + GPU_string_marker(success); return; } @@ -271,14 +356,14 @@ void gpu_debug_exit(void) return; } -void GPU_string_marker(size_t length, const char *buf) +void GPU_string_marker(const char *buf) { #ifndef WITH_GLEW_ES #ifndef GLEW_ES_ONLY if (GLEW_VERSION_4_3) { glDebugMessageInsert( GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, - GL_DEBUG_SEVERITY_NOTIFICATION, length, buf); + GL_DEBUG_SEVERITY_NOTIFICATION, -1, buf); return; } @@ -289,7 +374,7 @@ void GPU_string_marker(size_t length, const char *buf) #ifndef GLEW_ES_ONLY glDebugMessageInsert( GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, - GL_DEBUG_SEVERITY_NOTIFICATION, length, buf); + GL_DEBUG_SEVERITY_NOTIFICATION, -1, buf); #endif return; } @@ -298,7 +383,7 @@ void GPU_string_marker(size_t length, const char *buf) if (GLEW_ARB_debug_output) { glDebugMessageInsertARB( GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0, - GL_DEBUG_SEVERITY_LOW_ARB, length, buf); + GL_DEBUG_SEVERITY_LOW_ARB, -1, buf); return; } @@ -306,19 +391,17 @@ void GPU_string_marker(size_t length, const char *buf) if (GLEW_AMD_debug_output) { glDebugMessageInsertAMD( GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0, - length, buf); + 0, buf); return; } if (GLEW_GREMEDY_string_marker) { - glStringMarkerGREMEDY(length, buf); + glStringMarkerGREMEDY(0, buf); return; } #endif - - return; } void GPU_print_error_debug(const char *str) diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 1d7a99311f8..226595200ca 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -45,6 +45,7 @@ #define MAX_EXT_DEFINE_LENGTH 1024 /* Non-generated shaders */ +extern char datatoc_gpu_shader_fire_frag_glsl[]; extern char datatoc_gpu_shader_smoke_vert_glsl[]; extern char datatoc_gpu_shader_smoke_frag_glsl[]; extern char datatoc_gpu_shader_vsm_store_vert_glsl[]; @@ -690,8 +691,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) case GPU_SHADER_SMOKE_FIRE: if (!GG.shaders.smoke_fire) GG.shaders.smoke_fire = GPU_shader_create( - datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl, - NULL, NULL, "#define USE_FIRE;\n", 0, 0, 0); + datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_fire_frag_glsl, + NULL, NULL, NULL, 0, 0, 0); retval = GG.shaders.smoke_fire; break; case GPU_SHADER_DISPLAY_SH: diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 37f874ee512..e6a9db5059a 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -58,7 +58,8 @@ struct GPUTexture { int number; /* number for multitexture binding */ int refcount; /* reference count */ GLenum target; /* GL_TEXTURE_* */ - GLenum target_base; /* same as target, (but no multisample) */ + GLenum target_base; /* same as target, (but no multisample) + * use it for unbinding */ GLuint bindcode; /* opengl identifier for texture */ int fromblender; /* we got the texture from Blender */ @@ -484,6 +485,9 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget GLint bindcode = GPU_verify_image(ima, iuser, textarget, 0, 0, mipmap, is_data, do_clip); GPU_update_image_time(ima, time); + /* see GPUInput::textarget: it can take two values - GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP + * these values are correct for glDisable, so textarget can be safely used in + * GPU_texture_bind/GPU_texture_unbind through tex->target_base */ if (textarget == GL_TEXTURE_2D) gputt = TEXTARGET_TEXTURE_2D; else @@ -500,7 +504,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget tex->number = -1; tex->refcount = 1; tex->target = textarget; - tex->target_base = GL_TEXTURE_2D; + tex->target_base = textarget; tex->fromblender = 1; ima->gputexture[gputt] = tex; @@ -916,11 +920,11 @@ void GPU_texture_bind(GPUTexture *tex, int number) GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number); if (number != 0) glActiveTexture(arbnumber); if (tex->bindcode != 0) { - glBindTexture(tex->target, tex->bindcode); + glBindTexture(tex->target_base, tex->bindcode); } else - GPU_invalid_tex_bind(tex->target); - glEnable(tex->target); + GPU_invalid_tex_bind(tex->target_base); + glEnable(tex->target_base); if (number != 0) glActiveTexture(GL_TEXTURE0); tex->number = number; @@ -942,8 +946,6 @@ void GPU_texture_unbind(GPUTexture *tex) GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number); if (tex->number != 0) glActiveTexture(arbnumber); - glBindTexture(tex->target, 0); - glDisable(tex->target); glBindTexture(tex->target_base, 0); glDisable(tex->target_base); if (tex->number != 0) glActiveTexture(GL_TEXTURE0); diff --git a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl new file mode 100644 index 00000000000..3819203bcd9 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl @@ -0,0 +1,17 @@ + +varying vec3 coords; + +uniform sampler3D flame_texture; +uniform sampler1D spectrum_texture; + +void main() +{ + float flame = texture3D(flame_texture, coords).r; + vec4 emission = texture1D(spectrum_texture, flame); + + vec4 color; + color.rgb = emission.a * emission.rgb; + color.a = emission.a; + + gl_FragColor = color; +} diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl index 6f063883e37..fe630dbeddb 100644 --- a/source/blender/gpu/shaders/gpu_shader_geometry.glsl +++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl @@ -31,6 +31,18 @@ uniform int osd_fvar_count; tessCoord.t); \ } +#ifdef USE_NEW_SHADING +# define INTERP_FACE_VARYING_ATT_2(result, fvarOffset, tessCoord) \ + { \ + vec2 tmp; \ + INTERP_FACE_VARYING_2(tmp, fvarOffset, tessCoord); \ + result = vec3(tmp, 0); \ + } +#else +# define INTERP_FACE_VARYING_ATT_2(result, fvarOffset, tessCoord) \ + INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) +#endif + uniform samplerBuffer FVarDataBuffer; uniform isamplerBuffer FVarDataOffsetBuffer; diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 84fedf803c7..2b506acabef 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2196,11 +2196,11 @@ void shade_madd_clamped(vec4 col, vec4 col1, vec4 col2, out vec4 outcol) outcol = col + max(col1 * col2, vec4(0.0, 0.0, 0.0, 0.0)); } -void env_apply(vec4 col, vec4 hor, vec4 zen, vec4 f, mat4 vm, vec3 vn, out vec4 outcol) +void env_apply(vec4 col, vec3 hor, vec3 zen, vec4 f, mat4 vm, vec3 vn, out vec4 outcol) { vec3 vv = normalize(vm[2].xyz); float skyfac = 0.5 * (1.0 + dot(vn, -vv)); - outcol = col + f * mix(hor, zen, skyfac); + outcol = col + f * vec4(mix(hor, zen, skyfac), 0); } void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol) diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl index 4d1feb5c83e..fd790009e02 100644 --- a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl @@ -8,11 +8,6 @@ uniform float density_scale; uniform sampler3D soot_texture; uniform sampler3D shadow_texture; -#ifdef USE_FIRE -uniform sampler3D flame_texture; -uniform sampler1D spectrum_texture; -#endif - void main() { /* compute color and density from volume texture */ @@ -37,12 +32,5 @@ void main() /* premultiply alpha */ vec4 color = vec4(soot_alpha * soot_color, soot_alpha); -#ifdef USE_FIRE - /* fire */ - float flame = texture3D(flame_texture, coords).r; - vec4 emission = texture1D(spectrum_texture, flame); - color.rgb += (1 - color.a) * emission.a * emission.rgb; -#endif - gl_FragColor = color; } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 07df94ee332..5c1bfc229da 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -247,6 +247,7 @@ typedef enum ID_Type { ID_LS = MAKE_ID2('L', 'S'), /* FreestyleLineStyle */ ID_PAL = MAKE_ID2('P', 'L'), /* Palette */ ID_PC = MAKE_ID2('P', 'C'), /* PaintCurve */ + ID_CF = MAKE_ID2('C', 'F'), /* CacheFile */ } ID_Type; /* Only used as 'placeholder' in .blend files for directly linked datablocks. */ @@ -377,6 +378,47 @@ enum { FILTER_ID_VF = (1 << 25), FILTER_ID_WO = (1 << 26), FILTER_ID_PA = (1 << 27), + FILTER_ID_CF = (1 << 28), +}; + +/* IMPORTANT: this enum matches the order currently use in set_lisbasepointers, + * keep them in sync! */ +enum { + INDEX_ID_LI = 0, + INDEX_ID_IP, + INDEX_ID_AC, + INDEX_ID_KE, + INDEX_ID_GD, + INDEX_ID_NT, + INDEX_ID_IM, + INDEX_ID_TE, + INDEX_ID_MA, + INDEX_ID_VF, + INDEX_ID_AR, + INDEX_ID_CF, + INDEX_ID_ME, + INDEX_ID_CU, + INDEX_ID_MB, + INDEX_ID_LT, + INDEX_ID_LA, + INDEX_ID_CA, + INDEX_ID_TXT, + INDEX_ID_SO, + INDEX_ID_GR, + INDEX_ID_PAL, + INDEX_ID_PC, + INDEX_ID_BR, + INDEX_ID_PA, + INDEX_ID_SPK, + INDEX_ID_WO, + INDEX_ID_MC, + INDEX_ID_SCR, + INDEX_ID_OB, + INDEX_ID_LS, + INDEX_ID_SCE, + INDEX_ID_WM, + INDEX_ID_MSK, + INDEX_ID_NULL, }; #ifdef __cplusplus diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 9a19606d6c8..f3df9090d41 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -694,7 +694,9 @@ typedef enum eAnimEdit_Context { /* dopesheet (default) */ SACTCONT_DOPESHEET = 3, /* mask */ - SACTCONT_MASK = 4 + SACTCONT_MASK = 4, + /* cache file */ + SACTCONT_CACHEFILE = 5, } eAnimEdit_Context; /* SpaceAction AutoSnap Settings (also used by other Animation Editors) */ diff --git a/source/blender/makesdna/DNA_cachefile_types.h b/source/blender/makesdna/DNA_cachefile_types.h new file mode 100644 index 00000000000..dd47d63fc19 --- /dev/null +++ b/source/blender/makesdna/DNA_cachefile_types.h @@ -0,0 +1,85 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Kevin Dietrich. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file DNA_cachefile_types.h + * \ingroup DNA + */ + +#ifndef __DNA_CACHEFILE_TYPES_H__ +#define __DNA_CACHEFILE_TYPES_H__ + +#include "DNA_ID.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* CacheFile::flag */ +enum { + CACHEFILE_DS_EXPAND = (1 << 0), +}; + +/* CacheFile::draw_flag */ +enum { + CACHEFILE_KEYFRAME_DRAWN = (1 << 0), +}; + +typedef struct AlembicObjectPath { + struct AlembicObjectPath *next, *prev; + + char path[1024]; /* 1024 = FILE_MAX, might use PATH_MAX in the future. */ +} AlembicObjectPath; + +typedef struct CacheFile { + ID id; + struct AnimData *adt; + + struct AbcArchiveHandle *handle; + void *handle_mutex; + + /* Paths of the objects inside of the Alembic archive referenced by this + * CacheFile. */ + ListBase object_paths; + + char filepath[1024]; /* 1024 = FILE_MAX */ + + char is_sequence; + char forward_axis; + char up_axis; + char override_frame; + + float scale; + float frame; /* The frame/time to lookup in the cache file. */ + + short flag; /* Animation flag. */ + short draw_flag; +} CacheFile; + +#ifdef __cplusplus +} +#endif + +#endif /* __DNA_CACHEFILE_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 5fcd374b21f..fc4e7de73f5 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -458,6 +458,12 @@ typedef struct bObjectSolverConstraint { struct Object *camera; } bObjectSolverConstraint; +/* Transform matrix cache constraint */ +typedef struct bTransformCacheConstraint { + struct CacheFile *cache_file; + char object_path[1024]; /* FILE_MAX */ +} bTransformCacheConstraint; + /* ------------------------------------------ */ /* bConstraint->type @@ -494,6 +500,7 @@ typedef enum eBConstraint_Types { CONSTRAINT_TYPE_FOLLOWTRACK = 26, /* Follow Track Constraint */ CONSTRAINT_TYPE_CAMERASOLVER = 27, /* Camera Solver Constraint */ CONSTRAINT_TYPE_OBJECTSOLVER = 28, /* Object Solver Constraint */ + CONSTRAINT_TYPE_TRANSFORM_CACHE = 29, /* Transform Cache Constraint */ /* NOTE: no constraints are allowed to be added after this */ NUM_CONSTRAINT_TYPES diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h index a2981c0aa76..9e9ab974b01 100644 --- a/source/blender/makesdna/DNA_genfile.h +++ b/source/blender/makesdna/DNA_genfile.h @@ -100,6 +100,7 @@ void *DNA_struct_reconstruct( int DNA_elem_array_size(const char *str); int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name); +bool DNA_struct_find(const struct SDNA *sdna, const char *stype); bool DNA_struct_elem_find(const struct SDNA *sdna, const char *stype, const char *vartype, const char *name); diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index f1546053c5c..773d203bdb3 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -298,9 +298,8 @@ typedef struct bGPdata { char pad[6]; /* padding for compiler alignment error */ short sflag; /* settings for palette color */ - /* saved paletes and brushes */ + /* saved palettes */ ListBase palettes; - //ListBase brushes; } bGPdata; /* bGPdata->flag */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index bbc8edf4344..0424dc98a25 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -85,6 +85,7 @@ typedef enum ModifierType { eModifierType_DataTransfer = 49, eModifierType_NormalEdit = 50, eModifierType_CorrectiveSmooth = 51, + eModifierType_MeshSequenceCache = 52, NUM_MODIFIER_TYPES } ModifierType; @@ -1541,4 +1542,25 @@ enum { MOD_NORMALEDIT_MIX_MUL = 3, }; +typedef struct MeshSeqCacheModifierData { + ModifierData modifier; + + struct CacheFile *cache_file; + char object_path[1024]; /* 1024 = FILE_MAX */ + + char read_flag; + char pad[7]; +} MeshSeqCacheModifierData; + +/* MeshSeqCacheModifierData.read_flag */ +enum { + MOD_MESHSEQ_READ_VERT = (1 << 0), + MOD_MESHSEQ_READ_POLY = (1 << 1), + MOD_MESHSEQ_READ_UV = (1 << 2), + MOD_MESHSEQ_READ_COLOR = (1 << 3), +}; + +#define MOD_MESHSEQ_READ_ALL \ + (MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY | MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR) + #endif /* __DNA_MODIFIER_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 7c2308860da..85903cabd1a 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -349,7 +349,7 @@ typedef struct DupliObject { /* persistent identifier for a dupli object, for inter-frame matching of * objects with motion blur, or inter-update matching for syncing */ - int persistent_id[8]; /* MAX_DUPLI_RECUR */ + int persistent_id[16]; /* 2*MAX_DUPLI_RECUR */ /* particle this dupli was generated from */ struct ParticleSystem *particle_system; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 90e8d8b8270..9f18a702aef 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1738,9 +1738,11 @@ typedef struct Scene { #define R_STAMP_CAMERALENS 0x0800 #define R_STAMP_STRIPMETA 0x1000 #define R_STAMP_MEMORY 0x2000 +#define R_STAMP_HIDE_LABELS 0x4000 #define R_STAMP_ALL (R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_CAMERA|R_STAMP_SCENE| \ R_STAMP_NOTE|R_STAMP_MARKER|R_STAMP_FILENAME|R_STAMP_SEQSTRIP| \ - R_STAMP_RENDERTIME|R_STAMP_CAMERALENS|R_STAMP_MEMORY) + R_STAMP_RENDERTIME|R_STAMP_CAMERALENS|R_STAMP_MEMORY| \ + R_STAMP_HIDE_LABELS) /* alphamode */ #define R_ADDSKY 0 @@ -2088,6 +2090,8 @@ typedef enum eGPencil_Flags { GP_TOOL_FLAG_PAINTSESSIONS_ON = (1 << 0), /* When creating new frames, the last frame gets used as the basis for the new one */ GP_TOOL_FLAG_RETAIN_LAST = (1 << 1), + /* Add the strokes below all strokes in the layer */ + GP_TOOL_FLAG_PAINT_ONBACK = (1 << 2) } eGPencil_Flags; /* toolsettings->gpencil_src */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 4ce0f369ebd..41188c2412f 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -738,6 +738,7 @@ typedef enum eFileSel_File_Types { FILE_TYPE_COLLADA = (1 << 13), FILE_TYPE_OPERATOR = (1 << 14), /* from filter_glob operator property */ FILE_TYPE_APPLICATIONBUNDLE = (1 << 15), + FILE_TYPE_ALEMBIC = (1 << 16), FILE_TYPE_DIR = (1 << 30), /* An FS directory (i.e. S_ISDIR on its path is true). */ FILE_TYPE_BLENDERLIB = (1 << 31), diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 9888b735b8b..42b72c1ff93 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -158,7 +158,10 @@ typedef struct MovieTrackingTrack { * Used to prevent jumps of the camera when tracks are appearing or * disappearing. */ - float weight, pad; + float weight; + + /* track weight especially for 2D stabilization */ + float weight_stab; } MovieTrackingTrack; typedef struct MovieTrackingPlaneMarker { @@ -250,19 +253,24 @@ typedef struct MovieTrackingSettings { typedef struct MovieTrackingStabilization { int flag; - int tot_track, act_track; /* total number and index of active track in list */ + int tot_track, act_track; /* total number of translation tracks and index of active track in list */ + int tot_rot_track, act_rot_track; /* total number of rotation tracks and index of active track in list */ /* 2d stabilization */ float maxscale; /* max auto-scale factor */ - MovieTrackingTrack *rot_track; /* track used to stabilize rotation */ + MovieTrackingTrack *rot_track DNA_DEPRECATED; /* use TRACK_USE_2D_STAB_ROT on individual tracks instead */ + + int anchor_frame; /* reference point to anchor stabilization offset */ + float target_pos[2]; /* expected target position of frame after raw stabilization, will be subtracted */ + float target_rot; /* expected target rotation of frame after raw stabilization, will be compensated */ + float scale; /* zoom factor known to be present on original footage. Also used for autoscale */ float locinf, scaleinf, rotinf; /* influence on location, scale and rotation */ int filter; /* filter used for pixel interpolation */ - /* some pre-computing run-time variables */ - int ok; /* are precomputed values and scaled buf relevant? */ - float scale; /* autoscale factor */ + /* initialization and run-time data */ + int ok DNA_DEPRECATED; /* Without effect now, we initialize on every frame. Formerly used for caching of init values */ } MovieTrackingStabilization; typedef struct MovieTrackingReconstruction { @@ -386,7 +394,8 @@ enum { TRACK_USE_2D_STAB = (1 << 8), TRACK_PREVIEW_GRAYSCALE = (1 << 9), TRACK_DOPE_SEL = (1 << 10), - TRACK_PREVIEW_ALPHA = (1 << 11) + TRACK_PREVIEW_ALPHA = (1 << 11), + TRACK_USE_2D_STAB_ROT = (1 << 12) }; /* MovieTrackingTrack->motion_model */ @@ -452,7 +461,9 @@ enum { enum { TRACKING_2D_STABILIZATION = (1 << 0), TRACKING_AUTOSCALE = (1 << 1), - TRACKING_STABILIZE_ROTATION = (1 << 2) + TRACKING_STABILIZE_ROTATION = (1 << 2), + TRACKING_STABILIZE_SCALE = (1 << 3), + TRACKING_SHOW_STAB_TRACKS = (1 << 5) }; /* MovieTrackingStrabilization->filter */ diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 6a41591e051..96085a79eff 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -1294,6 +1294,11 @@ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const ch return (int)((intptr_t)cp); } +bool DNA_struct_find(const SDNA *sdna, const char *stype) +{ + return DNA_struct_find_nr(sdna, stype) != -1; +} + bool DNA_struct_elem_find(const SDNA *sdna, const char *stype, const char *vartype, const char *name) { const int SDNAnr = DNA_struct_find_nr(sdna, stype); diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index b78299316e1..2cea8715a65 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -129,6 +129,7 @@ static const char *includefiles[] = { "DNA_rigidbody_types.h", "DNA_freestyle_types.h", "DNA_linestyle_types.h", + "DNA_cachefile_types.h", /* see comment above before editing! */ /* empty string to indicate end of includefiles */ @@ -1340,4 +1341,5 @@ int main(int argc, char **argv) #include "DNA_rigidbody_types.h" #include "DNA_freestyle_types.h" #include "DNA_linestyle_types.h" +#include "DNA_cachefile_types.h" /* end of list */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 62e2018c67d..9cbe132282f 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -95,6 +95,8 @@ extern StructRNA RNA_Brush; extern StructRNA RNA_BrushTextureSlot; extern StructRNA RNA_BuildModifier; extern StructRNA RNA_MeshCacheModifier; +extern StructRNA RNA_MeshSequenceCacheModifier; +extern StructRNA RNA_CacheFile; extern StructRNA RNA_Camera; extern StructRNA RNA_CastModifier; extern StructRNA RNA_ChildOfConstraint; @@ -420,6 +422,7 @@ extern StructRNA RNA_MovieClipSequence; extern StructRNA RNA_MovieTracking; extern StructRNA RNA_MovieTrackingObject; extern StructRNA RNA_MovieTrackingTrack; +extern StructRNA RNA_MovieTrackingStabilization; extern StructRNA RNA_MulticamSequence; extern StructRNA RNA_MultiresModifier; extern StructRNA RNA_MusgraveTexture; diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 7ae3d552916..1c9b3593d17 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -198,6 +198,8 @@ extern EnumPropertyItem rna_enum_dt_mix_mode_items[]; extern EnumPropertyItem rna_enum_dt_layers_select_src_items[]; extern EnumPropertyItem rna_enum_dt_layers_select_dst_items[]; +extern EnumPropertyItem rna_enum_abc_compression_items[]; + /* API calls */ int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo); diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 7bfac9d0605..0f3ea27a7f9 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -38,6 +38,7 @@ set(DEFSRC rna_armature.c rna_boid.c rna_brush.c + rna_cachefile.c rna_camera.c rna_cloth.c rna_color.c @@ -290,6 +291,13 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_ALEMBIC) + list(APPEND INC + ../../alembic + ) + add_definitions(-DWITH_ALEMBIC) +endif() + if(WITH_BULLET) list(APPEND INC ../../../../intern/rigidbody @@ -319,6 +327,10 @@ if(WITH_OPENVDB) endif() endif() +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif() + # Build makesrna executable blender_include_dirs( . diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index f9a46409aea..569c1ee5f3f 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -50,7 +50,7 @@ #ifndef NDEBUG void BLI_system_backtrace(FILE *fp) { - (void)fp; + (void)fp; } #endif @@ -3301,6 +3301,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_armature.c", "rna_armature_api.c", RNA_def_armature}, {"rna_boid.c", NULL, RNA_def_boid}, {"rna_brush.c", NULL, RNA_def_brush}, + {"rna_cachefile.c", NULL, RNA_def_cachefile}, {"rna_camera.c", "rna_camera_api.c", RNA_def_camera}, {"rna_cloth.c", NULL, RNA_def_cloth}, {"rna_color.c", NULL, RNA_def_color}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 8ad6713192a..ab124b361f1 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -52,6 +52,7 @@ EnumPropertyItem rna_enum_id_type_items[] = { {ID_AR, "ARMATURE", ICON_ARMATURE_DATA, "Armature", ""}, {ID_BR, "BRUSH", ICON_BRUSH_DATA, "Brush", ""}, {ID_CA, "CAMERA", ICON_CAMERA_DATA, "Camera", ""}, + {ID_CF, "CACHEFILE", ICON_FILE, "Cache File", ""}, {ID_CU, "CURVE", ICON_CURVE_DATA, "Curve", ""}, {ID_VF, "FONT", ICON_FONT_DATA, "Font", ""}, {ID_GD, "GREASEPENCIL", ICON_GREASEPENCIL, "Grease Pencil", ""}, @@ -139,6 +140,7 @@ short RNA_type_to_ID_code(StructRNA *type) if (RNA_struct_is_a(type, &RNA_Action)) return ID_AC; if (RNA_struct_is_a(type, &RNA_Armature)) return ID_AR; if (RNA_struct_is_a(type, &RNA_Brush)) return ID_BR; + if (RNA_struct_is_a(type, &RNA_CacheFile)) return ID_CF; if (RNA_struct_is_a(type, &RNA_Camera)) return ID_CA; if (RNA_struct_is_a(type, &RNA_Curve)) return ID_CU; if (RNA_struct_is_a(type, &RNA_GreasePencil)) return ID_GD; @@ -179,6 +181,7 @@ StructRNA *ID_code_to_RNA_type(short idcode) case ID_AR: return &RNA_Armature; case ID_BR: return &RNA_Brush; case ID_CA: return &RNA_Camera; + case ID_CF: return &RNA_CacheFile; case ID_CU: return &RNA_Curve; case ID_GD: return &RNA_GreasePencil; case ID_GR: return &RNA_Group; @@ -383,15 +386,15 @@ int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assig } } -static void rna_IDMaterials_append_id(ID *id, Material *ma) +static void rna_IDMaterials_append_id(ID *id, Main *bmain, Material *ma) { - BKE_material_append_id(id, ma); + BKE_material_append_id(bmain, id, ma); WM_main_add_notifier(NC_OBJECT | ND_DRAW, id); WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id); } -static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i, int remove_material_slot) +static Material *rna_IDMaterials_pop_id(ID *id, Main *bmain, ReportList *reports, int index_i, int remove_material_slot) { Material *ma; short *totcol = give_totcolp_id(id); @@ -405,7 +408,7 @@ static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i return NULL; } - ma = BKE_material_pop_id(id, index_i, remove_material_slot); + ma = BKE_material_pop_id(bmain, id, index_i, remove_material_slot); if (*totcol == totcol_orig) { BKE_report(reports, RPT_ERROR, "No material to removed"); @@ -421,7 +424,7 @@ static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i static void rna_IDMaterials_clear_id(ID *id, int remove_material_slot) { - BKE_material_clear_id(id, remove_material_slot); + BKE_material_clear_id(G.main, id, remove_material_slot); DAG_id_tag_update(id, OB_RECALC_DATA); WM_main_add_notifier(NC_OBJECT | ND_DRAW, id); @@ -817,12 +820,13 @@ static void rna_def_ID_materials(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "ID Materials", "Collection of materials"); func = RNA_def_function(srna, "append", "rna_IDMaterials_append_id"); + RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Add a new material to the data block"); parm = RNA_def_pointer(func, "material", "Material", "", "Material to add"); RNA_def_property_flag(parm, PROP_REQUIRED); func = RNA_def_function(srna, "pop", "rna_IDMaterials_pop_id"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Remove a material from the data block"); parm = RNA_def_int(func, "index", -1, -MAXMAT, MAXMAT, "", "Index of material to remove", 0, MAXMAT); RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned"); diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c new file mode 100644 index 00000000000..7249ebd5feb --- /dev/null +++ b/source/blender/makesrna/intern/rna_cachefile.c @@ -0,0 +1,169 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Kevin Dietrich. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "DNA_cachefile_types.h" +#include "DNA_scene_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + +#ifdef RNA_RUNTIME + +#include "BKE_cachefile.h" +#include "BKE_depsgraph.h" + +#include "DEG_depsgraph.h" + +#include "WM_api.h" +#include "WM_types.h" + +#ifdef WITH_ALEMBIC +# include "../../../alembic/ABC_alembic.h" +#endif + +static void rna_CacheFile_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + CacheFile *cache_file = (CacheFile *)ptr->data; + + DAG_id_tag_update(&cache_file->id, 0); + WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); + + UNUSED_VARS(bmain, scene); +} + +static void rna_CacheFile_update_handle(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + CacheFile *cache_file = ptr->data; + + BKE_cachefile_reload(bmain, cache_file); + + rna_CacheFile_update(bmain, scene, ptr); +} + +static void rna_CacheFile_object_paths_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + CacheFile *cache_file = (CacheFile *)ptr->data; + rna_iterator_listbase_begin(iter, &cache_file->object_paths, NULL); +} + +#else + +/* cachefile.object_paths */ +static void rna_def_alembic_object_path(BlenderRNA *brna) +{ + StructRNA *srna = RNA_def_struct(brna, "AlembicObjectPath", NULL); + RNA_def_struct_sdna(srna, "AlembicObjectPath"); + RNA_def_struct_ui_text(srna, "Object Path", "Path of an object inside of an Alembic archive"); + RNA_def_struct_ui_icon(srna, ICON_NONE); + + PropertyRNA *prop = RNA_def_property(srna, "path", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Path", "Object path"); + RNA_def_struct_name_property(srna, prop); +} + +/* cachefile.object_paths */ +static void rna_def_cachefile_object_paths(BlenderRNA *brna, PropertyRNA *cprop) +{ + RNA_def_property_srna(cprop, "AlembicObjectPaths"); + StructRNA *srna = RNA_def_struct(brna, "AlembicObjectPaths", NULL); + RNA_def_struct_sdna(srna, "CacheFile"); + RNA_def_struct_ui_text(srna, "Object Paths", "Collection of object paths"); +} + +static void rna_def_cachefile(BlenderRNA *brna) +{ + StructRNA *srna = RNA_def_struct(brna, "CacheFile", "ID"); + RNA_def_struct_sdna(srna, "CacheFile"); + RNA_def_struct_ui_text(srna, "CacheFile", ""); + RNA_def_struct_ui_icon(srna, ICON_FILE); + + PropertyRNA *prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); + RNA_def_property_ui_text(prop, "File Path", "Path to external displacements file"); + RNA_def_property_update(prop, 0, "rna_CacheFile_update_handle"); + + prop = RNA_def_property(srna, "is_sequence", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Sequence", "Whether the cache is separated in a series of files"); + RNA_def_property_update(prop, 0, "rna_CacheFile_update"); + + /* ----------------- For Scene time ------------------- */ + + prop = RNA_def_property(srna, "override_frame", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Override Frame", + "Whether to use a custom frame for looking up data in the cache file," + " instead of using the current scene frame"); + RNA_def_property_update(prop, 0, "rna_CacheFile_update"); + + prop = RNA_def_property(srna, "frame", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "frame"); + RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); + RNA_def_property_ui_text(prop, "Frame", "The time to use for looking up the data in the cache file," + " or to determine which file to use in a file sequence"); + RNA_def_property_update(prop, 0, "rna_CacheFile_update"); + + /* ----------------- Axis Conversion ----------------- */ + + prop = RNA_def_property(srna, "forward_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "forward_axis"); + RNA_def_property_enum_items(prop, rna_enum_object_axis_items); + RNA_def_property_ui_text(prop, "Forward", ""); + RNA_def_property_update(prop, 0, "rna_CacheFile_update"); + + prop = RNA_def_property(srna, "up_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "up_axis"); + RNA_def_property_enum_items(prop, rna_enum_object_axis_items); + RNA_def_property_ui_text(prop, "Up", ""); + RNA_def_property_update(prop, 0, "rna_CacheFile_update"); + + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_range(prop, 0.0001f, 1000.0f); + RNA_def_property_ui_text(prop, "Scale", "Value by which to enlarge or shrink the object with respect to the world's origin" + " (only applicable through a Transform Cache constraint)"); + RNA_def_property_update(prop, 0, "rna_CacheFile_update"); + + /* object paths */ + prop = RNA_def_property(srna, "object_paths", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "object_paths", NULL); + RNA_def_property_collection_funcs(prop, "rna_CacheFile_object_paths_begin", "rna_iterator_listbase_next", + "rna_iterator_listbase_end", "rna_iterator_listbase_get", + NULL, NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "AlembicObjectPath"); + RNA_def_property_srna(prop, "AlembicObjectPaths"); + RNA_def_property_ui_text(prop, "Object Paths", "Paths of the objects inside the Alembic archive"); + rna_def_cachefile_object_paths(brna, prop); + + rna_def_animdata_common(srna); +} + +void RNA_def_cachefile(BlenderRNA *brna) +{ + rna_def_cachefile(brna); + rna_def_alembic_object_path(brna); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 781e44c9ed6..d8bcbc2cc72 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -56,6 +56,12 @@ static void rna_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); } +static void rna_cloth_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + DAG_relations_tag_update(bmain); + rna_cloth_update(bmain, scene, ptr); +} + static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; @@ -68,6 +74,16 @@ static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); } +static void rna_ClothSettings_bending_set(struct PointerRNA *ptr, float value) +{ + ClothSimSettings *settings = (ClothSimSettings *)ptr->data; + + settings->bending = value; + + /* check for max clipping */ + if (value > settings->max_bend) + settings->max_bend = value; +} static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value) { @@ -80,6 +96,17 @@ static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value) settings->max_bend = value; } +static void rna_ClothSettings_structural_set(struct PointerRNA *ptr, float value) +{ + ClothSimSettings *settings = (ClothSimSettings *)ptr->data; + + settings->structural = value; + + /* check for max clipping */ + if (value > settings->max_struct) + settings->max_struct = value; +} + static void rna_ClothSettings_max_struct_set(struct PointerRNA *ptr, float value) { ClothSimSettings *settings = (ClothSimSettings *)ptr->data; @@ -493,6 +520,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "structural"); RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_structural_set", NULL); RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure"); RNA_def_property_update(prop, 0, "rna_cloth_update"); @@ -521,6 +549,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "bending"); RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_bending_set", NULL); RNA_def_property_ui_text(prop, "Bending Stiffness", "Wrinkle coefficient (higher = less smaller but more big wrinkles)"); RNA_def_property_update(prop, 0, "rna_cloth_update"); @@ -706,7 +735,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group"); - RNA_def_property_update(prop, 0, "rna_cloth_update"); + RNA_def_property_update(prop, 0, "rna_cloth_dependency_update"); prop = RNA_def_property(srna, "vertex_group_self_collisions", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_CollSettings_selfcol_vgroup_get", "rna_CollSettings_selfcol_vgroup_length", diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 98560bf3452..db3f76f3cfc 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -72,6 +72,8 @@ EnumPropertyItem rna_enum_constraint_type_items[] = { "Compensate for scaling one axis by applying suitable scaling to the other two axes"}, {CONSTRAINT_TYPE_TRANSFORM, "TRANSFORM", ICON_CONSTRAINT_DATA, "Transformation", "Use one transform property from target to control another (or same) property on owner"}, + {CONSTRAINT_TYPE_TRANSFORM_CACHE, "TRANSFORM_CACHE", ICON_CONSTRAINT_DATA, "Transform Cache", + "Look up the transformation matrix from an external file"}, {0, "", 0, N_("Tracking"), ""}, {CONSTRAINT_TYPE_CLAMPTO, "CLAMP_TO", ICON_CONSTRAINT_DATA, "Clamp To", "Restrict movements to lie along a curve by remapping location along curve's longest axis"}, @@ -214,6 +216,8 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr) return &RNA_CameraSolverConstraint; case CONSTRAINT_TYPE_OBJECTSOLVER: return &RNA_ObjectSolverConstraint; + case CONSTRAINT_TYPE_TRANSFORM_CACHE: + return &RNA_TransformCacheConstraint; default: return &RNA_UnknownType; } @@ -2571,6 +2575,27 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna) "rna_Constraint_cameraObject_poll"); } +static void rna_def_constraint_transform_cache(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "TransformCacheConstraint", "Constraint"); + RNA_def_struct_ui_text(srna, "Transform Cache Constraint", "Look up transformation from an external file"); + RNA_def_struct_sdna_from(srna, "bTransformCacheConstraint", "data"); + + prop = RNA_def_property(srna, "cache_file", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "cache_file"); + RNA_def_property_struct_type(prop, "CacheFile"); + RNA_def_property_ui_text(prop, "Cache File", ""); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_update(prop, 0, "rna_Constraint_dependency_update"); + + prop = RNA_def_property(srna, "object_path", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Object Path", "Path to the object in the Alembic archive used to lookup the transform matrix"); + RNA_def_property_update(prop, 0, "rna_Constraint_update"); +} + /* base struct for constraints */ void RNA_def_constraint(BlenderRNA *brna) { @@ -2687,6 +2712,7 @@ void RNA_def_constraint(BlenderRNA *brna) rna_def_constraint_follow_track(brna); rna_def_constraint_camera_solver(brna); rna_def_constraint_object_solver(brna); + rna_def_constraint_transform_cache(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index fb4ff6f4856..f4fb30e0793 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -1273,7 +1273,7 @@ static void rna_def_curve_spline_bezpoints(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_srna(cprop, "SplineBezierPoints"); srna = RNA_def_struct(brna, "SplineBezierPoints", NULL); RNA_def_struct_sdna(srna, "Nurb"); - RNA_def_struct_ui_text(srna, "Spline Bezier Points", "Collection of spline bezirt points"); + RNA_def_struct_ui_text(srna, "Spline Bezier Points", "Collection of spline Bezier points"); func = RNA_def_function(srna, "add", "rna_Curve_spline_bezpoints_add"); RNA_def_function_ui_description(func, "Add a number of points to this spline"); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 619eecad8e5..7eaf8b65902 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -323,7 +323,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value) static int rna_GPencil_active_layer_index_get(PointerRNA *ptr) { bGPdata *gpd = (bGPdata *)ptr->id.data; - bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); return BLI_findindex(&gpd->layers, gpl); } @@ -333,7 +333,7 @@ static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value) bGPdata *gpd = (bGPdata *)ptr->id.data; bGPDlayer *gpl = BLI_findlink(&gpd->layers, value); - gpencil_layer_setactive(gpd, gpl); + BKE_gpencil_layer_setactive(gpd, gpl); } static void rna_GPencil_active_layer_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) @@ -366,7 +366,7 @@ static void rna_GPencil_use_onion_skinning_set(PointerRNA *ptr, const int value) /* set new value */ if (value) { /* enable on active layer (it's the one that's most likely to be of interest right now) */ - gpl = gpencil_layer_getactive(gpd); + gpl = BKE_gpencil_layer_getactive(gpd); if (gpl) { gpl->flag |= GP_LAYER_ONIONSKIN; } @@ -435,16 +435,27 @@ static void rna_GPencil_stroke_point_select_set(PointerRNA *ptr, const int value pt->flag &= ~GP_SPOINT_SELECT; /* Check if the stroke should be selected or not... */ - gpencil_stroke_sync_selection(gps); + BKE_gpencil_stroke_sync_selection(gps); } } -static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count) +static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count, float pressure, float strength) { if (count > 0) { + /* create space at the end of the array for extra points */ stroke->points = MEM_recallocN_id(stroke->points, sizeof(bGPDspoint) * (stroke->totpoints + count), "gp_stroke_points"); + + /* init the pressure and strength values so that old scripts won't need to + * be modified to give these initial values... + */ + for (int i = 0; i < count; i++) { + bGPDspoint *pt = stroke->points + (stroke->totpoints + i); + pt->pressure = pressure; + pt->strength = strength; + } + stroke->totpoints += count; } } @@ -482,7 +493,9 @@ static void rna_GPencil_stroke_point_pop(bGPDstroke *stroke, ReportList *reports static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame, const char *colorname) { bGPDstroke *stroke = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); - strcpy(stroke->colorname, colorname); + if (colorname) { + BLI_strncpy(stroke->colorname, colorname, sizeof(stroke->colorname)); + } stroke->palcolor = NULL; stroke->flag |= GP_STROKE_RECALC_COLOR; BLI_addtail(&frame->strokes, stroke); @@ -534,7 +547,7 @@ static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer, ReportList *reports, i return NULL; } - frame = gpencil_frame_addnew(layer, frame_number); + frame = BKE_gpencil_frame_addnew(layer, frame_number); WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); @@ -549,7 +562,7 @@ static void rna_GPencil_frame_remove(bGPDlayer *layer, ReportList *reports, Poin return; } - gpencil_layer_delframe(layer, frame); + BKE_gpencil_layer_delframe(layer, frame); RNA_POINTER_INVALIDATE(frame_ptr); WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); @@ -557,7 +570,7 @@ static void rna_GPencil_frame_remove(bGPDlayer *layer, ReportList *reports, Poin static bGPDframe *rna_GPencil_frame_copy(bGPDlayer *layer, bGPDframe *src) { - bGPDframe *frame = gpencil_frame_duplicate(src); + bGPDframe *frame = BKE_gpencil_frame_duplicate(src); while (BKE_gpencil_layer_find_frame(layer, frame->framenum)) { frame->framenum++; @@ -572,7 +585,7 @@ static bGPDframe *rna_GPencil_frame_copy(bGPDlayer *layer, bGPDframe *src) static bGPDlayer *rna_GPencil_layer_new(bGPdata *gpd, const char *name, int setactive) { - bGPDlayer *gl = gpencil_layer_addnew(gpd, name, setactive != 0); + bGPDlayer *gl = BKE_gpencil_layer_addnew(gpd, name, setactive != 0); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -587,7 +600,7 @@ static void rna_GPencil_layer_remove(bGPdata *gpd, ReportList *reports, PointerR return; } - gpencil_layer_delete(gpd, layer); + BKE_gpencil_layer_delete(gpd, layer); RNA_POINTER_INVALIDATE(layer_ptr); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -595,21 +608,21 @@ static void rna_GPencil_layer_remove(bGPdata *gpd, ReportList *reports, PointerR static void rna_GPencil_frame_clear(bGPDframe *frame) { - free_gpencil_strokes(frame); + BKE_gpencil_free_strokes(frame); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } static void rna_GPencil_layer_clear(bGPDlayer *layer) { - free_gpencil_frames(layer); + BKE_gpencil_free_frames(layer); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } static void rna_GPencil_clear(bGPdata *gpd) { - free_gpencil_layers(&gpd->layers); + BKE_gpencil_free_layers(&gpd->layers); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } @@ -617,7 +630,7 @@ static void rna_GPencil_clear(bGPdata *gpd) /* Palettes */ static bGPDpalette *rna_GPencil_palette_new(bGPdata *gpd, const char *name, int setactive) { - bGPDpalette *palette = gpencil_palette_addnew(gpd, name, setactive != 0); + bGPDpalette *palette = BKE_gpencil_palette_addnew(gpd, name, setactive != 0); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -632,7 +645,7 @@ static void rna_GPencil_palette_remove(bGPdata *gpd, ReportList *reports, Pointe return; } - gpencil_palette_delete(gpd, palette); + BKE_gpencil_palette_delete(gpd, palette); RNA_POINTER_INVALIDATE(palette_ptr); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -675,7 +688,7 @@ static void rna_GPencil_active_palette_set(PointerRNA *ptr, PointerRNA value) } } /* force color recalc */ - gpencil_palette_change_strokes(gpd); + BKE_gpencil_palette_change_strokes(gpd); WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } @@ -684,7 +697,7 @@ static void rna_GPencil_active_palette_set(PointerRNA *ptr, PointerRNA value) static int rna_GPencilPalette_index_get(PointerRNA *ptr) { bGPdata *gpd = (bGPdata *)ptr->id.data; - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); return BLI_findindex(&gpd->palettes, palette); } @@ -694,7 +707,7 @@ static void rna_GPencilPalette_index_set(PointerRNA *ptr, int value) bGPdata *gpd = (bGPdata *)ptr->id.data; bGPDpalette *palette = BLI_findlink(&gpd->palettes, value); - gpencil_palette_setactive(gpd, palette); + BKE_gpencil_palette_setactive(gpd, palette); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } @@ -712,7 +725,7 @@ static void rna_GPencilPalette_index_range(PointerRNA *ptr, int *min, int *max, /* Palette colors */ static bGPDpalettecolor *rna_GPencilPalette_color_new(bGPDpalette *palette) { - bGPDpalettecolor *color = gpencil_palettecolor_addnew(palette, DATA_("Color"), true); + bGPDpalettecolor *color = BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true); return color; } @@ -726,7 +739,7 @@ static void rna_GPencilPalette_color_remove(bGPDpalette *palette, ReportList *re return; } - gpencil_palettecolor_delete(palette, color); + BKE_gpencil_palettecolor_delete(palette, color); RNA_POINTER_INVALIDATE(color_ptr); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -755,7 +768,7 @@ static void rna_GPencilPalette_active_color_set(PointerRNA *ptr, PointerRNA valu bGPDpalette *palette = (bGPDpalette *)ptr->data; bGPDpalettecolor *color = value.data; - gpencil_palettecolor_setactive(palette, color); + BKE_gpencil_palettecolor_setactive(palette, color); } static void rna_GPencilPalette_info_set(PointerRNA *ptr, const char *value) @@ -773,7 +786,7 @@ static void rna_GPencilPalette_info_set(PointerRNA *ptr, const char *value) static char *rna_GPencilPalette_color_path(PointerRNA *ptr) { bGPdata *gpd = ptr->id.data; - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); bGPDpalettecolor *palcolor = ptr->data; char name_palette[sizeof(palette->info) * 2]; @@ -788,11 +801,11 @@ static char *rna_GPencilPalette_color_path(PointerRNA *ptr) static void rna_GPencilPaletteColor_info_set(PointerRNA *ptr, const char *value) { bGPdata *gpd = ptr->id.data; - bGPDpalette *palette = gpencil_palette_getactive(gpd); + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); bGPDpalettecolor *palcolor = ptr->data; /* rename all strokes */ - gpencil_palettecolor_changename(gpd, palcolor->info, value); + BKE_gpencil_palettecolor_changename(gpd, palcolor->info, value); /* copy the new name into the name slot */ BLI_strncpy_utf8(palcolor->info, value, sizeof(palcolor->info)); @@ -824,7 +837,7 @@ static int rna_GPencilPaletteColor_is_fill_visible_get(PointerRNA *ptr) static int rna_GPencilPaletteColor_index_get(PointerRNA *ptr) { bGPDpalette *palette = (bGPDpalette *)ptr->data; - bGPDpalettecolor *pcolor = gpencil_palettecolor_getactive(palette); + bGPDpalettecolor *pcolor = BKE_gpencil_palettecolor_getactive(palette); return BLI_findindex(&palette->colors, pcolor); } @@ -833,7 +846,7 @@ static void rna_GPencilPaletteColor_index_set(PointerRNA *ptr, int value) { bGPDpalette *palette = (bGPDpalette *)ptr->data; bGPDpalettecolor *pcolor = BLI_findlink(&palette->colors, value); - gpencil_palettecolor_setactive(palette, pcolor); + BKE_gpencil_palettecolor_setactive(palette, pcolor); } static void rna_GPencilPaletteColor_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) @@ -886,9 +899,7 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna) static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - FunctionRNA *func; - /* PropertyRNA *parm; */ RNA_def_property_srna(cprop, "GPencilStrokePoints"); srna = RNA_def_struct(brna, "GPencilStrokePoints", NULL); @@ -898,6 +909,8 @@ static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cpr func = RNA_def_function(srna, "add", "rna_GPencil_stroke_point_add"); RNA_def_function_ui_description(func, "Add a new grease pencil stroke point"); RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of points to add to the stroke", 0, INT_MAX); + RNA_def_float(func, "pressure", 1.0f, 0.0f, 1.0f, "Pressure", "Pressure for newly created points", 0.0f, 1.0f); + RNA_def_float(func, "strength", 1.0f, 0.0f, 1.0f, "Strength", "Color intensity (alpha factor) for newly created points", 0.0f, 1.0f); func = RNA_def_function(srna, "pop", "rna_GPencil_stroke_point_pop"); RNA_def_function_ui_description(func, "Remove a grease pencil stroke point"); @@ -918,19 +931,19 @@ static void rna_def_gpencil_triangle(BlenderRNA *brna) /* point v1 */ prop = RNA_def_property(srna, "v1", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "v1"); - RNA_def_property_ui_text(prop, "v1", "First triangle vertice index"); + RNA_def_property_ui_text(prop, "v1", "First triangle vertex index"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* point v2 */ prop = RNA_def_property(srna, "v2", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "v2"); - RNA_def_property_ui_text(prop, "v2", "Second triangle vertice index"); + RNA_def_property_ui_text(prop, "v2", "Second triangle vertex index"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* point v3 */ prop = RNA_def_property(srna, "v3", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "v3"); - RNA_def_property_ui_text(prop, "v3", "Third triangle vertice index"); + RNA_def_property_ui_text(prop, "v3", "Third triangle vertex index"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); } @@ -1145,7 +1158,8 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) // TODO: replace these with a "draw type" combo (i.e. strokes only, filled strokes, strokes + fills, volumetric)? prop = RNA_def_property(srna, "use_volumetric_strokes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_VOLUMETRIC); - RNA_def_property_ui_text(prop, "Volumetric Strokes", "Draw strokes as a series of circular blobs, resulting in a volumetric effect"); + RNA_def_property_ui_text(prop, "Volumetric Strokes", + "Draw strokes as a series of circular blobs, resulting in a volumetric effect"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); prop = RNA_def_property(srna, "opacity", PROP_FLOAT, PROP_NONE); @@ -1174,7 +1188,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "thickness"); //RNA_def_property_range(prop, 1, 10); /* 10 px limit comes from Windows OpenGL limits for natively-drawn strokes */ RNA_def_property_int_funcs(prop, NULL, NULL, "rna_GPencilLayer_line_width_range"); - RNA_def_property_ui_text(prop, "Thickness", "Thickness change to apply current strokes (in pixels)"); + RNA_def_property_ui_text(prop, "Thickness", "Thickness change to apply to current strokes (in pixels)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); /* Onion-Skinning */ @@ -1241,8 +1255,8 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) prop = RNA_def_property(srna, "unlock_color", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_UNLOCK_COLOR); RNA_def_property_ui_icon(prop, ICON_RESTRICT_COLOR_OFF, 1); - RNA_def_property_ui_text(prop, "Unlock color", "Unprotect colors selected from further editing " - "and/or frame changes"); + RNA_def_property_ui_text(prop, "Unlock Color", + "Unprotect selected colors from further editing and/or frame changes"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); @@ -1299,7 +1313,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "inverse"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "MatrixInverse", "Parent inverse transformation matrix"); + RNA_def_property_ui_text(prop, "Inverse Matrix", "Parent inverse transformation matrix"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); /* read only parented flag */ @@ -1381,8 +1395,9 @@ static void rna_def_gpencil_palettecolor(BlenderRNA *brna) RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); /* Name */ - prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE); - RNA_def_property_ui_text(prop, "Info", "Color name"); + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "info"); + RNA_def_property_ui_text(prop, "Name", "Color name"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GPencilPaletteColor_info_set"); RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 161e19f581c..364aa9ba939 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -133,6 +133,7 @@ void RNA_def_armature(struct BlenderRNA *brna); void RNA_def_actuator(struct BlenderRNA *brna); void RNA_def_boid(struct BlenderRNA *brna); void RNA_def_brush(struct BlenderRNA *brna); +void RNA_def_cachefile(struct BlenderRNA *brna); void RNA_def_camera(struct BlenderRNA *brna); void RNA_def_cloth(struct BlenderRNA *brna); void RNA_def_color(struct BlenderRNA *brna); @@ -332,6 +333,7 @@ void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_cachefiles(BlenderRNA *brna, PropertyRNA *cprop); /* ID Properties */ diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index e4e3699f301..51709d3137c 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -546,7 +546,7 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area) prop = RNA_def_property(srna, "shadow_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, (spot) ? prop_spot_shadow_items : prop_shadow_items); - RNA_def_property_update(prop, 0, "rna_Lamp_update"); + RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); prop = RNA_def_property(srna, "shadow_buffer_size", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "bufsize"); diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index d8cc61bf906..9b28009d161 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -1499,14 +1499,15 @@ static void rna_def_freestyle_thickness_modifiers(BlenderRNA *brna, PropertyRNA RNA_def_property_srna(cprop, "LineStyleThicknessModifiers"); srna = RNA_def_struct(brna, "LineStyleThicknessModifiers", NULL); RNA_def_struct_sdna(srna, "FreestyleLineStyle"); - RNA_def_struct_ui_text(srna, "Thickness Modifiers", "Thickness modifiers for changing line thicknesss"); + RNA_def_struct_ui_text(srna, "Thickness Modifiers", "Thickness modifiers for changing line thickness"); func = RNA_def_function(srna, "new", "rna_LineStyle_thickness_modifier_add"); RNA_def_function_ui_description(func, "Add a thickness modifier to line style"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_string(func, "name", "ThicknessModifier", 0, "", "New name for the thickness modifier (not unique)"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_enum(func, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "", "Thickness modifier type to add"); + parm = RNA_def_enum(func, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, + "", "Thickness modifier type to add"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "modifier", "LineStyleThicknessModifier", "", "Newly added thickness modifier"); RNA_def_function_return(func, parm); @@ -1528,14 +1529,15 @@ static void rna_def_freestyle_geometry_modifiers(BlenderRNA *brna, PropertyRNA * RNA_def_property_srna(cprop, "LineStyleGeometryModifiers"); srna = RNA_def_struct(brna, "LineStyleGeometryModifiers", NULL); RNA_def_struct_sdna(srna, "FreestyleLineStyle"); - RNA_def_struct_ui_text(srna, "Geometry Modifiers", "Geometry modifiers for changing line geometrys"); + RNA_def_struct_ui_text(srna, "Geometry Modifiers", "Geometry modifiers for changing line geometries"); func = RNA_def_function(srna, "new", "rna_LineStyle_geometry_modifier_add"); RNA_def_function_ui_description(func, "Add a geometry modifier to line style"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_string(func, "name", "GeometryModifier", 0, "", "New name for the geometry modifier (not unique)"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_enum(func, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "", "Geometry modifier type to add"); + parm = RNA_def_enum(func, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, + "", "Geometry modifier type to add"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "modifier", "LineStyleGeometryModifier", "", "Newly added geometry modifier"); RNA_def_function_return(func, parm); diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index e0538d1c05b..3392d0d9b3a 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -281,6 +281,12 @@ static void rna_Main_linestyle_begin(CollectionPropertyIterator *iter, PointerRN rna_iterator_listbase_begin(iter, &bmain->linestyle, NULL); } +static void rna_Main_cachefiles_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Main *bmain = (Main *)ptr->data; + rna_iterator_listbase_begin(iter, &bmain->cachefiles, NULL); +} + static void rna_Main_version_get(PointerRNA *ptr, int *value) { Main *bmain = (Main *)ptr->data; @@ -354,6 +360,7 @@ void RNA_def_main(BlenderRNA *brna) {"movieclips", "MovieClip", "rna_Main_movieclips_begin", "Movie Clips", "Movie Clip datablocks", RNA_def_main_movieclips}, {"masks", "Mask", "rna_Main_masks_begin", "Masks", "Masks datablocks", RNA_def_main_masks}, {"linestyles", "FreestyleLineStyle", "rna_Main_linestyle_begin", "Line Styles", "Line Style datablocks", RNA_def_main_linestyles}, + {"cache_files", "CacheFile", "rna_Main_cachefiles_begin", "Cache Files", "Cache Files datablocks", RNA_def_main_cachefiles}, {NULL, NULL, NULL, NULL, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 0083207efd0..7c627e72fd5 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -535,6 +535,7 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(gpencil, gpencil, ID_GD) RNA_MAIN_ID_TAG_FUNCS_DEF(movieclips, movieclip, ID_MC) RNA_MAIN_ID_TAG_FUNCS_DEF(masks, mask, ID_MSK) RNA_MAIN_ID_TAG_FUNCS_DEF(linestyle, linestyle, ID_LS) +RNA_MAIN_ID_TAG_FUNCS_DEF(cachefiles, cachefiles, ID_CF) #undef RNA_MAIN_ID_TAG_FUNCS_DEF @@ -1548,6 +1549,21 @@ void RNA_def_main_palettes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_funcs(prop, "rna_Main_palettes_is_updated_get", NULL); } +void RNA_def_main_cachefiles(BlenderRNA *brna, PropertyRNA *cprop) +{ + RNA_def_property_srna(cprop, "BlendDataCacheFiles"); + StructRNA *srna = RNA_def_struct(brna, "BlendDataCacheFiles", NULL); + RNA_def_struct_sdna(srna, "Main"); + RNA_def_struct_ui_text(srna, "Main Cache Files", "Collection of cache files"); + + FunctionRNA *func = RNA_def_function(srna, "tag", "rna_Main_cachefiles_tag"); + PropertyRNA *parm = RNA_def_boolean(func, "value", 0, "Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + + PropertyRNA *prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_boolean_funcs(prop, "rna_Main_cachefiles_is_updated_get", NULL); +} void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; @@ -1564,7 +1580,7 @@ void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop) parm = RNA_def_boolean(func, "value", 0, "Value", ""); RNA_def_property_flag(parm, PROP_REQUIRED); - func = RNA_def_function(srna, "new", "gpencil_data_addnew"); + func = RNA_def_function(srna, "new", "BKE_gpencil_data_addnew"); RNA_def_function_flag(func, FUNC_NO_SELF); parm = RNA_def_string(func, "name", "GreasePencil", 0, "", "New name for the data-block"); RNA_def_property_flag(parm, PROP_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index e4f9f856db7..2a8cc073e22 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -1889,7 +1889,7 @@ void RNA_def_material(BlenderRNA *brna) prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "index"); - RNA_def_property_ui_text(prop, "Pass Index", "Index number for the IndexMA render pass"); + RNA_def_property_ui_text(prop, "Pass Index", "Index number for the \"Material Index\" render pass"); RNA_def_property_update(prop, NC_OBJECT, "rna_Material_update"); /* flags */ diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index a23ef6eaa82..0b55c19c374 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -30,6 +30,7 @@ #include <stdlib.h> #include "DNA_armature_types.h" +#include "DNA_cachefile_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" @@ -65,6 +66,7 @@ EnumPropertyItem rna_enum_object_modifier_type_items[] = { {0, "", 0, N_("Modify"), ""}, {eModifierType_DataTransfer, "DATA_TRANSFER", ICON_MOD_DATA_TRANSFER, "Data Transfer", ""}, {eModifierType_MeshCache, "MESH_CACHE", ICON_MOD_MESHDEFORM, "Mesh Cache", ""}, + {eModifierType_MeshSequenceCache, "MESH_SEQUENCE_CACHE", ICON_MOD_MESHDEFORM, "Mesh Sequence Cache", ""}, {eModifierType_NormalEdit, "NORMAL_EDIT", ICON_MOD_NORMALEDIT, "Normal Edit", ""}, {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""}, {eModifierType_UVWarp, "UV_WARP", ICON_MOD_UVPROJECT, "UV Warp", ""}, @@ -281,6 +283,7 @@ EnumPropertyItem rna_enum_axis_flag_xyz_items[] = { #include "DNA_curve_types.h" #include "DNA_smoke_types.h" +#include "BKE_cachefile.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_library.h" @@ -288,6 +291,10 @@ EnumPropertyItem rna_enum_axis_flag_xyz_items[] = { #include "BKE_object.h" #include "BKE_particle.h" +#ifdef WITH_ALEMBIC +# include "ABC_alembic.h" +#endif + static void rna_UVProject_projectors_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { UVProjectModifierData *uvp = (UVProjectModifierData *)ptr->data; @@ -399,6 +406,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_NormalEditModifier; case eModifierType_CorrectiveSmooth: return &RNA_CorrectiveSmoothModifier; + case eModifierType_MeshSequenceCache: + return &RNA_MeshSequenceCacheModifier; /* Default */ case eModifierType_None: case eModifierType_ShapeKey: @@ -4216,6 +4225,42 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_meshseqcache(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MeshSequenceCacheModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Cache Modifier", "Cache Mesh"); + RNA_def_struct_sdna(srna, "MeshSeqCacheModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */ + + prop = RNA_def_property(srna, "cache_file", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "cache_file"); + RNA_def_property_struct_type(prop, "CacheFile"); + RNA_def_property_ui_text(prop, "Cache File", ""); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + + prop = RNA_def_property(srna, "object_path", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Object Path", "Path to the object in the Alembic archive used to lookup geometric data"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + static EnumPropertyItem read_flag_items[] = { + {MOD_MESHSEQ_READ_VERT, "VERT", 0, "Vertex", ""}, + {MOD_MESHSEQ_READ_POLY, "POLY", 0, "Faces", ""}, + {MOD_MESHSEQ_READ_UV, "UV", 0, "UV", ""}, + {MOD_MESHSEQ_READ_COLOR, "COLOR", 0, "Color", ""}, + {0, NULL, 0, NULL, NULL} + }; + + prop = RNA_def_property(srna, "read_data", PROP_ENUM, PROP_NONE); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_enum_sdna(prop, NULL, "read_flag"); + RNA_def_property_enum_items(prop, read_flag_items); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); +} + static void rna_def_modifier_laplaciandeform(BlenderRNA *brna) { StructRNA *srna; @@ -4745,6 +4790,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_wireframe(brna); rna_def_modifier_datatransfer(brna); rna_def_modifier_normaledit(brna); + rna_def_modifier_meshseqcache(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 19d78361019..15411f85ba3 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -347,6 +347,8 @@ static void rna_def_movieclip(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings"); RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings"); RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings"); + + rna_def_animdata_common(srna); } void RNA_def_movieclip(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 2f9e6741677..a37fe049e72 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -5391,13 +5391,13 @@ static void def_cmp_double_edge_mask(StructRNA *srna) }; prop = RNA_def_property(srna, "inner_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom2"); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, InnerEdgeMode_items); RNA_def_property_ui_text(prop, "Inner Edge Mode", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "edge_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_sdna(prop, NULL, "custom2"); RNA_def_property_enum_items(prop, BufEdgeMode_items); RNA_def_property_ui_text(prop, "Buffer Edge Mode", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 32f7e5f0226..194bb1eaa14 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2652,7 +2652,7 @@ static void rna_def_object(BlenderRNA *brna) /* render */ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "index"); - RNA_def_property_ui_text(prop, "Pass Index", "Index number for the IndexOB render pass"); + RNA_def_property_ui_text(prop, "Pass Index", "Index number for the \"Object Index\" render pass"); RNA_def_property_update(prop, NC_OBJECT, "rna_Object_internal_update"); prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index f05813043ca..1d89f7535c4 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -730,6 +730,11 @@ static void rna_softbody_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); } +static void rna_softbody_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + DAG_relations_tag_update(bmain); + rna_softbody_update(bmain, scene, ptr); +} static EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) @@ -1378,7 +1383,7 @@ static void rna_def_field(BlenderRNA *brna) prop = RNA_def_property(srna, "use_absorption", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_VISIBILITY); RNA_def_property_ui_text(prop, "Absorption", "Force gets absorbed by collision objects"); - RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_dependency_update"); prop = RNA_def_property(srna, "use_multiple_springs", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_MULTIPLE_SPRINGS); @@ -1855,7 +1860,7 @@ static void rna_def_softbody(BlenderRNA *brna) prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group"); - RNA_def_property_update(prop, 0, "rna_softbody_update"); + RNA_def_property_update(prop, 0, "rna_softbody_dependency_update"); prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "effector_weights"); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index eabf41cb332..5e3fa4b467d 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -630,6 +630,12 @@ static void rna_Particle_reset(Main *bmain, Scene *scene, PointerRNA *ptr) particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET); } +static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + DAG_relations_tag_update(bmain); + rna_Particle_reset(bmain, scene, ptr); +} + static void rna_Particle_change_type(Main *bmain, Scene *scene, PointerRNA *ptr) { particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET | PSYS_RECALC_TYPE); @@ -2744,7 +2750,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group"); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); + RNA_def_property_update(prop, 0, "rna_Particle_reset_dependency"); /* global physical properties */ prop = RNA_def_property(srna, "drag_factor", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 19f25ff1ee9..fef9435b567 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -454,7 +454,7 @@ EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = { /* Grease pencil Drawing Brushes */ static bGPDbrush *rna_GPencil_brush_new(ToolSettings *ts, const char *name, int setactive) { - bGPDbrush *brush = gpencil_brush_addnew(ts, name, setactive != 0); + bGPDbrush *brush = BKE_gpencil_brush_addnew(ts, name, setactive != 0); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -469,13 +469,13 @@ static void rna_GPencil_brush_remove(ToolSettings *ts, ReportList *reports, Poin return; } - gpencil_brush_delete(ts, brush); + BKE_gpencil_brush_delete(ts, brush); RNA_POINTER_INVALIDATE(brush_ptr); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } -static PointerRNA rna_GPencil_active_brush_get(PointerRNA *ptr) +static PointerRNA rna_GPencilBrushes_active_get(PointerRNA *ptr) { ToolSettings *ts = (ToolSettings *) ptr->data; @@ -494,7 +494,7 @@ static PointerRNA rna_GPencil_active_brush_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, NULL, NULL); } -static void rna_GPencil_active_brush_set(PointerRNA *ptr, PointerRNA value) +static void rna_GPencilBrushes_active_set(PointerRNA *ptr, PointerRNA value) { ToolSettings *ts = (ToolSettings *) ptr->data; @@ -511,25 +511,25 @@ static void rna_GPencil_active_brush_set(PointerRNA *ptr, PointerRNA value) WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } -static int rna_GPencilBrush_index_get(PointerRNA *ptr) +static int rna_GPencilBrushes_index_get(PointerRNA *ptr) { ToolSettings *ts = (ToolSettings *) ptr->data; - bGPDbrush *brush = gpencil_brush_getactive(ts); + bGPDbrush *brush = BKE_gpencil_brush_getactive(ts); return BLI_findindex(&ts->gp_brushes, brush); } -static void rna_GPencilBrush_index_set(PointerRNA *ptr, int value) +static void rna_GPencilBrushes_index_set(PointerRNA *ptr, int value) { ToolSettings *ts = (ToolSettings *) ptr->data; bGPDbrush *brush = BLI_findlink(&ts->gp_brushes, value); - gpencil_brush_setactive(ts, brush); + BKE_gpencil_brush_setactive(ts, brush); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } -static void rna_GPencilBrush_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) +static void rna_GPencilBrushes_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { ToolSettings *ts = (ToolSettings *) ptr->data; @@ -542,7 +542,7 @@ static void rna_GPencilBrush_index_range(PointerRNA *ptr, int *min, int *max, in static void rna_GPencilBrush_name_set(PointerRNA *ptr, const char *value) { - ToolSettings *ts = (ToolSettings *) ptr->data; + ToolSettings *ts = ((Scene *) ptr->id.data)->toolsettings; bGPDbrush *brush = ptr->data; /* copy the new name into the name slot */ @@ -2103,8 +2103,8 @@ static void rna_def_gpencil_brush(BlenderRNA *brna) srna = RNA_def_struct(brna, "GPencilBrush", NULL); RNA_def_struct_sdna(srna, "bGPDbrush"); - RNA_def_struct_ui_text(srna, "Grease Pencil Brush", "Collection of brushes being used to control the " - "line style of new strokes"); + RNA_def_struct_ui_text(srna, "Grease Pencil Brush", + "Collection of brushes being used to control the line style of new strokes"); RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA); /* Name */ @@ -2161,39 +2161,42 @@ static void rna_def_gpencil_brush(BlenderRNA *brna) /* Angle when brush is full size */ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "draw_angle"); - RNA_def_property_range(prop, 0.0f, M_PI_2); - RNA_def_property_ui_text(prop, "Angle", "Angle of drawing when brush has full size"); + RNA_def_property_range(prop, -M_PI_2, M_PI_2); + RNA_def_property_ui_text(prop, "Angle", + "Direction of the stroke at which brush gives maximal thickness " + "(0° for horizontal)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Factor to change brush size depending of angle */ prop = RNA_def_property(srna, "angle_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "draw_angle_factor"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Angle Factor", "Factor to apply when the brush rotate of its full size"); + RNA_def_property_ui_text(prop, "Angle Factor", + "Reduce brush thickness by this factor when stroke is perpendicular to 'Angle' direction"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Smoothing factor for new strokes */ prop = RNA_def_property(srna, "pen_smooth_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "draw_smoothfac"); RNA_def_property_range(prop, 0.0, 2.0f); - RNA_def_property_ui_text(prop, "Smooth", "Amount of smoothing to apply to newly created strokes, to " - "reduce jitter/noise"); + RNA_def_property_ui_text(prop, "Smooth", + "Amount of smoothing to apply to newly created strokes, to reduce jitter/noise"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Iterations of the Smoothing factor */ prop = RNA_def_property(srna, "pen_smooth_steps", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "draw_smoothlvl"); RNA_def_property_range(prop, 1, 3); - RNA_def_property_ui_text(prop, "Iterations", "Number of times to smooth newly created strokes [+ reason/effect " - "of using higher values of this property]"); + RNA_def_property_ui_text(prop, "Iterations", + "Number of times to smooth newly created strokes"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Subdivision level for new strokes */ prop = RNA_def_property(srna, "pen_subdivision_steps", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sublevel"); RNA_def_property_range(prop, 0, 3); - RNA_def_property_ui_text(prop, "Subdivision Steps", "Number of times to subdivide newly created strokes, for " - "less jagged strokes"); + RNA_def_property_ui_text(prop, "Subdivision Steps", + "Number of times to subdivide newly created strokes, for less jagged strokes"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Curves for pressure */ @@ -2249,7 +2252,7 @@ static void rna_def_gpencil_brush(BlenderRNA *brna) } /* Grease Pencil Drawing Brushes API */ -static void rna_def_gpencil_brushes_api(BlenderRNA *brna, PropertyRNA *cprop) +static void rna_def_gpencil_brushes(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; PropertyRNA *prop; @@ -2279,16 +2282,16 @@ static void rna_def_gpencil_brushes_api(BlenderRNA *brna, PropertyRNA *cprop) prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "GPencilBrush"); - RNA_def_property_pointer_funcs(prop, "rna_GPencil_active_brush_get", "rna_GPencil_active_brush_set", NULL, NULL); + RNA_def_property_pointer_funcs(prop, "rna_GPencilBrushes_active_get", "rna_GPencilBrushes_active_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Brush", "Current active brush"); prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_funcs(prop, - "rna_GPencilBrush_index_get", - "rna_GPencilBrush_index_set", - "rna_GPencilBrush_index_range"); - RNA_def_property_ui_text(prop, "Active brush Index", "Index of active brush"); + "rna_GPencilBrushes_index_get", + "rna_GPencilBrushes_index_set", + "rna_GPencilBrushes_index_range"); + RNA_def_property_ui_text(prop, "Active Brush Index", "Index of active brush"); } static void rna_def_transform_orientation(BlenderRNA *brna) @@ -2611,6 +2614,12 @@ static void rna_def_tool_settings(BlenderRNA *brna) "are included as the basis for the new one"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + prop = RNA_def_property(srna, "use_gpencil_draw_onback", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "gpencil_flags", GP_TOOL_FLAG_PAINT_ONBACK); + RNA_def_property_ui_text(prop, "Draw Strokes on Back", + "When draw new strokes, the new stroke is drawn below of all strokes in the layer"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + prop = RNA_def_property(srna, "grease_pencil_source", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_src"); RNA_def_property_enum_items(prop, gpencil_source_3d_items); @@ -2628,7 +2637,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "gp_brushes", NULL); RNA_def_property_struct_type(prop, "GPencilBrush"); RNA_def_property_ui_text(prop, "Grease Pencil Brushes", "Grease Pencil drawing brushes"); - rna_def_gpencil_brushes_api(brna, prop); + rna_def_gpencil_brushes(brna, prop); /* Grease Pencil - 3D View Stroke Placement */ prop = RNA_def_property(srna, "gpencil_stroke_placement_view3d", PROP_ENUM, PROP_NONE); @@ -6290,6 +6299,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Stamp Output", "Render the stamp info text in the rendered image"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "use_stamp_labels", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "stamp", R_STAMP_HIDE_LABELS); + RNA_def_property_ui_text(prop, "Stamp Labels", "Draw stamp labels (\"Camera\" in front of camera name, etc.)"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "use_stamp_strip_meta", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_STRIPMETA); RNA_def_property_ui_text(prop, "Strip Metadata", "Use metadata from the strips in the sequencer"); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 1d3537dc9a0..519f28bea24 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -37,6 +37,7 @@ #include "BLI_path_util.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "DNA_anim_types.h" #include "DNA_object_types.h" @@ -44,6 +45,18 @@ #include "rna_internal.h" /* own include */ +#ifdef WITH_ALEMBIC +# include "../../alembic/ABC_alembic.h" +#endif + +EnumPropertyItem rna_enum_abc_compression_items[] = { +#ifdef WITH_ALEMBIC + { ABC_ARCHIVE_OGAWA, "OGAWA", 0, "Ogawa", "" }, + { ABC_ARCHIVE_HDF5, "HDF5", 0, "HDF5", "" }, +#endif + { 0, NULL, 0, NULL, NULL } +}; + #ifdef RNA_RUNTIME #include "BKE_animsys.h" @@ -173,6 +186,73 @@ static void rna_Scene_ray_cast( } } +#ifdef WITH_ALEMBIC + +static void rna_Scene_alembic_export( + Scene *scene, + bContext *C, + const char *filepath, + int frame_start, + int frame_end, + int xform_samples, + int geom_samples, + float shutter_open, + float shutter_close, + int selected_only, + int uvs, + int normals, + int vcolors, + int apply_subdiv, + int flatten_hierarchy, + int visible_layers_only, + int renderable_only, + int face_sets, + int use_subdiv_schema, + int compression_type, + int packuv, + float scale) +{ +/* We have to enable allow_threads, because we may change scene frame number + * during export. */ +#ifdef WITH_PYTHON + BPy_BEGIN_ALLOW_THREADS; +#endif + + const struct AlembicExportParams params = { + .frame_start = frame_start, + .frame_end = frame_end, + + .frame_step_xform = 1.0 / (double)xform_samples, + .frame_step_shape = 1.0 / (double)geom_samples, + + .shutter_open = shutter_open, + .shutter_close = shutter_close, + + .selected_only = selected_only, + .uvs = uvs, + .normals = normals, + .vcolors = vcolors, + .apply_subdiv = apply_subdiv, + .flatten_hierarchy = flatten_hierarchy, + .visible_layers_only = visible_layers_only, + .renderable_only = renderable_only, + .face_sets = face_sets, + .use_subdiv_schema = use_subdiv_schema, + .compression_type = compression_type, + .packuv = packuv, + + .global_scale = scale, + }; + + ABC_export(scene, C, filepath, ¶ms); + +#ifdef WITH_PYTHON + BPy_END_ALLOW_THREADS; +#endif +} + +#endif + #ifdef WITH_COLLADA /* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */ #include "../../collada/collada.h" @@ -198,8 +278,8 @@ static void rna_Scene_collada_export( int use_object_instantiation, int use_blender_profile, int sort_by_name, - int export_transformation_type, - int open_sim) + int open_sim, + int export_transformation_type) { collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, include_children, include_armatures, include_shapekeys, deform_bones_only, @@ -296,6 +376,37 @@ void RNA_api_scene(StructRNA *srna) RNA_def_function_ui_description(func, "Export to collada file"); #endif + +#ifdef WITH_ALEMBIC + func = RNA_def_function(srna, "alembic_export", "rna_Scene_alembic_export"); + RNA_def_function_ui_description(func, "Export to Alembic file"); + + parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Alembic file"); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */ + + RNA_def_int(func, "frame_start", 1, INT_MIN, INT_MAX, "Start", "Start Frame", INT_MIN, INT_MAX); + RNA_def_int(func, "frame_end", 1, INT_MIN, INT_MAX, "End", "End Frame", INT_MIN, INT_MAX); + RNA_def_int(func, "xform_samples", 1, 1, 128, "Xform samples", "Transform samples per frame", 1, 128); + RNA_def_int(func, "geom_samples", 1, 1, 128, "Geom samples", "Geometry samples per frame", 1, 128); + RNA_def_float(func, "shutter_open", 0.0f, -1.0f, 1.0f, "Shutter open", "", -1.0f, 1.0f); + RNA_def_float(func, "shutter_close", 1.0f, -1.0f, 1.0f, "Shutter close", "", -1.0f, 1.0f); + RNA_def_boolean(func, "selected_only" , 0, "Selected only", "Export only selected objects"); + RNA_def_boolean(func, "uvs" , 1, "UVs", "Export UVs"); + RNA_def_boolean(func, "normals" , 1, "Normals", "Export cormals"); + RNA_def_boolean(func, "vcolors" , 0, "Vertex colors", "Export vertex colors"); + RNA_def_boolean(func, "apply_subdiv" , 1, "Subsurfs as meshes", "Export subdivision surfaces as meshes"); + RNA_def_boolean(func, "flatten" , 0, "Flatten hierarchy", "Flatten hierarchy"); + RNA_def_boolean(func, "visible_layers_only" , 0, "Visible layers only", "Export only objects in visible layers"); + RNA_def_boolean(func, "renderable_only" , 0, "Renderable objects only", "Export only objects marked renderable in the outliner"); + RNA_def_boolean(func, "face_sets" , 0, "Facesets", "Export face sets"); + RNA_def_boolean(func, "subdiv_schema", 0, "Use Alembic subdivision Schema", "Use Alembic subdivision Schema"); + RNA_def_enum(func, "compression_type", rna_enum_abc_compression_items, 0, "Compression", ""); + RNA_def_boolean(func, "packuv" , 0, "Export with packed UV islands", "Export with packed UV islands"); + RNA_def_float(func, "scale", 1.0f, 0.0001f, 1000.0f, "Scale", "Value by which to enlarge or shrink the objects with respect to the world's origin", 0.0001f, 1000.0f); + + RNA_def_function_flag(func, FUNC_USE_CONTEXT); +#endif } diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index acde2e0957e..a8e80dbc4a3 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -1024,17 +1024,17 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna) prop = RNA_def_property(srna, "affect_position", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_POSITION); - RNA_def_property_ui_text(prop, "Affect position", "The brush affects the position of the point"); + RNA_def_property_ui_text(prop, "Affect Position", "The brush affects the position of the point"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); prop = RNA_def_property(srna, "affect_strength", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_STRENGTH); - RNA_def_property_ui_text(prop, "Affect strength", "The brush affects the color strength of the point"); + RNA_def_property_ui_text(prop, "Affect Strength", "The brush affects the color strength of the point"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); prop = RNA_def_property(srna, "affect_thickness", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_THICKNESS); - RNA_def_property_ui_text(prop, "Affect thickness", "The brush affects the thickness of the point"); + RNA_def_property_ui_text(prop, "Affect Thickness", "The brush affects the thickness of the point"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); prop = RNA_def_property(srna, "selection_alpha", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index d6c650545b2..074fc9f68bd 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3494,6 +3494,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) {SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "Shape Key Editor", "Edit keyframes in active object's Shape Keys action"}, {SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Edit timings for all Grease Pencil sketches in file"}, {SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Edit timings for Mask Editor splines"}, + {SACTCONT_CACHEFILE, "CACHEFILE", ICON_FILE, "Cache File", "Edit timings for Cache File data-blocks"}, {0, NULL, 0, NULL, NULL} }; @@ -3938,6 +3939,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna) {FILTER_ID_AR, "ARMATURE", ICON_ARMATURE_DATA, "Armatures", "Show/hide Armature data-blocks"}, {FILTER_ID_BR, "BRUSH", ICON_BRUSH_DATA, "Brushes", "Show/hide Brushes data-blocks"}, {FILTER_ID_CA, "CAMERA", ICON_CAMERA_DATA, "Cameras", "Show/hide Camera data-blocks"}, + {FILTER_ID_CF, "CACHEFILE", ICON_FILE, "Cache Files", "Show/hide Cache File data-blocks"}, {FILTER_ID_CU, "CURVE", ICON_CURVE_DATA, "Curves", "Show/hide Curve data-blocks"}, {FILTER_ID_GD, "GREASE_PENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Show/hide Grease pencil data-blocks"}, {FILTER_ID_GR, "GROUP", ICON_GROUP, "Groups", "Show/hide Group data-blocks"}, @@ -3983,7 +3985,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna) "IMAGE", ICON_IMAGE_DATA, "Images & Sounds", "Show/hide images, movie clips, sounds and masks"}, {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_SPK | FILTER_ID_WO, "ENVIRONMENT", ICON_WORLD_DATA, "Environment", "Show/hide worlds, lamps, cameras and speakers"}, - {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | FILTER_ID_VF, + {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_CF, "MISC", ICON_GREASEPENCIL, "Miscellaneous", "Show/hide other data types"}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 2564bdb800f..2340345c1c6 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -394,6 +394,16 @@ static int rna_track_2d_stabilization(CollectionPropertyIterator *UNUSED(iter), return 0; } +static int rna_track_2d_stabilization_rotation(CollectionPropertyIterator *UNUSED(iter), void *data) +{ + MovieTrackingTrack *track = (MovieTrackingTrack *)data; + + if ((track->flag & TRACK_USE_2D_STAB_ROT) == 0) + return 1; + + return 0; +} + static void rna_tracking_stabTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { MovieClip *clip = (MovieClip *)ptr->id.data; @@ -421,23 +431,36 @@ static void rna_tracking_stabTracks_active_index_range(PointerRNA *ptr, int *min *max = max_ii(0, clip->tracking.stabilization.tot_track - 1); } -static void rna_tracking_resetIntrinsics(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_tracking_stabRotTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { MovieClip *clip = (MovieClip *)ptr->id.data; - MovieTracking *tracking = &clip->tracking; + rna_iterator_listbase_begin(iter, &clip->tracking.tracks, rna_track_2d_stabilization_rotation); +} - if (tracking->camera.intrinsics) { - BKE_tracking_distortion_free(tracking->camera.intrinsics); - tracking->camera.intrinsics = NULL; - } +static int rna_tracking_stabRotTracks_active_index_get(PointerRNA *ptr) +{ + MovieClip *clip = (MovieClip *)ptr->id.data; + return clip->tracking.stabilization.act_rot_track; } -static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +static void rna_tracking_stabRotTracks_active_index_set(PointerRNA *ptr, int value) +{ + MovieClip *clip = (MovieClip *)ptr->id.data; + clip->tracking.stabilization.act_rot_track = value; +} + +static void rna_tracking_stabRotTracks_active_index_range(PointerRNA *ptr, int *min, int *max, + int *UNUSED(softmin), int *UNUSED(softmax)) { MovieClip *clip = (MovieClip *)ptr->id.data; - MovieTrackingStabilization *stab = &clip->tracking.stabilization; - stab->ok = 0; + *min = 0; + *max = max_ii(0, clip->tracking.stabilization.tot_rot_track - 1); +} + +static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +{ + MovieClip *clip = (MovieClip *)ptr->id.data; nodeUpdateID(scene->nodetree, &clip->id); @@ -446,6 +469,17 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR DAG_id_tag_update(&clip->id, 0); } +static void rna_tracking_resetIntrinsics(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + MovieClip *clip = (MovieClip *)ptr->id.data; + MovieTracking *tracking = &clip->tracking; + + if (tracking->camera.intrinsics) { + BKE_tracking_distortion_free(tracking->camera.intrinsics); + tracking->camera.intrinsics = NULL; + } +} + static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { MovieTrackingObject *object = (MovieTrackingObject *)ptr->data; @@ -1495,6 +1529,12 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Weight", "Influence of this track on a final solution"); + /* weight_stab */ + prop = RNA_def_property(srna, "weight_stab", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "weight_stab"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Stab Weight", "Influence of this track on 2D stabilization"); + /* offset */ prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_array(prop, 2); @@ -1634,15 +1674,15 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem filter_items[] = { - {TRACKING_FILTER_NEAREST, "NEAREST", 0, "Nearest", ""}, - {TRACKING_FILTER_BILINEAR, "BILINEAR", 0, "Bilinear", ""}, - {TRACKING_FILTER_BICUBIC, "BICUBIC", 0, "Bicubic", ""}, + {TRACKING_FILTER_NEAREST, "NEAREST", 0, "Nearest", "No interpolation, use nearest neighbor pixel"}, + {TRACKING_FILTER_BILINEAR, "BILINEAR", 0, "Bilinear", "Simple interpolation between adjacent pixels"}, + {TRACKING_FILTER_BICUBIC, "BICUBIC", 0, "Bicubic", "High quality pixel interpolation"}, {0, NULL, 0, NULL, NULL} }; srna = RNA_def_struct(brna, "MovieTrackingStabilization", NULL); RNA_def_struct_path_func(srna, "rna_trackingStabilization_path"); - RNA_def_struct_ui_text(srna, "Movie tracking stabilization data", "Match-moving stabilization data for tracking"); + RNA_def_struct_ui_text(srna, "Movie tracking stabilization data", "2D stabilization based on tracking markers"); /* 2d stabilization */ prop = RNA_def_property(srna, "use_2d_stabilization", PROP_BOOLEAN, PROP_NONE); @@ -1651,22 +1691,30 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use 2D stabilization", "Use 2D stabilization for footage"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + /* use_stabilize_rotation */ + prop = RNA_def_property(srna, "use_stabilize_rotation", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_STABILIZE_ROTATION); + RNA_def_property_ui_text(prop, "Stabilize Rotation", "Stabilize detected rotation around center of frame"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + + /* use_stabilize_scale */ + prop = RNA_def_property(srna, "use_stabilize_scale", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_STABILIZE_SCALE); + RNA_def_property_ui_text(prop, "Stabilize Scale", "Compensate any scale changes relative to center of rotation"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + /* tracks */ prop = RNA_def_property(srna, "tracks", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_tracking_stabTracks_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL); RNA_def_property_struct_type(prop, "MovieTrackingTrack"); - RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks used for stabilization"); + RNA_def_property_ui_text(prop, "Translation Tracks", + "Collection of tracks used for 2D stabilization (translation)"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); - /* rotation track */ - prop = RNA_def_property(srna, "rotation_track", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "rot_track"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Rotation Track", "Track used to compensate rotation"); - RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_tracking_flushUpdate"); - /* active track index */ prop = RNA_def_property(srna, "active_track_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "act_track"); @@ -1674,7 +1722,65 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_tracking_stabTracks_active_index_get", "rna_tracking_stabTracks_active_index_set", "rna_tracking_stabTracks_active_index_range"); - RNA_def_property_ui_text(prop, "Active Track Index", "Index of active track in stabilization tracks list"); + RNA_def_property_ui_text(prop, "Active Track Index", + "Index of active track in translation stabilization tracks list"); + + /* tracks used for rotation stabilization */ + prop = RNA_def_property(srna, "rotation_tracks", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_tracking_stabRotTracks_begin", "rna_iterator_listbase_next", + "rna_iterator_listbase_end", "rna_iterator_listbase_get", + NULL, NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "MovieTrackingTrack"); + RNA_def_property_ui_text(prop, "Rotation Tracks", "Collection of tracks used for 2D stabilization (translation)"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + + /* active rotation track index */ + prop = RNA_def_property(srna, "active_rotation_track_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "act_rot_track"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_int_funcs(prop, "rna_tracking_stabRotTracks_active_index_get", + "rna_tracking_stabRotTracks_active_index_set", + "rna_tracking_stabRotTracks_active_index_range"); + RNA_def_property_ui_text(prop, "Active Rotation Track Index", + "Index of active track in rotation stabilization tracks list"); + + /* anchor frame */ + prop = RNA_def_property(srna, "anchor_frame", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "anchor_frame"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_range(prop, MINFRAME, MAXFRAME); + RNA_def_property_ui_text(prop, "Anchor Frame", + "Reference point to anchor stabilization " + "(other frames will be adjusted relative to this frame's position)"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + + /* target position */ + prop = RNA_def_property(srna, "target_position", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 2); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3); /* increment in steps of 0.01 and show 3 digit after point */ + RNA_def_property_float_sdna(prop, NULL, "target_pos"); + RNA_def_property_ui_text(prop, "Expected Position", + "Known relative offset of original shot, will be subtracted " + "(e.g. for panning shot, can be animated)"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + + /* target rotation */ + prop = RNA_def_property(srna, "target_rotation", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "target_rot"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 10.0f, 3); + RNA_def_property_ui_text(prop, "Expected Rotation", + "Rotation present on original shot, will be compensated (e.g. for deliberate tilting)"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + + /* target scale */ + prop = RNA_def_property(srna, "target_scale", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_range(prop, FLT_EPSILON, FLT_MAX); + RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.001f, 3); /* increment in steps of 0.001. Show 3 digit after point */ + RNA_def_property_ui_text(prop, "Expected Scale", + "Explicitly scale resulting frame to compensate zoom of original shot"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); /* autoscale */ prop = RNA_def_property(srna, "use_autoscale", PROP_BOOLEAN, PROP_NONE); @@ -1705,13 +1811,6 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Scale Influence", "Influence of stabilization algorithm on footage scale"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); - /* use_stabilize_rotation */ - prop = RNA_def_property(srna, "use_stabilize_rotation", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_STABILIZE_ROTATION); - RNA_def_property_ui_text(prop, "Stabilize Rotation", "Stabilize horizon line on the shot"); - RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); - /* influence_rotation */ prop = RNA_def_property(srna, "influence_rotation", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "rotinf"); @@ -1723,8 +1822,16 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "filter"); RNA_def_property_enum_items(prop, filter_items); - RNA_def_property_ui_text(prop, "Filter", "Method to use to filter stabilization"); + RNA_def_property_ui_text(prop, "Interpolate", + "Interpolation to use for sub-pixel shifts and rotations due to stabilization"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + + /* UI display : show participating tracks */ + prop = RNA_def_property(srna, "show_tracks_expanded", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_SHOW_STAB_TRACKS); + RNA_def_property_ui_text(prop, "Show Tracks", "Show UI list of tracks participating in stabilization"); + RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); } static void rna_def_reconstructedCamera(BlenderRNA *brna) @@ -1987,7 +2094,7 @@ static void rna_def_trackingObjects(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_srna(cprop, "MovieTrackingObjects"); srna = RNA_def_struct(brna, "MovieTrackingObjects", NULL); RNA_def_struct_sdna(srna, "MovieTracking"); - RNA_def_struct_ui_text(srna, "Movie Objects", "Collection of movie trackingobjects"); + RNA_def_struct_ui_text(srna, "Movie Objects", "Collection of movie tracking objects"); func = RNA_def_function(srna, "new", "rna_trackingObject_new"); RNA_def_function_ui_description(func, "Add tracking object to this movie clip"); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 80777f57811..a751c414d83 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -912,6 +912,11 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "Node Socket Icon"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); RNA_def_float_array(func, "color", 4, node_socket_color_default, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f); + + func = RNA_def_function(srna, "template_cache_file", "uiTemplateCacheFile"); + RNA_def_function_ui_description(func, "Item(s). User interface for selecting cache files and their source paths"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + api_ui_item_rna_common(func); } #endif diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index cbf7bb4d5e0..29c0e948a4c 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -292,11 +292,13 @@ static void rna_userdef_autokeymode_set(PointerRNA *ptr, int value) } } +#ifdef WITH_INPUT_NDOF static void rna_userdef_ndof_deadzone_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { UserDef *userdef = ptr->data; WM_ndof_deadzone_set(userdef->ndof_deadzone); } +#endif static void rna_userdef_timecode_style_set(PointerRNA *ptr, int value) { @@ -4333,6 +4335,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; +#ifdef WITH_INPUT_NDOF static EnumPropertyItem ndof_view_navigation_items[] = { {0, "FREE", 0, "Free", "Use full 6 degrees of freedom by default"}, {NDOF_MODE_ORBIT, "ORBIT", 0, "Orbit", "Orbit about the view center by default"}, @@ -4344,6 +4347,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) {0, "TRACKBALL", 0, "Trackball", "Use trackball style rotation in the viewport"}, {0, NULL, 0, NULL, NULL} }; +#endif /* WITH_INPUT_NDOF */ static EnumPropertyItem view_zoom_styles[] = { {USER_ZOOM_CONT, "CONTINUE", 0, "Continue", "Old style zoom, continues while moving mouse up or down"}, @@ -4421,6 +4425,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Tweak Threshold", "Number of pixels you have to drag before tweak event is triggered"); +#ifdef WITH_INPUT_NDOF /* 3D mouse settings */ /* global options */ prop = RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE); @@ -4501,6 +4506,13 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER); RNA_def_property_ui_text(prop, "Helicopter Mode", "Device up/down directly controls your Z position"); + /* let Python know whether NDOF is enabled */ + prop = RNA_def_boolean(srna, "use_ndof", true, "", ""); +#else + prop = RNA_def_boolean(srna, "use_ndof", false, "", ""); +#endif /* WITH_INPUT_NDOF */ + RNA_def_property_flag(prop, PROP_IDPROPERTY); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop = RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dbl_click_time"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 026d2e209a3..90081a93188 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -167,7 +167,7 @@ static EnumPropertyItem event_ndof_type_items[] = { {NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "Button C", ""}, {0, NULL, 0, NULL, NULL} }; -#endif +#endif /* RNA_RUNTIME */ /* not returned: CAPSLOCKKEY, UNKNOWNKEY */ EnumPropertyItem rna_enum_event_type_items[] = { @@ -1935,15 +1935,15 @@ static void rna_def_wm_keyconfigs(BlenderRNA *brna, PropertyRNA *cprop) prop = RNA_def_property(srna, "addon", PROP_POINTER, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "addonconf"); RNA_def_property_struct_type(prop, "KeyConfig"); - RNA_def_property_ui_text(prop, "Addon Key Configuration", - "Key configuration that can be extended by addons, and is added to the active " + RNA_def_property_ui_text(prop, "Add-on Key Configuration", + "Key configuration that can be extended by add-ons, and is added to the active " "configuration when handling events"); prop = RNA_def_property(srna, "user", PROP_POINTER, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "userconf"); RNA_def_property_struct_type(prop, "KeyConfig"); RNA_def_property_ui_text(prop, "User Key Configuration", - "Final key configuration that combines keymaps from the active and addon configurations, " + "Final key configuration that combines keymaps from the active and add-on configurations, " "and can be edited by the user"); RNA_api_keyconfigs(srna); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 0de7676e8f8..b8ebb375a48 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -73,6 +73,7 @@ set(SRC intern/MOD_meshcache_pc2.c intern/MOD_meshcache_util.c intern/MOD_meshdeform.c + intern/MOD_meshsequencecache.c intern/MOD_mirror.c intern/MOD_multires.c intern/MOD_none.c @@ -112,6 +113,13 @@ set(SRC intern/MOD_weightvg_util.h ) +if(WITH_ALEMBIC) + add_definitions(-DWITH_ALEMBIC) + list(APPEND INC + ../alembic + ) +endif() + if(WITH_MOD_BOOLEAN) add_definitions(-DWITH_MOD_BOOLEAN) list(APPEND SRC diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index a5d96759952..4c881445893 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -84,6 +84,7 @@ extern ModifierTypeInfo modifierType_Wireframe; extern ModifierTypeInfo modifierType_DataTransfer; extern ModifierTypeInfo modifierType_NormalEdit; extern ModifierTypeInfo modifierType_CorrectiveSmooth; +extern ModifierTypeInfo modifierType_MeshSequenceCache; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 6cc2f097be8..d15a6fcb1c8 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -123,19 +123,11 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, { ClothModifierData *clmd = (ClothModifierData *) md; - Base *base; - if (clmd) { - for (base = scene->base.first; base; base = base->next) { - Object *ob1 = base->object; - if (ob1 != ob) { - CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); - if (coll_clmd) { - DagNode *curNode = dag_get_node(forest, ob1); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Cloth Collision"); - } - } - } + /* Actual code uses get_collisionobjects */ + dag_add_collision_relations(forest, scene, ob, obNode, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision"); + + dag_add_forcefield_relations(forest, scene, ob, obNode, clmd->sim_parms->effector_weights, true, 0, "Cloth Field"); } } @@ -147,16 +139,10 @@ static void updateDepsgraph(ModifierData *md, { ClothModifierData *clmd = (ClothModifierData *)md; if (clmd != NULL) { - Base *base; - for (base = scene->base.first; base; base = base->next) { - Object *ob1 = base->object; - if (ob1 != ob) { - CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); - if (coll_clmd) { - DEG_add_object_relation(node, ob1, DEG_OB_COMP_TRANSFORM, "Cloth Modifier"); - } - } - } + /* Actual code uses get_collisionobjects */ + DEG_add_collision_relations(node, scene, ob, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision"); + + DEG_add_forcefield_relations(node, scene, ob, clmd->sim_parms->effector_weights, true, 0, "Cloth Field"); } } diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index edf959f42c6..bde20e56748 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -114,6 +114,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, return dm; } +static bool is_brush_cb(Object *UNUSED(ob), ModifierData *pmd) +{ + return ((DynamicPaintModifierData*)pmd)->brush != NULL; +} + static void updateDepgraph(ModifierData *md, DagForest *forest, struct Main *UNUSED(bmain), struct Scene *scene, @@ -124,16 +129,13 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, /* add relation from canvases to all brush objects */ if (pmd && pmd->canvas) { - Base *base = scene->base.first; - - for (; base; base = base->next) { - DynamicPaintModifierData *pmd2 = - (DynamicPaintModifierData *)modifiers_findByType(base->object, eModifierType_DynamicPaint); - - if (pmd2 && pmd2->brush && ob != base->object) { - DagNode *brushNode = dag_get_node(forest, base->object); - dag_add_relation(forest, brushNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Dynamic Paint Brush"); + for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) { + if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) { + dag_add_forcefield_relations(forest, scene, ob, obNode, surface->effector_weights, true, 0, "Dynamic Paint Field"); } + + /* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */ + dag_add_collision_relations(forest, scene, ob, obNode, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush"); } } } @@ -147,13 +149,13 @@ static void updateDepsgraph(ModifierData *md, DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; /* Add relation from canvases to all brush objects. */ if (pmd->canvas != NULL) { - Base *base = scene->base.first; - for (; base; base = base->next) { - DynamicPaintModifierData *pmd2 = - (DynamicPaintModifierData *)modifiers_findByType(base->object, eModifierType_DynamicPaint); - if (pmd2 && pmd2->brush && ob != base->object) { - DEG_add_object_relation(node, base->object, DEG_OB_COMP_TRANSFORM, "Dynamic Paint Brush"); + for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) { + if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) { + DEG_add_forcefield_relations(node, scene, ob, surface->effector_weights, true, 0, "Dynamic Paint Field"); } + + /* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */ + DEG_add_collision_relations(node, scene, ob, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush"); } } } diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c new file mode 100644 index 00000000000..355ac9563dd --- /dev/null +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -0,0 +1,197 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/modifiers/intern/MOD_meshsequencecache.c + * \ingroup modifiers + */ + +#include "DNA_cachefile_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_cachefile.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_library_query.h" +#include "BKE_scene.h" + +#include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" + +#include "MOD_modifiertypes.h" + +#ifdef WITH_ALEMBIC +# include "ABC_alembic.h" +#endif + +static void initData(ModifierData *md) +{ + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; + + mcmd->cache_file = NULL; + mcmd->object_path[0] = '\0'; + mcmd->read_flag = MOD_MESHSEQ_READ_ALL; +} + +static void copyData(ModifierData *md, ModifierData *target) +{ +#if 0 + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; +#endif + MeshSeqCacheModifierData *tmcmd = (MeshSeqCacheModifierData *)target; + + modifier_copyData_generic(md, target); + + if (tmcmd->cache_file) { + id_us_plus(&tmcmd->cache_file->id); + } +} + +static void freeData(ModifierData *md) +{ + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; + + if (mcmd->cache_file) { + id_us_min(&mcmd->cache_file->id); + } +} + +static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) +{ + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; + + /* leave it up to the modifier to check the file is valid on calculation */ + return (mcmd->cache_file == NULL) || (mcmd->object_path[0] == '\0'); +} + +static DerivedMesh *applyModifier(ModifierData *md, Object *ob, + DerivedMesh *dm, + ModifierApplyFlag flag) +{ +#ifdef WITH_ALEMBIC + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; + + Scene *scene = md->scene; + const float frame = BKE_scene_frame_get(scene); + const float time = BKE_cachefile_time_offset(mcmd->cache_file, frame, FPS); + + const char *err_str = NULL; + + CacheFile *cache_file = mcmd->cache_file; + + BKE_cachefile_ensure_handle(G.main, cache_file); + + DerivedMesh *result = ABC_read_mesh(cache_file->handle, + ob, + dm, + mcmd->object_path, + time, + &err_str, + mcmd->read_flag); + + if (err_str) { + modifier_setError(md, "%s", err_str); + } + + return result ? result : dm; + UNUSED_VARS(flag); +#else + return dm; + UNUSED_VARS(md, ob, flag); +#endif +} + +static bool dependsOnTime(ModifierData *md) +{ + UNUSED_VARS(md); + return true; +} + +static void foreachIDLink(ModifierData *md, Object *ob, + IDWalkFunc walk, void *userData) +{ + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; + + walk(userData, ob, (ID **)&mcmd->cache_file, IDWALK_USER); +} + + +static void updateDepgraph(ModifierData *md, DagForest *forest, + struct Main *bmain, + struct Scene *scene, + Object *ob, DagNode *obNode) +{ + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; + + if (mcmd->cache_file != NULL) { + DagNode *curNode = dag_get_node(forest, mcmd->cache_file); + + dag_add_relation(forest, curNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Cache File Modifier"); + } + + UNUSED_VARS(bmain, scene, ob); +} + +static void updateDepsgraph(ModifierData *md, + struct Main *bmain, + struct Scene *scene, + Object *ob, + struct DepsNodeHandle *node) +{ + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; + + if (mcmd->cache_file != NULL) { + DEG_add_object_cache_relation(node, mcmd->cache_file, DEG_OB_COMP_CACHE, "Mesh Cache File"); + } + + UNUSED_VARS(bmain, scene, ob); +} + +ModifierTypeInfo modifierType_MeshSequenceCache = { + /* name */ "Mesh Sequence Cache", + /* structName */ "MeshSeqCacheModifierData", + /* structSize */ sizeof(MeshSeqCacheModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_AcceptsCVs, + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ NULL, + /* freeData */ freeData, + /* isDisabled */ isDisabled, + /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index 237d4cc6718..f04d7432a8f 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -117,219 +117,48 @@ static bool dependsOnTime(ModifierData *UNUSED(md)) return true; } -static void update_depsgraph_flow_coll_object(DagForest *forest, - DagNode *obNode, - Object *object2) +static bool is_flow_cb(Object *UNUSED(ob), ModifierData *md) { - SmokeModifierData *smd; - if ((object2->id.tag & LIB_TAG_DOIT) == 0) { - return; - } - object2->id.tag &= ~LIB_TAG_DOIT; - smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke); - if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) || - ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll))) - { - DagNode *curNode = dag_get_node(forest, object2); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Flow/Coll"); - } - if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { - GroupObject *go; - for (go = object2->dup_group->gobject.first; - go != NULL; - go = go->next) - { - if (go->ob == NULL) { - continue; - } - update_depsgraph_flow_coll_object(forest, obNode, go->ob); - } - } + SmokeModifierData *smd = (SmokeModifierData *) md; + return (smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow; } -static void update_depsgraph_field_source_object(DagForest *forest, - DagNode *obNode, - Object *object, - Object *object2) +static bool is_coll_cb(Object *UNUSED(ob), ModifierData *md) { - if ((object2->id.tag & LIB_TAG_DOIT) == 0) { - return; - } - object2->id.tag &= ~LIB_TAG_DOIT; - if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) { - DagNode *node2 = dag_get_node(forest, object2); - dag_add_relation(forest, obNode, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Source Object"); - } - if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { - GroupObject *go; - for (go = object2->dup_group->gobject.first; - go != NULL; - go = go->next) - { - if (go->ob == NULL) { - continue; - } - update_depsgraph_field_source_object(forest, obNode, object, go->ob); - } - } + SmokeModifierData *smd = (SmokeModifierData *) md; + return (smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll; } static void updateDepgraph(ModifierData *md, DagForest *forest, - struct Main *bmain, + struct Main *UNUSED(bmain), struct Scene *scene, struct Object *ob, DagNode *obNode) { SmokeModifierData *smd = (SmokeModifierData *) md; - Base *base; if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { - if (smd->domain->fluid_group || smd->domain->coll_group) { - GroupObject *go = NULL; - - if (smd->domain->fluid_group) - for (go = smd->domain->fluid_group->gobject.first; go; go = go->next) { - if (go->ob) { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); - - /* check for initialized smoke object */ - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) { - DagNode *curNode = dag_get_node(forest, go->ob); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Flow"); - } - } - } - - if (smd->domain->coll_group) - for (go = smd->domain->coll_group->gobject.first; go; go = go->next) { - if (go->ob) { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); - - /* check for initialized smoke object */ - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) { - DagNode *curNode = dag_get_node(forest, go->ob); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Coll"); - } - } - } - } - else { - BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - base = scene->base.first; - for (; base; base = base->next) { - update_depsgraph_flow_coll_object(forest, obNode, base->object); - } - } - /* add relation to all "smoke flow" force fields */ - base = scene->base.first; - BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - for (; base; base = base->next) { - update_depsgraph_field_source_object(forest, obNode, ob, base->object); - } - } -} + /* Actual code uses get_collisionobjects */ + dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow"); + dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll"); -static void update_depsgraph_flow_coll_object_new(struct DepsNodeHandle *node, - Object *object2) -{ - SmokeModifierData *smd; - if ((object2->id.tag & LIB_TAG_DOIT) == 0) { - return; - } - object2->id.tag &= ~LIB_TAG_DOIT; - smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke); - if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) || - ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll))) - { - DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Smoke Flow/Coll"); - DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Smoke Flow/Coll"); - } - if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { - GroupObject *go; - for (go = object2->dup_group->gobject.first; - go != NULL; - go = go->next) - { - if (go->ob == NULL) { - continue; - } - update_depsgraph_flow_coll_object_new(node, go->ob); - } - } -} - -static void update_depsgraph_field_source_object_new(struct DepsNodeHandle *node, - Object *object, - Object *object2) -{ - if ((object2->id.tag & LIB_TAG_DOIT) == 0) { - return; - } - object2->id.tag &= ~LIB_TAG_DOIT; - if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) { - DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Field Source Object"); - DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Field Source Object"); - } - if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { - GroupObject *go; - for (go = object2->dup_group->gobject.first; - go != NULL; - go = go->next) - { - if (go->ob == NULL) { - continue; - } - update_depsgraph_field_source_object_new(node, object, go->ob); - } + dag_add_forcefield_relations(forest, scene, ob, obNode, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field"); } } static void updateDepsgraph(ModifierData *md, - struct Main *bmain, + struct Main *UNUSED(bmain), struct Scene *scene, Object *ob, struct DepsNodeHandle *node) { SmokeModifierData *smd = (SmokeModifierData *)md; - Base *base; + if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { - if (smd->domain->fluid_group || smd->domain->coll_group) { - GroupObject *go = NULL; - if (smd->domain->fluid_group != NULL) { - for (go = smd->domain->fluid_group->gobject.first; go; go = go->next) { - if (go->ob != NULL) { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); - /* Check for initialized smoke object. */ - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) { - DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Flow"); - } - } - } - } - if (smd->domain->coll_group != NULL) { - for (go = smd->domain->coll_group->gobject.first; go; go = go->next) { - if (go->ob != NULL) { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); - /* Check for initialized smoke object. */ - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) { - DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Coll"); - } - } - } - } - } - else { - BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - base = scene->base.first; - for (; base; base = base->next) { - update_depsgraph_flow_coll_object_new(node, base->object); - } - } - /* add relation to all "smoke flow" force fields */ - base = scene->base.first; - BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - for (; base; base = base->next) { - update_depsgraph_field_source_object_new(node, ob, base->object); - } + /* Actual code uses get_collisionobjects */ + DEG_add_collision_relations(node, scene, ob, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow"); + DEG_add_collision_relations(node, scene, ob, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll"); + + DEG_add_forcefield_relations(node, scene, ob, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field"); } } diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index 98a1412d0c6..17adc7f1520 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -35,6 +35,7 @@ #include <stdio.h> #include "DNA_scene_types.h" +#include "DNA_object_force.h" #include "BLI_utildefines.h" @@ -42,6 +43,9 @@ #include "BKE_particle.h" #include "BKE_softbody.h" +#include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" + #include "MOD_modifiertypes.h" static void deformVerts(ModifierData *md, Object *ob, @@ -58,6 +62,31 @@ static bool dependsOnTime(ModifierData *UNUSED(md)) return true; } +static void updateDepgraph(ModifierData *UNUSED(md), DagForest *forest, + struct Main *UNUSED(bmain), + Scene *scene, Object *ob, DagNode *obNode) +{ + if (ob->soft) { + /* Actual code uses ccd_build_deflector_hash */ + dag_add_collision_relations(forest, scene, ob, obNode, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision"); + + dag_add_forcefield_relations(forest, scene, ob, obNode, ob->soft->effector_weights, true, 0, "Softbody Field"); + } +} + +static void updateDepsgraph(ModifierData *UNUSED(md), + struct Main *UNUSED(bmain), + struct Scene *scene, + Object *ob, + struct DepsNodeHandle *node) +{ + if (ob->soft) { + /* Actual code uses ccd_build_deflector_hash */ + DEG_add_collision_relations(node, scene, ob, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision"); + + DEG_add_forcefield_relations(node, scene, ob, ob->soft->effector_weights, true, 0, "Softbody Field"); + } +} ModifierTypeInfo modifierType_Softbody = { /* name */ "Softbody", @@ -80,8 +109,8 @@ ModifierTypeInfo modifierType_Softbody = { /* requiredDataMask */ NULL, /* freeData */ NULL, /* isDisabled */ NULL, - /* updateDepgraph */ NULL, - /* updateDepsgraph */ NULL, + /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index f9291fb077f..93414562ccf 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -286,5 +286,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(DataTransfer); INIT_TYPE(NormalEdit); INIT_TYPE(CorrectiveSmooth); + INIT_TYPE(MeshSequenceCache); #undef INIT_TYPE } diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c index 8b21b1ff33b..6850cdbf6ea 100644 --- a/source/blender/nodes/shader/nodes/node_shader_material.c +++ b/source/blender/nodes/shader/nodes/node_shader_material.c @@ -223,12 +223,27 @@ static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode *node) /* XXX this is also done as a local static function in gpu_codegen.c, * but we need this to hack around the crappy material node. */ -static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) +static GPUNodeLink *gpu_get_input_link(GPUMaterial *mat, GPUNodeStack *in) { - if (in->link) + if (in->link) { return in->link; - else - return GPU_uniform(in->vec); + } + else { + GPUNodeLink *result = NULL; + + /* note GPU_uniform() is only intended to be used as a parameter to + * GPU_link(), returning it directly results in leaks or double frees */ + if (in->type == GPU_FLOAT) + GPU_link(mat, "set_value", GPU_uniform(in->vec), &result); + else if (in->type == GPU_VEC3) + GPU_link(mat, "set_rgb", GPU_uniform(in->vec), &result); + else if (in->type == GPU_VEC4) + GPU_link(mat, "set_rgba", GPU_uniform(in->vec), &result); + else + BLI_assert(0); + + return result; + } } static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) @@ -251,18 +266,18 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNU /* write values */ if (hasinput[MAT_IN_COLOR]) - shi.rgb = gpu_get_input_link(&in[MAT_IN_COLOR]); + shi.rgb = gpu_get_input_link(mat, &in[MAT_IN_COLOR]); if (hasinput[MAT_IN_SPEC]) - shi.specrgb = gpu_get_input_link(&in[MAT_IN_SPEC]); + shi.specrgb = gpu_get_input_link(mat, &in[MAT_IN_SPEC]); if (hasinput[MAT_IN_REFL]) - shi.refl = gpu_get_input_link(&in[MAT_IN_REFL]); + shi.refl = gpu_get_input_link(mat, &in[MAT_IN_REFL]); /* retrieve normal */ if (hasinput[MAT_IN_NORMAL]) { GPUNodeLink *tmp; - shi.vn = gpu_get_input_link(&in[MAT_IN_NORMAL]); + shi.vn = gpu_get_input_link(mat, &in[MAT_IN_NORMAL]); if (GPU_material_use_world_space_shading(mat)) { GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); GPU_link(mat, "direction_transform_m4v3", shi.vn, GPU_builtin(GPU_VIEW_MATRIX), &shi.vn); @@ -276,15 +291,15 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNU if (node->type == SH_NODE_MATERIAL_EXT) { if (hasinput[MAT_IN_MIR]) - shi.mir = gpu_get_input_link(&in[MAT_IN_MIR]); + shi.mir = gpu_get_input_link(mat, &in[MAT_IN_MIR]); if (hasinput[MAT_IN_AMB]) - shi.amb = gpu_get_input_link(&in[MAT_IN_AMB]); + shi.amb = gpu_get_input_link(mat, &in[MAT_IN_AMB]); if (hasinput[MAT_IN_EMIT]) - shi.emit = gpu_get_input_link(&in[MAT_IN_EMIT]); + shi.emit = gpu_get_input_link(mat, &in[MAT_IN_EMIT]); if (hasinput[MAT_IN_SPECTRA]) - shi.spectra = gpu_get_input_link(&in[MAT_IN_SPECTRA]); + shi.spectra = gpu_get_input_link(mat, &in[MAT_IN_SPECTRA]); if (hasinput[MAT_IN_ALPHA]) - shi.alpha = gpu_get_input_link(&in[MAT_IN_ALPHA]); + shi.alpha = gpu_get_input_link(mat, &in[MAT_IN_ALPHA]); } GPU_shaderesult_set(&shi, &shr); /* clears shr */ diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 2715d2c5992..038c1e7eb10 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -49,6 +49,7 @@ set(SRC gpu_offscreen.c bpy.c bpy_app.c + bpy_app_alembic.c bpy_app_build_options.c bpy_app_ffmpeg.c bpy_app_handlers.c @@ -82,6 +83,7 @@ set(SRC gpu.h bpy.h bpy_app.h + bpy_app_alembic.h bpy_app_build_options.h bpy_app_ffmpeg.h bpy_app_handlers.h @@ -264,6 +266,10 @@ if(WITH_OPENCOLLADA) add_definitions(-DWITH_COLLADA) endif() +if(WITH_ALEMBIC) + add_definitions(-DWITH_ALEMBIC) +endif() + if(WITH_OPENCOLORIO) add_definitions(-DWITH_OCIO) endif() @@ -275,6 +281,13 @@ if(WITH_OPENVDB) ) endif() +if(WITH_ALEMBIC) + add_definitions(-DWITH_ALEMBIC) + list(APPEND INC + ../../alembic + ) +endif() + if(WITH_OPENIMAGEIO) add_definitions(-DWITH_OPENIMAGEIO) list(APPEND INC diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 727d980b182..78cb537cccd 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -33,6 +33,7 @@ #include "bpy_app.h" +#include "bpy_app_alembic.h" #include "bpy_app_ffmpeg.h" #include "bpy_app_ocio.h" #include "bpy_app_oiio.h" @@ -104,6 +105,7 @@ static PyStructSequence_Field app_info_fields[] = { {(char *)"build_system", (char *)"Build system used"}, /* submodules */ + {(char *)"alembic", (char *)"Alembic library information backend"}, {(char *)"ffmpeg", (char *)"FFmpeg library information backend"}, {(char *)"ocio", (char *)"OpenColorIO library information backend"}, {(char *)"oiio", (char *)"OpenImageIO library information backend"}, @@ -182,6 +184,7 @@ static PyObject *make_app_info(void) SetBytesItem("Unknown"); #endif + SetObjItem(BPY_app_alembic_struct()); SetObjItem(BPY_app_ffmpeg_struct()); SetObjItem(BPY_app_ocio_struct()); SetObjItem(BPY_app_oiio_struct()); diff --git a/source/blender/python/intern/bpy_app_alembic.c b/source/blender/python/intern/bpy_app_alembic.c new file mode 100644 index 00000000000..90e6a02b418 --- /dev/null +++ b/source/blender/python/intern/bpy_app_alembic.c @@ -0,0 +1,113 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_alembic.c + * \ingroup pythonintern + */ + +#include <Python.h> +#include "BLI_utildefines.h" + +#include "bpy_app_alembic.h" + +#ifdef WITH_ALEMBIC +# include "ABC_alembic.h" +#endif + +static PyTypeObject BlenderAppABCType; + +static PyStructSequence_Field app_alembic_info_fields[] = { + {(char *)"supported", (char *)"Boolean, True when Blender is built with Alembic support"}, + {(char *)"version", (char *)"The Alembic version as a tuple of 3 numbers"}, + {(char *)"version_string", (char *)"The Alembic version formatted as a string"}, + {NULL} +}; + +static PyStructSequence_Desc app_alembic_info_desc = { + (char *)"bpy.app.alembic", /* name */ + (char *)"This module contains information about Alembic blender is linked against", /* doc */ + app_alembic_info_fields, /* fields */ + ARRAY_SIZE(app_alembic_info_fields) - 1 +}; + +static PyObject *make_alembic_info(void) +{ + PyObject *alembic_info = PyStructSequence_New(&BlenderAppABCType); + + if (alembic_info == NULL) { + return NULL; + } + + int pos = 0; + +#ifndef WITH_ALEMBIC +# define SetStrItem(str) \ + PyStructSequence_SET_ITEM(alembic_info, pos++, PyUnicode_FromString(str)) +#endif + +#define SetObjItem(obj) \ + PyStructSequence_SET_ITEM(alembic_info, pos++, obj) + +#ifdef WITH_ALEMBIC + const int curversion = ABC_get_version(); + const int major = curversion / 10000; + const int minor = (curversion / 100) - (major * 100); + const int patch = curversion - ((curversion / 100 ) * 100); + + SetObjItem(PyBool_FromLong(1)); + SetObjItem(Py_BuildValue("(iii)", major, minor, patch)); + SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", major, minor, patch)); +#else + SetObjItem(PyBool_FromLong(0)); + SetObjItem(Py_BuildValue("(iii)", 0, 0, 0)); + SetStrItem("Unknown"); +#endif + + if (PyErr_Occurred()) { + Py_CLEAR(alembic_info); + return NULL; + } + +#undef SetStrItem +#undef SetObjItem + + return alembic_info; +} + +PyObject *BPY_app_alembic_struct(void) +{ + PyStructSequence_InitType(&BlenderAppABCType, &app_alembic_info_desc); + + PyObject *ret = make_alembic_info(); + + /* prevent user from creating new instances */ + BlenderAppABCType.tp_init = NULL; + BlenderAppABCType.tp_new = NULL; + BlenderAppABCType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + + return ret; +} diff --git a/source/blender/python/intern/bpy_app_alembic.h b/source/blender/python/intern/bpy_app_alembic.h new file mode 100644 index 00000000000..8cc647a77df --- /dev/null +++ b/source/blender/python/intern/bpy_app_alembic.h @@ -0,0 +1,38 @@ +/* + * ***** 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) 2016 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Kevin Dietrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_alembic.h + * \ingroup pythonintern + */ + +#ifndef __BPY_APP_ALEMBIC_H__ +#define __BPY_APP_ALEMBIC_H__ + +PyObject *BPY_app_alembic_struct(void); + +#endif /* __BPY_APP_ALEMBIC_H__ */ + diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c index 4c186aab100..a6b98567a9a 100644 --- a/source/blender/python/intern/bpy_app_build_options.c +++ b/source/blender/python/intern/bpy_app_build_options.c @@ -69,6 +69,7 @@ static PyStructSequence_Field app_builtopts_info_fields[] = { {(char *)"player", NULL}, {(char *)"openmp", NULL}, {(char *)"openvdb", NULL}, + {(char *)"alembic", NULL}, {NULL} }; @@ -303,6 +304,12 @@ static PyObject *make_builtopts_info(void) SetObjIncref(Py_False); #endif +#ifdef WITH_ALEMBIC + SetObjIncref(Py_True); +#else + SetObjIncref(Py_False); +#endif + #undef SetObjIncref return builtopts_info; diff --git a/source/blender/python/intern/bpy_library_write.c b/source/blender/python/intern/bpy_library_write.c index f582cebb260..bf91253141a 100644 --- a/source/blender/python/intern/bpy_library_write.c +++ b/source/blender/python/intern/bpy_library_write.c @@ -50,7 +50,7 @@ PyDoc_STRVAR(bpy_lib_write_doc, -".. method:: write(filepath, datablocks, relative_remap=False, fake_user=False)\n" +".. method:: write(filepath, datablocks, relative_remap=False, fake_user=False, compress=False)\n" "\n" " Write data-blocks into a blend file.\n" "\n" diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index 2104315dc00..c16ef5500df 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -138,16 +138,81 @@ MALWAYS_INLINE int vlr_check_bake(Isect *is, ObjectInstanceRen *obi, VlakRen *UN /* Ray Triangle/Quad Intersection */ -MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *isect_precalc, RayFace *face, float r_uv[2], float *lambda) +static bool isect_ray_tri_watertight_no_sign_check_v3( + const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, float r_uv[2]) +{ + const int kx = isect_precalc->kx; + const int ky = isect_precalc->ky; + const int kz = isect_precalc->kz; + const float sx = isect_precalc->sx; + const float sy = isect_precalc->sy; + const float sz = isect_precalc->sz; + + /* Calculate vertices relative to ray origin. */ + const float a[3] = {v0[0] - ray_origin[0], v0[1] - ray_origin[1], v0[2] - ray_origin[2]}; + const float b[3] = {v1[0] - ray_origin[0], v1[1] - ray_origin[1], v1[2] - ray_origin[2]}; + const float c[3] = {v2[0] - ray_origin[0], v2[1] - ray_origin[1], v2[2] - ray_origin[2]}; + + const float a_kx = a[kx], a_ky = a[ky], a_kz = a[kz]; + const float b_kx = b[kx], b_ky = b[ky], b_kz = b[kz]; + const float c_kx = c[kx], c_ky = c[ky], c_kz = c[kz]; + + /* Perform shear and scale of vertices. */ + const float ax = a_kx - sx * a_kz; + const float ay = a_ky - sy * a_kz; + const float bx = b_kx - sx * b_kz; + const float by = b_ky - sy * b_kz; + const float cx = c_kx - sx * c_kz; + const float cy = c_ky - sy * c_kz; + + /* Calculate scaled barycentric coordinates. */ + const float u = cx * by - cy * bx; + const float v = ax * cy - ay * cx; + const float w = bx * ay - by * ax; + float det; + + if ((u < 0.0f || v < 0.0f || w < 0.0f) && + (u > 0.0f || v > 0.0f || w > 0.0f)) + { + return false; + } + + /* Calculate determinant. */ + det = u + v + w; + if (UNLIKELY(det == 0.0f)) { + return false; + } + else { + /* Calculate scaled z-coordinates of vertices and use them to calculate + * the hit distance. + */ + const float t = (u * a_kz + v * b_kz + w * c_kz) * sz; + /* Normalize u, v and t. */ + const float inv_det = 1.0f / det; + if (r_uv) { + r_uv[0] = u * inv_det; + r_uv[1] = v * inv_det; + } + *r_lambda = t * inv_det; + return true; + } +} + +MALWAYS_INLINE int isec_tri_quad(const float start[3], + const struct IsectRayPrecalc *isect_precalc, + const RayFace *face, + float r_uv[2], float *r_lambda) { float uv[2], l; if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v2, face->v3, &l, uv)) { /* check if intersection is within ray length */ - if (l > -RE_RAYTRACE_EPSILON && l < *lambda) { + if (l > -RE_RAYTRACE_EPSILON && l < *r_lambda) { r_uv[0] = -uv[0]; r_uv[1] = -uv[1]; - *lambda = l; + *r_lambda = l; return 1; } } @@ -156,10 +221,10 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *i if (RE_rayface_isQuad(face)) { if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v3, face->v4, &l, uv)) { /* check if intersection is within ray length */ - if (l > -RE_RAYTRACE_EPSILON && l < *lambda) { + if (l > -RE_RAYTRACE_EPSILON && l < *r_lambda) { r_uv[0] = -uv[0]; r_uv[1] = -uv[1]; - *lambda = l; + *r_lambda = l; return 2; } } @@ -170,24 +235,25 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *i /* Simpler yes/no Ray Triangle/Quad Intersection */ -MALWAYS_INLINE int isec_tri_quad_neighbour(float start[3], float dir[3], RayFace *face) +MALWAYS_INLINE int isec_tri_quad_neighbour(const float start[3], + const float dir[3], + const RayFace *face) { float r[3]; struct IsectRayPrecalc isect_precalc; float uv[2], l; - negate_v3_v3(r, dir); /* note, different than above function */ isect_ray_tri_watertight_v3_precalc(&isect_precalc, r); - if (isect_ray_tri_watertight_v3(start, &isect_precalc, face->v1, face->v2, face->v3, &l, uv)) { + if (isect_ray_tri_watertight_no_sign_check_v3(start, &isect_precalc, face->v1, face->v2, face->v3, &l, uv)) { return 1; } /* intersect second triangle in quad */ if (RE_rayface_isQuad(face)) { - if (isect_ray_tri_watertight_v3(start, &isect_precalc, face->v1, face->v3, face->v4, &l, uv)) { + if (isect_ray_tri_watertight_no_sign_check_v3(start, &isect_precalc, face->v1, face->v3, face->v4, &l, uv)) { return 2; } } diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 02a49fc3c8f..724a809077e 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -42,6 +42,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#if __cplusplus >= 201103L +using std::isfinite; +#endif + static bool selected_node(RTBuilder::Object *node) { return node->selected; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 604693f486e..9f1ae4a96e0 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2785,6 +2785,7 @@ static void do_render_all_options(Render *re) /* ensure no images are in memory from previous animated sequences */ BKE_image_all_free_anim_ibufs(re->r.cfra); + BKE_sequencer_all_free_anim_ibufs(re->r.cfra); if (RE_engine_render(re, 1)) { /* in this case external render overrides all */ @@ -3058,6 +3059,13 @@ bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList * } #endif + if (RE_seq_render_active(scene, &scene->r)) { + if (scene->r.mode & R_BORDER) { + BKE_report(reports, RPT_ERROR, "Border rendering is not supported by sequencer"); + return false; + } + } + /* layer flag tests */ if (!render_scene_has_layers_to_render(scene)) { BKE_report(reports, RPT_ERROR, "All render layers are disabled"); diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 01188cb7f65..b6245a8c0d1 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -146,6 +146,10 @@ if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) endif() +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif() + if(WIN32) if(WITH_INPUT_IME) add_definitions(-DWITH_INPUT_IME) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 493fe82ff80..2b82f1becb3 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -64,7 +64,10 @@ struct wmDrag; struct ImBuf; struct ImageFormatData; struct ARegion; + +#ifdef WITH_INPUT_NDOF struct wmNDOFMotionData; +#endif typedef struct wmJob wmJob; @@ -186,9 +189,10 @@ void WM_event_add_mousemove(struct bContext *C); bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event); bool WM_event_is_absolute(const struct wmEvent *event); +#ifdef WITH_INPUT_NDOF /* 3D mouse */ void WM_ndof_deadzone_set(float deadzone); - +#endif /* notifiers */ void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference); void WM_main_add_notifier(unsigned int type, void *reference); @@ -441,6 +445,7 @@ enum { WM_JOB_TYPE_SEQ_BUILD_PREVIEW, WM_JOB_TYPE_POINTCACHE, WM_JOB_TYPE_DPAINT_BAKE, + WM_JOB_TYPE_ALEMBIC, /* add as needed, screencast, seq proxy build * if having hard coded values is a problem */ }; @@ -497,11 +502,13 @@ bool write_crash_blend(void); /* Lock the interface for any communication */ void WM_set_locked_interface(struct wmWindowManager *wm, bool lock); +#ifdef WITH_INPUT_NDOF void WM_event_ndof_pan_get(const struct wmNDOFMotionData *ndof, float r_pan[3], const bool use_zoom); void WM_event_ndof_rotate_get(const struct wmNDOFMotionData *ndof, float r_rot[3]); float WM_event_ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]); void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]); +#endif /* WITH_INPUT_NDOF */ float WM_event_tablet_data(const struct wmEvent *event, int *pen_flip, float tilt[2]); bool WM_event_is_tablet(const struct wmEvent *event); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 3c0e99bddd0..0fe3e8a0fcf 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -485,6 +485,7 @@ typedef enum { /* motion progress, for modal handlers */ P_FINISHED } wmProgress; +#ifdef WITH_INPUT_NDOF typedef struct wmNDOFMotionData { /* awfully similar to GHOST_TEventNDOFMotionData... */ /* Each component normally ranges from -1 to +1, but can exceed that. @@ -496,6 +497,7 @@ typedef struct wmNDOFMotionData { float dt; /* time since previous NDOF Motion event */ wmProgress progress; /* is this the first event, the last, or one of many in between? */ } wmNDOFMotionData; +#endif /* WITH_INPUT_NDOF */ typedef struct wmTimer { struct wmTimer *next, *prev; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 01dc77127d2..77d74399769 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -567,6 +567,7 @@ void WM_event_print(const wmEvent *event) BLI_str_utf8_size(event->utf8_buf), event->utf8_buf, event->keymap_idname, (const void *)event); +#ifdef WITH_INPUT_NDOF if (ISNDOF(event->type)) { const wmNDOFMotionData *ndof = event->customdata; if (event->type == NDOF_MOTION) { @@ -577,6 +578,7 @@ void WM_event_print(const wmEvent *event) /* ndof buttons printed already */ } } +#endif /* WITH_INPUT_NDOF */ if (event->tablet_data) { const wmTabletData *wmtab = event->tablet_data; @@ -613,10 +615,12 @@ bool WM_event_is_absolute(const wmEvent *event) return (event->tablet_data != NULL); } +#ifdef WITH_INPUT_NDOF void WM_ndof_deadzone_set(float deadzone) { GHOST_setNDOFDeadZone(deadzone); } +#endif static void wm_add_reports(ReportList *reports) { @@ -2423,9 +2427,11 @@ void wm_event_do_handlers(bContext *C) /* for regions having custom cursors */ wm_paintcursor_test(C, event); } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { win->addmousemove = true; } +#endif for (sa = win->screen->areabase.first; sa; sa = sa->next) { /* after restoring a screen from SCREENMAXIMIZED we have to wait @@ -3026,6 +3032,7 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) } } +#ifdef WITH_INPUT_NDOF /* adds customdata to event */ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *ghost) { @@ -3052,6 +3059,7 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g event->customdata = data; event->customdatafree = 1; } +#endif /* WITH_INPUT_NDOF */ /* imperfect but probably usable... draw/enable drags to other windows */ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event) @@ -3439,6 +3447,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } +#ifdef WITH_INPUT_NDOF case GHOST_kEventNDOFMotion: { event.type = NDOF_MOTION; @@ -3474,6 +3483,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } +#endif /* WITH_INPUT_NDOF */ case GHOST_kEventUnknown: case GHOST_kNumEventTypes: @@ -3545,6 +3555,7 @@ void WM_set_locked_interface(wmWindowManager *wm, bool lock) } +#ifdef WITH_INPUT_NDOF /* -------------------------------------------------------------------- */ /* NDOF */ @@ -3587,6 +3598,7 @@ void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]) angle = WM_event_ndof_to_axis_angle(ndof, axis); axis_angle_to_quat(q, axis, angle); } +#endif /* WITH_INPUT_NDOF */ /* if this is a tablet event, return tablet pressure and set *pen_flip * to 1 if the eraser tool is being used, 0 otherwise */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 3022d865460..73622cda483 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -198,8 +198,11 @@ void WM_init(bContext *C, int argc, const char **argv) BLT_lang_set(NULL); if (!G.background) { + +#ifdef WITH_INPUT_NDOF /* sets 3D mouse deadzone */ WM_ndof_deadzone_set(U.ndof_deadzone); +#endif GPU_init(); diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 7ec2aea73e1..18836f34c99 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -97,6 +97,8 @@ void WM_operator_properties_filesel( RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & FILE_TYPE_COLLADA) != 0, "Filter COLLADA files", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "filter_alembic", (filter & FILE_TYPE_ALEMBIC) != 0, "Filter Alembic files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FILE_TYPE_FOLDER) != 0, "Filter folders", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "filter_blenlib", (filter & FILE_TYPE_BLENDERLIB) != 0, "Filter Blender IDs", ""); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 78273615602..0c137221856 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1369,12 +1369,13 @@ typedef struct wmOpPopUp { /* Only invoked by OK button in popups created with wm_block_dialog_create() */ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - wmOpPopUp *data = arg1; uiBlock *block = arg2; + /* Explicitly set UI_RETURN_OK flag, otherwise the menu might be cancelled + * in case WM_operator_call_ex exits/reloads the current file (T49199). */ + UI_popup_menu_retval_set(block, UI_RETURN_OK, true); + WM_operator_call_ex(C, data->op, true); /* let execute handle freeing it */ @@ -1384,8 +1385,18 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2) /* in this case, wm_operator_ui_popup_cancel wont run */ MEM_freeN(data); + /* get context data *after* WM_operator_call_ex which might have closed the current file and changed context */ + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + /* check window before 'block->handle' incase the - * popup execution closed the window and freed the block. see T44688. */ + * popup execution closed the window and freed the block. see T44688. + */ + /* Post 2.78 TODO: Check if this fix and others related to T44688 are still + * needed or can be improved now that requesting context data has been corrected + * (see above). We're close to release so not a good time for experiments. + * -- Julian + */ if (BLI_findindex(&wm->windows, win) != -1) { UI_popup_block_close(C, win, block); } @@ -4348,7 +4359,6 @@ void wm_window_keymap(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_find(keyconf, "Window", 0, 0); wmKeyMapItem *kmi; - const char *data_path; /* note, this doesn't replace existing keymap items */ WM_keymap_verify_item(keymap, "WM_OT_window_duplicate", WKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); @@ -4386,7 +4396,9 @@ void wm_window_keymap(wmKeyConfig *keyconf) /* menus that can be accessed anywhere in blender */ WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_menu(keymap, "USERPREF_MT_ndof_settings", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); +#endif /* Space switching */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F2KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was DXF export */ @@ -4433,8 +4445,9 @@ void wm_window_keymap(wmKeyConfig *keyconf) RNA_string_set(kmi->ptr, "data_path", "area.type"); RNA_string_set(kmi->ptr, "value", "DOPESHEET_EDITOR"); +#ifdef WITH_INPUT_NDOF /* ndof speed */ - data_path = "user_preferences.inputs.ndof_sensitivity"; + const char *data_path = "user_preferences.inputs.ndof_sensitivity"; kmi = WM_keymap_add_item(keymap, "WM_OT_context_scale_float", NDOF_BUTTON_PLUS, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", data_path); RNA_float_set(kmi->ptr, "value", 1.1f); @@ -4450,9 +4463,7 @@ void wm_window_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "WM_OT_context_scale_float", NDOF_BUTTON_MINUS, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", data_path); RNA_float_set(kmi->ptr, "value", 1.0f / 1.5f); - data_path = NULL; - (void)data_path; - +#endif /* WITH_INPUT_NDOF */ gesture_circle_modal_keymap(keyconf); gesture_border_modal_keymap(keyconf); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index b68b607f48b..2d43c47679d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -69,6 +69,8 @@ #include "ED_screen.h" #include "ED_fileselect.h" +#include "UI_interface.h" + #include "PIL_time.h" #include "GPU_draw.h" @@ -1194,18 +1196,30 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr break; } case GHOST_kEventNativeResolutionChange: - // printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin)); - + { + // only update if the actual pixel size changes + float prev_pixelsize = U.pixelsize; U.pixelsize = wm_window_pixelsize(win); - BKE_blender_userdef_refresh(); - wm_window_make_drawable(wm, win); - wm_draw_window_clear(win); + if (U.pixelsize != prev_pixelsize) { + BKE_blender_userdef_refresh(); + + // close all popups since they are positioned with the pixel + // size baked in and it's difficult to correct them + wmWindow *oldWindow = CTX_wm_window(C); + CTX_wm_window_set(C, win); + UI_popup_handlers_remove_all(C, &win->modalhandlers); + CTX_wm_window_set(C, oldWindow); - WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); + wm_window_make_drawable(wm, win); + wm_draw_window_clear(win); + + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); + } break; + } case GHOST_kEventTrackpad: { GHOST_TEventTrackpadData *pd = data; diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index ca841954b16..58bebc66a3e 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -58,7 +58,7 @@ if(WIN32 AND NOT UNIX) blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c ${CMAKE_SOURCE_DIR}/release/windows/icons/winblender.rc) - + WINDOWS_SIGN_TARGET(blenderplayer) install(TARGETS blenderplayer COMPONENT Blenderplayer DESTINATION ".") @@ -233,6 +233,10 @@ endif() list(APPEND BLENDER_SORTED_LIBS bf_intern_openvdb) endif() + if(WITH_ALEMBIC) + list(APPEND BLENDER_SORTED_LIBS bf_alembic) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt index 1d681d28589..0e570e19258 100644 --- a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt +++ b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt @@ -70,4 +70,8 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif() + blender_add_lib_nolist(blenkernel_blc "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index bd67462fb94..d8a4ddc8d4f 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -45,6 +45,7 @@ struct ARegion; struct ARegionType; struct BMEditMesh; struct Base; +struct bContext; struct BoundBox; struct Brush; struct CSG_FaceIteratorDescriptor; @@ -322,7 +323,22 @@ void WM_cursor_modal_restore(struct wmWindow *win) RET_NONE void WM_cursor_time(struct wmWindow *win, int nr) RET_NONE void WM_cursor_warp(struct wmWindow *win, int x, int y) RET_NONE -void WM_ndof_deadzone_set(float deadzone) RET_NONE +struct wmJob *WM_jobs_get(struct wmWindowManager *wm, struct wmWindow *win, void *owner, const char *name, int flag, int job_type) RET_NULL +void WM_jobs_customdata_set(struct wmJob *job, void *customdata, void (*free)(void *)) RET_NONE +void WM_jobs_timer(struct wmJob *job, double timestep, unsigned int note, unsigned int endnote) RET_NONE + +void WM_jobs_callbacks(struct wmJob *job, + void (*startjob)(void *, short *, short *, float *), + void (*initjob)(void *), + void (*update)(void *), + void (*endjob)(void *)) RET_NONE + +void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *job) RET_NONE +void WM_report(ReportType type, const char *message) RET_NONE + +#ifdef WITH_INPUT_NDOF + void WM_ndof_deadzone_set(float deadzone) RET_NONE +#endif void WM_uilisttype_init(void) RET_NONE struct uiListType *WM_uilisttype_find(const char *idname, bool quiet) RET_NULL @@ -623,6 +639,7 @@ void uiTemplateComponentMenu(struct uiLayout *layout, struct PointerRNA *ptr, co void uiTemplateNodeSocket(struct uiLayout *layout, struct bContext *C, float *color) RET_NONE void uiTemplatePalette(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int color) RET_NONE void uiTemplateImageStereo3d(struct uiLayout *layout, struct PointerRNA *stereo3d_format_ptr) RET_NONE +void uiTemplateCacheFile(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname) RET_NONE /* rna render */ struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname) RET_NULL diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 7acea43d1f5..fc02dfda9d1 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -263,6 +263,7 @@ if(WITH_PYTHON_MODULE) else() add_executable(blender ${EXETYPE} ${SRC}) + WINDOWS_SIGN_TARGET(blender) endif() if(WITH_BUILDINFO) diff --git a/source/creator/creator.c b/source/creator/creator.c index bfb1dd94dd4..a59a45f885c 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -54,6 +54,7 @@ #include "BKE_appdir.h" #include "BKE_blender.h" #include "BKE_brush.h" +#include "BKE_cachefile.h" #include "BKE_context.h" #include "BKE_depsgraph.h" /* for DAG_init */ #include "BKE_font.h" @@ -357,6 +358,7 @@ int main( BKE_blender_globals_init(); /* blender.c */ IMB_init(); + BKE_cachefiles_init(); BKE_images_init(); BKE_modifier_init(); DAG_init(); diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index 6c09af33f9e..577e25d6198 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -81,6 +81,10 @@ if(WIN32) blender_include_dirs(../../../../intern/utfconv) endif() +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif(WITH_INPUT_NDOF) + if(WITH_CODEC_FFMPEG) add_definitions(-DWITH_FFMPEG) endif() diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index d033afacc08..edbbf93bf7a 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -61,6 +61,7 @@ extern "C" #include "DNA_scene_types.h" #include "DNA_userdef_types.h" +#include "DNA_genfile.h" #include "BLO_readfile.h" #include "BLO_runtime.h" @@ -492,6 +493,8 @@ int main( // freeing up GPU_Textures works correctly. BLI_threadapi_init(); + DNA_sdna_current_init(); + RNA_init(); init_nodesystem(); diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp index b8907ca5c6b..5beda2e038a 100644 --- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp +++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp @@ -306,7 +306,12 @@ bool KX_NavMeshObject::BuildNavMesh() || vertsPerPoly<3) { printf("Can't build navigation mesh data for object:%s\n", m_name.ReadPtr()); - if (vertices) delete[] vertices; + if (vertices) { + delete[] vertices; + } + if (dvertices) { + delete[] dvertices; + } return false; } diff --git a/source/tools b/source/tools -Subproject 373945d0978b6601c55c9d5879e0f488b18515c +Subproject 896c5f78952adb2d091d28c65086d46992dabda |