Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarshan Kadu <darsh7807@gmail.com>2017-09-10 15:41:40 +0300
committerDarshan Kadu <darsh7807@gmail.com>2017-09-10 15:41:40 +0300
commit6594fa1ce02809a275c9cd488fa0223d03d73571 (patch)
tree0bcd95846e1e3b09239126b40ef434ed3dc3a50d
parentf2017083a19e5c83aadc575625dce0642ffce6c5 (diff)
merged the master branchsoc-2017-vertex_paint
-rw-r--r--.gitignore9
-rw-r--r--CMakeLists.txt8
-rw-r--r--GNUmakefile37
-rw-r--r--build_files/build_environment/CMakeLists.txt130
-rw-r--r--build_files/build_environment/cmake/alembic.cmake75
-rw-r--r--build_files/build_environment/cmake/blendthumb.cmake61
-rw-r--r--build_files/build_environment/cmake/blosc.cmake43
-rw-r--r--build_files/build_environment/cmake/boost.cmake99
-rw-r--r--build_files/build_environment/cmake/clang.cmake35
-rw-r--r--build_files/build_environment/cmake/clew.cmake28
-rw-r--r--build_files/build_environment/cmake/cuew.cmake29
-rw-r--r--build_files/build_environment/cmake/faad.cmake35
-rw-r--r--build_files/build_environment/cmake/ffmpeg.cmake119
-rw-r--r--build_files/build_environment/cmake/fftw.cmake40
-rw-r--r--build_files/build_environment/cmake/flac.cmake32
-rw-r--r--build_files/build_environment/cmake/flexbison.cmake31
-rw-r--r--build_files/build_environment/cmake/freeglut.cmake35
-rw-r--r--build_files/build_environment/cmake/freetype.cmake28
-rw-r--r--build_files/build_environment/cmake/glew.cmake32
-rw-r--r--build_files/build_environment/cmake/glfw.cmake28
-rw-r--r--build_files/build_environment/cmake/harvest.cmake292
-rw-r--r--build_files/build_environment/cmake/hdf5.cmake42
-rw-r--r--build_files/build_environment/cmake/hidapi.cmake29
-rw-r--r--build_files/build_environment/cmake/iconv.cmake34
-rw-r--r--build_files/build_environment/cmake/ilmbase.cmake35
-rw-r--r--build_files/build_environment/cmake/jemalloc.cmake28
-rw-r--r--build_files/build_environment/cmake/jpeg.cmake65
-rw-r--r--build_files/build_environment/cmake/lame.cmake47
-rw-r--r--build_files/build_environment/cmake/lapack.cmake43
-rw-r--r--build_files/build_environment/cmake/llvm.cmake44
-rw-r--r--build_files/build_environment/cmake/mingw.cmake40
-rw-r--r--build_files/build_environment/cmake/numpy.cmake55
-rw-r--r--build_files/build_environment/cmake/ogg.cmake32
-rw-r--r--build_files/build_environment/cmake/openal.cmake42
-rw-r--r--build_files/build_environment/cmake/opencollada.cmake37
-rw-r--r--build_files/build_environment/cmake/opencolorio.cmake70
-rw-r--r--build_files/build_environment/cmake/openexr.cmake41
-rw-r--r--build_files/build_environment/cmake/openimageio.cmake113
-rw-r--r--build_files/build_environment/cmake/openjpeg.cmake43
-rw-r--r--build_files/build_environment/cmake/opensubdiv.cmake71
-rw-r--r--build_files/build_environment/cmake/openvdb.cmake71
-rw-r--r--build_files/build_environment/cmake/options.cmake205
-rw-r--r--build_files/build_environment/cmake/orc.cmake32
-rw-r--r--build_files/build_environment/cmake/osl.cmake87
-rw-r--r--build_files/build_environment/cmake/png.cmake41
-rw-r--r--build_files/build_environment/cmake/pthreads.cmake45
-rw-r--r--build_files/build_environment/cmake/python.cmake138
-rw-r--r--build_files/build_environment/cmake/requests.cmake37
-rw-r--r--build_files/build_environment/cmake/schroedinger.cmake45
-rw-r--r--build_files/build_environment/cmake/sdl.cmake39
-rw-r--r--build_files/build_environment/cmake/setup_mingw32.cmake219
-rw-r--r--build_files/build_environment/cmake/setup_mingw64.cmake219
-rw-r--r--build_files/build_environment/cmake/sndfile.cmake44
-rw-r--r--build_files/build_environment/cmake/spnav.cmake28
-rw-r--r--build_files/build_environment/cmake/tbb.cmake36
-rw-r--r--build_files/build_environment/cmake/theora.cmake40
-rw-r--r--build_files/build_environment/cmake/tiff.cmake44
-rw-r--r--build_files/build_environment/cmake/versions.cmake245
-rw-r--r--build_files/build_environment/cmake/vorbis.cmake38
-rw-r--r--build_files/build_environment/cmake/vpx.cmake60
-rw-r--r--build_files/build_environment/cmake/webp.cmake50
-rw-r--r--build_files/build_environment/cmake/x264.cmake40
-rw-r--r--build_files/build_environment/cmake/xml2.cmake36
-rw-r--r--build_files/build_environment/cmake/xvidcore.cmake44
-rw-r--r--build_files/build_environment/cmake/zlib.cmake33
-rw-r--r--build_files/build_environment/cmake/zlib_mingw.cmake40
-rwxr-xr-xbuild_files/build_environment/install_deps.sh46
-rw-r--r--build_files/build_environment/patches/alembic.diff35
-rw-r--r--build_files/build_environment/patches/blosc.diff33
-rw-r--r--build_files/build_environment/patches/clang.diff127
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindBlosc.cmake73
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake73
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake260
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake73
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake244
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindTBB.cmake73
-rw-r--r--build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake82
-rw-r--r--build_files/build_environment/patches/cmakelists_glew.txt2
-rw-r--r--build_files/build_environment/patches/cmakelists_hidapi.txt20
-rw-r--r--build_files/build_environment/patches/cmakelists_openvdb.txt398
-rw-r--r--build_files/build_environment/patches/cmakelists_tbb.txt196
-rw-r--r--build_files/build_environment/patches/cuew.diff26
-rw-r--r--build_files/build_environment/patches/distutildebugflags.diff11
-rw-r--r--build_files/build_environment/patches/ffmpeg.diff32
-rw-r--r--build_files/build_environment/patches/fftw3.diff25
-rw-r--r--build_files/build_environment/patches/hdf5.diff11
-rw-r--r--build_files/build_environment/patches/hidapi.diff15
-rw-r--r--build_files/build_environment/patches/install_deps_llvm.diff (renamed from build_files/build_environment/install_deps_patches/llvm.patch)0
-rw-r--r--build_files/build_environment/patches/install_deps_osl.diff (renamed from build_files/build_environment/install_deps_patches/osl.patch)0
-rw-r--r--build_files/build_environment/patches/libfaad.diff10
-rw-r--r--build_files/build_environment/patches/llvm-alloca-fix.diff111
-rw-r--r--build_files/build_environment/patches/ming32sh.cmd7
-rw-r--r--build_files/build_environment/patches/ming64sh.cmd7
-rw-r--r--build_files/build_environment/patches/numpy.diff23
-rw-r--r--build_files/build_environment/patches/opencollada.diff32
-rw-r--r--build_files/build_environment/patches/opencolorio.diff21
-rw-r--r--build_files/build_environment/patches/openexr.diff33
-rw-r--r--build_files/build_environment/patches/openimageio_gdi.diff26
-rw-r--r--build_files/build_environment/patches/openimageio_idiff.diff13
-rw-r--r--build_files/build_environment/patches/openimageio_staticexr.diff10
-rw-r--r--build_files/build_environment/patches/opensubdiv.diff16
-rw-r--r--build_files/build_environment/patches/openvdb.diff11
-rw-r--r--build_files/build_environment/patches/openvdb_vc2013.diff35
-rw-r--r--build_files/build_environment/patches/osl.diff12
-rw-r--r--build_files/build_environment/patches/osl_simd_oiio.diff14
-rw-r--r--build_files/build_environment/patches/pthreads.diff13
-rw-r--r--build_files/build_environment/patches/pyshell.diff12
-rw-r--r--build_files/build_environment/patches/python.diff40
-rw-r--r--build_files/build_environment/patches/python_apple.diff48
-rw-r--r--build_files/build_environment/patches/python_runtime_vc2013.diff29
-rw-r--r--build_files/build_environment/patches/schroedinger.diff54
-rw-r--r--build_files/build_environment/patches/sdl.diff50
-rw-r--r--build_files/build_environment/patches/semi.txt1
-rw-r--r--build_files/build_environment/windows/build_deps.cmd122
-rw-r--r--build_files/build_environment/windows/buildall.cmd10
-rw-r--r--build_files/build_environment/windows/nuke.cmd52
-rw-r--r--build_files/buildbot/config/blender_linux.cmake2
-rw-r--r--build_files/buildbot/config/blender_linux_player.cmake2
-rw-r--r--build_files/buildbot/master.cfg16
-rw-r--r--build_files/buildbot/slave_compile.py4
-rw-r--r--build_files/cmake/Modules/FindOpenCOLLADA.cmake1
-rwxr-xr-xbuild_files/cmake/cmake_consistency_check.py4
-rw-r--r--build_files/cmake/platform/platform_apple.cmake9
-rw-r--r--build_files/cmake/platform/platform_win32_msvc.cmake42
-rwxr-xr-xbuild_files/cmake/project_info.py6
-rw-r--r--doc/doxygen/Doxyfile2
-rw-r--r--doc/python_api/examples/bpy.app.translations.py59
-rw-r--r--doc/python_api/examples/bpy.types.Operator.5.py15
-rw-r--r--doc/python_api/rst/bge.app.rst1
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst4
-rw-r--r--doc/python_api/rst/gpu.rst8
-rw-r--r--doc/python_api/rst/include__bmesh.rst15
-rw-r--r--doc/python_api/rst/info_overview.rst44
-rw-r--r--doc/python_api/rst/info_tutorial_addon.rst635
-rw-r--r--doc/python_api/rst_from_bmesh_opdefines.py2
-rw-r--r--doc/python_api/sphinx_doc_gen.py60
-rw-r--r--doc/python_api/static/blender_logo.svg116
-rw-r--r--doc/python_api/static/favicon.ico (renamed from doc/python_api/blender-org/static/favicon.ico)bin1150 -> 1150 bytes
-rw-r--r--extern/cuew/README.blender2
-rw-r--r--extern/cuew/include/cuew.h177
-rw-r--r--extern/cuew/src/cuew.c25
-rw-r--r--extern/curve_fit_nd/intern/curve_fit_cubic_refit.c4
-rw-r--r--intern/atomic/atomic_ops.h1
-rw-r--r--intern/atomic/intern/atomic_ops_ext.h11
-rw-r--r--intern/atomic/intern/atomic_ops_utils.h11
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp2
-rw-r--r--intern/cycles/CMakeLists.txt86
-rw-r--r--intern/cycles/blender/addon/engine.py3
-rw-r--r--intern/cycles/blender/addon/presets.py3
-rw-r--r--intern/cycles/blender/addon/properties.py40
-rw-r--r--intern/cycles/blender/addon/ui.py214
-rw-r--r--intern/cycles/blender/addon/version_update.py13
-rw-r--r--intern/cycles/blender/blender_camera.cpp11
-rw-r--r--intern/cycles/blender/blender_mesh.cpp55
-rw-r--r--intern/cycles/blender/blender_python.cpp3
-rw-r--r--intern/cycles/blender/blender_session.cpp47
-rw-r--r--intern/cycles/blender/blender_session.h9
-rw-r--r--intern/cycles/blender/blender_sync.cpp24
-rw-r--r--intern/cycles/blender/blender_sync.h3
-rw-r--r--intern/cycles/blender/blender_util.h4
-rw-r--r--intern/cycles/bvh/bvh.cpp8
-rw-r--r--intern/cycles/bvh/bvh2.cpp4
-rw-r--r--intern/cycles/bvh/bvh4.cpp28
-rw-r--r--intern/cycles/bvh/bvh_build.cpp14
-rw-r--r--intern/cycles/bvh/bvh_node.cpp11
-rw-r--r--intern/cycles/bvh/bvh_node.h1
-rw-r--r--intern/cycles/device/CMakeLists.txt2
-rw-r--r--intern/cycles/device/device.cpp4
-rw-r--r--intern/cycles/device/device.h12
-rw-r--r--intern/cycles/device/device_cpu.cpp27
-rw-r--r--intern/cycles/device/device_cuda.cpp53
-rw-r--r--intern/cycles/device/device_denoising.cpp2
-rw-r--r--intern/cycles/device/device_denoising.h2
-rw-r--r--intern/cycles/device/device_network.cpp1
-rw-r--r--intern/cycles/device/device_opencl.cpp42
-rw-r--r--intern/cycles/device/device_split_kernel.cpp4
-rw-r--r--intern/cycles/device/device_split_kernel.h4
-rw-r--r--intern/cycles/device/opencl/memory_manager.cpp253
-rw-r--r--intern/cycles/device/opencl/memory_manager.h105
-rw-r--r--intern/cycles/device/opencl/opencl.h77
-rw-r--r--intern/cycles/device/opencl/opencl_base.cpp192
-rw-r--r--intern/cycles/device/opencl/opencl_mega.cpp5
-rw-r--r--intern/cycles/device/opencl/opencl_split.cpp89
-rw-r--r--intern/cycles/device/opencl/opencl_util.cpp65
-rw-r--r--intern/cycles/kernel/CMakeLists.txt12
-rw-r--r--intern/cycles/kernel/bvh/bvh.h12
-rw-r--r--intern/cycles/kernel/bvh/bvh_nodes.h26
-rw-r--r--intern/cycles/kernel/bvh/bvh_shadow_all.h71
-rw-r--r--intern/cycles/kernel/bvh/bvh_traversal.h60
-rw-r--r--intern/cycles/kernel/bvh/qbvh_nodes.h8
-rw-r--r--intern/cycles/kernel/bvh/qbvh_shadow_all.h65
-rw-r--r--intern/cycles/kernel/bvh/qbvh_traversal.h54
-rw-r--r--intern/cycles/kernel/closure/bsdf.h5
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h18
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi.h101
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h25
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_diffuse.h8
-rw-r--r--intern/cycles/kernel/filter/filter_features.h12
-rw-r--r--intern/cycles/kernel/filter/filter_features_sse.h80
-rw-r--r--intern/cycles/kernel/filter/filter_nlm_cpu.h23
-rw-r--r--intern/cycles/kernel/filter/filter_nlm_gpu.h5
-rw-r--r--intern/cycles/kernel/filter/filter_prefilter.h94
-rw-r--r--intern/cycles/kernel/filter/filter_reconstruction.h56
-rw-r--r--intern/cycles/kernel/filter/filter_transform_sse.h16
-rw-r--r--intern/cycles/kernel/geom/geom.h1
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h904
-rw-r--r--intern/cycles/kernel/geom/geom_curve_intersect.h934
-rw-r--r--intern/cycles/kernel/geom/geom_object.h5
-rw-r--r--intern/cycles/kernel/geom/geom_volume.h8
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h93
-rw-r--r--intern/cycles/kernel/kernel_bake.h55
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h10
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h5
-rw-r--r--intern/cycles/kernel/kernel_debug.h56
-rw-r--r--intern/cycles/kernel/kernel_emission.h8
-rw-r--r--intern/cycles/kernel/kernel_globals.h68
-rw-r--r--intern/cycles/kernel/kernel_image_opencl.h66
-rw-r--r--intern/cycles/kernel/kernel_light.h261
-rw-r--r--intern/cycles/kernel/kernel_passes.h43
-rw-r--r--intern/cycles/kernel/kernel_path.h147
-rw-r--r--intern/cycles/kernel/kernel_path_branched.h133
-rw-r--r--intern/cycles/kernel/kernel_path_common.h8
-rw-r--r--intern/cycles/kernel/kernel_path_state.h44
-rw-r--r--intern/cycles/kernel/kernel_path_subsurface.h8
-rw-r--r--intern/cycles/kernel/kernel_path_surface.h42
-rw-r--r--intern/cycles/kernel/kernel_path_volume.h49
-rw-r--r--intern/cycles/kernel/kernel_queues.h15
-rw-r--r--intern/cycles/kernel/kernel_random.h261
-rw-r--r--intern/cycles/kernel/kernel_shader.h49
-rw-r--r--intern/cycles/kernel/kernel_shadow.h176
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h6
-rw-r--r--intern/cycles/kernel/kernel_textures.h181
-rw-r--r--intern/cycles/kernel/kernel_types.h113
-rw-r--r--intern/cycles/kernel/kernel_volume.h23
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_cpu.h2
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h4
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_sse41.cpp1
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu.h1
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h2
-rw-r--r--intern/cycles/kernel/kernels/cuda/filter.cu3
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel_config.h9
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel_split.cu6
-rw-r--r--intern/cycles/kernel/kernels/opencl/filter.cl3
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel.cl47
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl13
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_data_init.cl11
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl13
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_enqueue_inactive.cl26
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl15
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl13
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_path_init.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl13
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl13
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl13
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl10
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_split.cl4
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_split_function.h67
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl10
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp2
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp24
-rw-r--r--intern/cycles/kernel/osl/osl_globals.h2
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp7
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp24
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h8
-rw-r--r--intern/cycles/kernel/shaders/node_principled_bsdf.osl12
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h2
-rw-r--r--intern/cycles/kernel/split/kernel_branched.h59
-rw-r--r--intern/cycles/kernel/split/kernel_buffer_update.h64
-rw-r--r--intern/cycles/kernel/split/kernel_data_init.h29
-rw-r--r--intern/cycles/kernel/split/kernel_direct_lighting.h9
-rw-r--r--intern/cycles/kernel/split/kernel_do_volume.h35
-rw-r--r--intern/cycles/kernel/split/kernel_enqueue_inactive.h46
-rw-r--r--intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h56
-rw-r--r--intern/cycles/kernel/split/kernel_indirect_background.h3
-rw-r--r--intern/cycles/kernel/split/kernel_next_iteration_setup.h7
-rw-r--r--intern/cycles/kernel/split/kernel_path_init.h33
-rw-r--r--intern/cycles/kernel/split/kernel_queue_enqueue.h3
-rw-r--r--intern/cycles/kernel/split/kernel_scene_intersect.h32
-rw-r--r--intern/cycles/kernel/split/kernel_shader_eval.h16
-rw-r--r--intern/cycles/kernel/split/kernel_shader_sort.h10
-rw-r--r--intern/cycles/kernel/split/kernel_shadow_blocked_ao.h7
-rw-r--r--intern/cycles/kernel/split/kernel_shadow_blocked_dl.h21
-rw-r--r--intern/cycles/kernel/split/kernel_split_common.h15
-rw-r--r--intern/cycles/kernel/split/kernel_split_data_types.h31
-rw-r--r--intern/cycles/kernel/split/kernel_subsurface_scatter.h49
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h41
-rw-r--r--intern/cycles/kernel/svm/svm_image.h190
-rw-r--r--intern/cycles/render/constant_fold.cpp8
-rw-r--r--intern/cycles/render/graph.cpp25
-rw-r--r--intern/cycles/render/graph.h3
-rw-r--r--intern/cycles/render/image.cpp228
-rw-r--r--intern/cycles/render/image.h37
-rw-r--r--intern/cycles/render/integrator.cpp22
-rw-r--r--intern/cycles/render/integrator.h3
-rw-r--r--intern/cycles/render/light.cpp8
-rw-r--r--intern/cycles/render/mesh.cpp11
-rw-r--r--intern/cycles/render/nodes.cpp36
-rw-r--r--intern/cycles/render/nodes.h33
-rw-r--r--intern/cycles/render/object.cpp25
-rw-r--r--intern/cycles/render/object.h7
-rw-r--r--intern/cycles/render/osl.cpp35
-rw-r--r--intern/cycles/render/scene.cpp2
-rw-r--r--intern/cycles/render/scene.h7
-rw-r--r--intern/cycles/render/session.cpp5
-rw-r--r--intern/cycles/render/session.h3
-rw-r--r--intern/cycles/render/shader.cpp21
-rw-r--r--intern/cycles/render/shader.h6
-rw-r--r--intern/cycles/render/svm.cpp38
-rw-r--r--intern/cycles/render/svm.h3
-rw-r--r--intern/cycles/render/tile.cpp20
-rw-r--r--intern/cycles/render/tile.h3
-rw-r--r--intern/cycles/test/util_string_test.cpp37
-rw-r--r--intern/cycles/util/CMakeLists.txt1
-rw-r--r--intern/cycles/util/util_atomic.h14
-rw-r--r--intern/cycles/util/util_debug.cpp7
-rw-r--r--intern/cycles/util/util_debug.h7
-rw-r--r--intern/cycles/util/util_defines.h135
-rw-r--r--intern/cycles/util/util_logging.h16
-rw-r--r--intern/cycles/util/util_math.h12
-rw-r--r--intern/cycles/util/util_math_float3.h26
-rw-r--r--intern/cycles/util/util_math_float4.h109
-rw-r--r--intern/cycles/util/util_math_matrix.h56
-rw-r--r--intern/cycles/util/util_optimization.h52
-rw-r--r--intern/cycles/util/util_path.cpp213
-rw-r--r--intern/cycles/util/util_progress.h19
-rw-r--r--intern/cycles/util/util_simd.h184
-rw-r--r--intern/cycles/util/util_sseb.h3
-rw-r--r--intern/cycles/util/util_ssef.h3
-rw-r--r--intern/cycles/util/util_ssei.h9
-rw-r--r--intern/cycles/util/util_stats.h2
-rw-r--r--intern/cycles/util/util_string.cpp6
-rw-r--r--intern/cycles/util/util_task.cpp4
-rw-r--r--intern/cycles/util/util_time.h7
-rw-r--r--intern/cycles/util/util_types.h131
-rw-r--r--intern/elbeem/intern/isosurface.cpp33
-rw-r--r--intern/elbeem/intern/solver_util.cpp4
-rw-r--r--intern/ghost/GHOST_C-api.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm48
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp3
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm4
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp9
-rw-r--r--intern/guardedalloc/intern/mallocn_lockfree_impl.c11
-rw-r--r--intern/libmv/ChangeLog389
-rwxr-xr-xintern/libmv/bundle.sh1
-rw-r--r--intern/libmv/intern/track_region.cc2
-rw-r--r--intern/memutil/MEM_CacheLimiterC-Api.h24
-rw-r--r--intern/mikktspace/mikktspace.c130
-rw-r--r--intern/opensubdiv/opensubdiv_capi.cc70
-rw-r--r--intern/opensubdiv/opensubdiv_capi.h2
-rw-r--r--make.bat135
-rw-r--r--release/datafiles/blender_icons.svg530
-rw-r--r--release/datafiles/blender_icons16/icon16_outliner_ob_force_field.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_outliner_ob_group_instance.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_outliner_ob_force_field.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_outliner_ob_group_instance.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/colormanagement/config.ocio2
-rw-r--r--release/datafiles/splash.pngbin283527 -> 254480 bytes
-rw-r--r--release/datafiles/splash_2x.pngbin988186 -> 698643 bytes
-rw-r--r--release/scripts/freestyle/modules/freestyle/__init__.py19
-rw-r--r--release/scripts/freestyle/styles/apriori_and_causal_density.py4
-rw-r--r--release/scripts/freestyle/styles/cartoon.py2
-rw-r--r--release/scripts/freestyle/styles/external_contour_sketchy.py6
-rw-r--r--release/scripts/freestyle/styles/haloing.py8
-rw-r--r--release/scripts/freestyle/styles/invisible_lines.py2
-rw-r--r--release/scripts/freestyle/styles/long_anisotropically_dense.py8
-rw-r--r--release/scripts/freestyle/styles/multiple_parameterization.py2
-rw-r--r--release/scripts/freestyle/styles/nature.py2
-rw-r--r--release/scripts/freestyle/styles/near_lines.py2
-rw-r--r--release/scripts/freestyle/styles/qi1.py2
-rw-r--r--release/scripts/freestyle/styles/qi2.py2
-rw-r--r--release/scripts/freestyle/styles/sequentialsplit_sketchy.py2
-rw-r--r--release/scripts/freestyle/styles/sketchy_multiple_parameterization.py2
-rw-r--r--release/scripts/freestyle/styles/uniformpruning_zsort.py2
-rw-r--r--release/scripts/modules/bl_i18n_utils/settings.py4
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py2
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py90
-rw-r--r--release/scripts/modules/bpy_extras/anim_utils.py165
-rw-r--r--release/scripts/modules/keyingsets_utils.py2
-rw-r--r--release/scripts/modules/nodeitems_utils.py22
-rw-r--r--release/scripts/modules/rna_info.py35
-rw-r--r--release/scripts/modules/sys_info.py7
-rw-r--r--release/scripts/presets/cycles/integrator/direct_light.py2
-rw-r--r--release/scripts/presets/cycles/integrator/full_global_illumination.py2
-rw-r--r--release/scripts/presets/cycles/integrator/limited_global_illumination.py2
-rw-r--r--release/scripts/presets/cycles/sampling/final.py22
-rw-r--r--release/scripts/presets/cycles/sampling/preview.py22
-rw-r--r--release/scripts/presets/ffmpeg/DVD_(note_colon__this_changes_render_resolution).py (renamed from release/scripts/presets/ffmpeg/DVD (note_colon_ this changes render resolution).py)0
-rw-r--r--release/scripts/presets/ffmpeg/h264_in_MP4.py (renamed from release/scripts/presets/ffmpeg/h264 in MP4.py)0
-rw-r--r--release/scripts/presets/ffmpeg/h264_in_Matroska.py (renamed from release/scripts/presets/ffmpeg/h264 in Matroska.py)0
-rw-r--r--release/scripts/presets/ffmpeg/h264_in_Matroska_for_scrubbing.py (renamed from release/scripts/presets/ffmpeg/h264 in Matroska for scrubbing.py)0
-rw-r--r--release/scripts/presets/interface_theme/dark_blue_gradient.xml2
-rw-r--r--release/scripts/presets/interface_theme/elsyiun.xml2
-rw-r--r--release/scripts/presets/interface_theme/flatty_light.xml69
-rw-r--r--release/scripts/presets/interface_theme/science_lab.xml2
-rw-r--r--release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py2
-rw-r--r--release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py2
-rw-r--r--release/scripts/startup/bl_operators/anim.py49
-rw-r--r--release/scripts/startup/bl_operators/clip.py11
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py20
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lamp.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py13
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py60
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py16
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_field.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_softbody.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py22
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py2
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py6
-rw-r--r--release/scripts/startup/bl_ui/space_image.py8
-rw-r--r--release/scripts/startup/bl_ui/space_node.py10
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py2
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py47
-rw-r--r--release/scripts/startup/bl_ui/space_time.py2
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py26
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py17
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py40
-rw-r--r--release/scripts/startup/keyingsets_builtins.py23
-rw-r--r--release/scripts/templates_py/custom_nodes.py81
-rw-r--r--release/scripts/templates_py/gamelogic.py2
-rw-r--r--release/text/copyright.txt2
-rw-r--r--release/windows/blendthumb/CMakeLists.txt42
-rw-r--r--release/windows/blendthumb/src/BlendThumb.def5
-rw-r--r--release/windows/blendthumb/src/BlendThumb.rc26
-rw-r--r--release/windows/blendthumb/src/BlenderThumb.cpp324
-rw-r--r--release/windows/blendthumb/src/Dll.cpp277
-rw-r--r--source/blender/alembic/intern/abc_customdata.cc48
-rw-r--r--source/blender/alembic/intern/abc_customdata.h3
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc15
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc70
-rw-r--r--source/blender/alembic/intern/abc_mesh.h5
-rw-r--r--source/blender/alembic/intern/abc_object.cc56
-rw-r--r--source/blender/alembic/intern/abc_object.h10
-rw-r--r--source/blender/alembic/intern/abc_util.cc10
-rw-r--r--source/blender/alembic/intern/abc_util.h2
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc13
-rw-r--r--source/blender/blenfont/BLF_api.h2
-rw-r--r--source/blender/blenfont/intern/blf.c7
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h15
-rw-r--r--source/blender/blenkernel/BKE_action.h8
-rw-r--r--source/blender/blenkernel/BKE_animsys.h12
-rw-r--r--source/blender/blenkernel/BKE_armature.h3
-rw-r--r--source/blender/blenkernel/BKE_blender.h1
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h4
-rw-r--r--source/blender/blenkernel/BKE_boids.h2
-rw-r--r--source/blender/blenkernel/BKE_brush.h3
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h4
-rw-r--r--source/blender/blenkernel/BKE_camera.h3
-rw-r--r--source/blender/blenkernel/BKE_colortools.h4
-rw-r--r--source/blender/blenkernel/BKE_constraint.h1
-rw-r--r--source/blender/blenkernel/BKE_curve.h15
-rw-r--r--source/blender/blenkernel/BKE_deform.h4
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h14
-rw-r--r--source/blender/blenkernel/BKE_font.h1
-rw-r--r--source/blender/blenkernel/BKE_freestyle.h2
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h3
-rw-r--r--source/blender/blenkernel/BKE_group.h3
-rw-r--r--source/blender/blenkernel/BKE_icons.h6
-rw-r--r--source/blender/blenkernel/BKE_idprop.h3
-rw-r--r--source/blender/blenkernel/BKE_image.h4
-rw-r--r--source/blender/blenkernel/BKE_key.h3
-rw-r--r--source/blender/blenkernel/BKE_lamp.h3
-rw-r--r--source/blender/blenkernel/BKE_lattice.h3
-rw-r--r--source/blender/blenkernel/BKE_library.h78
-rw-r--r--source/blender/blenkernel/BKE_library_query.h2
-rw-r--r--source/blender/blenkernel/BKE_library_remap.h5
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h17
-rw-r--r--source/blender/blenkernel/BKE_mask.h9
-rw-r--r--source/blender/blenkernel/BKE_material.h3
-rw-r--r--source/blender/blenkernel/BKE_mball.h5
-rw-r--r--source/blender/blenkernel/BKE_mesh.h9
-rw-r--r--source/blender/blenkernel/BKE_modifier.h1
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h3
-rw-r--r--source/blender/blenkernel/BKE_node.h6
-rw-r--r--source/blender/blenkernel/BKE_object.h16
-rw-r--r--source/blender/blenkernel/BKE_paint.h10
-rw-r--r--source/blender/blenkernel/BKE_particle.h12
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h2
-rw-r--r--source/blender/blenkernel/BKE_property.h4
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h6
-rw-r--r--source/blender/blenkernel/BKE_sca.h14
-rw-r--r--source/blender/blenkernel/BKE_scene.h3
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h7
-rw-r--r--source/blender/blenkernel/BKE_sound.h2
-rw-r--r--source/blender/blenkernel/BKE_speaker.h3
-rw-r--r--source/blender/blenkernel/BKE_text.h3
-rw-r--r--source/blender/blenkernel/BKE_texture.h11
-rw-r--r--source/blender/blenkernel/BKE_tracking.h2
-rw-r--r--source/blender/blenkernel/BKE_world.h3
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c118
-rw-r--r--source/blender/blenkernel/intern/action.c88
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c95
-rw-r--r--source/blender/blenkernel/intern/appdir.c12
-rw-r--r--source/blender/blenkernel/intern/armature.c78
-rw-r--r--source/blender/blenkernel/intern/armature_update.c4
-rw-r--r--source/blender/blenkernel/intern/blender.c13
-rw-r--r--source/blender/blenkernel/intern/blendfile.c11
-rw-r--r--source/blender/blenkernel/intern/boids.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c50
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c19
-rw-r--r--source/blender/blenkernel/intern/cachefile.c30
-rw-r--r--source/blender/blenkernel/intern/camera.c25
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c17
-rw-r--r--source/blender/blenkernel/intern/cloth.c1
-rw-r--r--source/blender/blenkernel/intern/colortools.c4
-rw-r--r--source/blender/blenkernel/intern/constraint.c30
-rw-r--r--source/blender/blenkernel/intern/curve.c126
-rw-r--r--source/blender/blenkernel/intern/deform.c15
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c6
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c57
-rw-r--r--source/blender/blenkernel/intern/effect.c26
-rw-r--r--source/blender/blenkernel/intern/fcurve.c6
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c2
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c14
-rw-r--r--source/blender/blenkernel/intern/font.c19
-rw-r--r--source/blender/blenkernel/intern/freestyle.c18
-rw-r--r--source/blender/blenkernel/intern/gpencil.c81
-rw-r--r--source/blender/blenkernel/intern/group.c35
-rw-r--r--source/blender/blenkernel/intern/icons.c8
-rw-r--r--source/blender/blenkernel/intern/idprop.c51
-rw-r--r--source/blender/blenkernel/intern/image.c106
-rw-r--r--source/blender/blenkernel/intern/image_gen.c2
-rw-r--r--source/blender/blenkernel/intern/key.c56
-rw-r--r--source/blender/blenkernel/intern/lamp.c56
-rw-r--r--source/blender/blenkernel/intern/lattice.c45
-rw-r--r--source/blender/blenkernel/intern/library.c616
-rw-r--r--source/blender/blenkernel/intern/library_query.c3
-rw-r--r--source/blender/blenkernel/intern/library_remap.c177
-rw-r--r--source/blender/blenkernel/intern/linestyle.c127
-rw-r--r--source/blender/blenkernel/intern/mask.c40
-rw-r--r--source/blender/blenkernel/intern/material.c76
-rw-r--r--source/blender/blenkernel/intern/mball.c58
-rw-r--r--source/blender/blenkernel/intern/mesh.c276
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c90
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c17
-rw-r--r--source/blender/blenkernel/intern/modifier.c29
-rw-r--r--source/blender/blenkernel/intern/movieclip.c38
-rw-r--r--source/blender/blenkernel/intern/node.c323
-rw-r--r--source/blender/blenkernel/intern/object.c169
-rw-r--r--source/blender/blenkernel/intern/object_deform.c2
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c30
-rw-r--r--source/blender/blenkernel/intern/object_update.c12
-rw-r--r--source/blender/blenkernel/intern/ocean.c2
-rw-r--r--source/blender/blenkernel/intern/packedFile.c6
-rw-r--r--source/blender/blenkernel/intern/paint.c65
-rw-r--r--source/blender/blenkernel/intern/particle.c118
-rw-r--r--source/blender/blenkernel/intern/particle_child.c8
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c40
-rw-r--r--source/blender/blenkernel/intern/particle_system.c157
-rw-r--r--source/blender/blenkernel/intern/pbvh.c2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c17
-rw-r--r--source/blender/blenkernel/intern/property.c4
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c91
-rw-r--r--source/blender/blenkernel/intern/sca.c32
-rw-r--r--source/blender/blenkernel/intern/scene.c413
-rw-r--r--source/blender/blenkernel/intern/screen.c1
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c2
-rw-r--r--source/blender/blenkernel/intern/sequencer.c64
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c12
-rw-r--r--source/blender/blenkernel/intern/smoke.c2
-rw-r--r--source/blender/blenkernel/intern/softbody.c6
-rw-r--r--source/blender/blenkernel/intern/sound.c30
-rw-r--r--source/blender/blenkernel/intern/speaker.c28
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c19
-rw-r--r--source/blender/blenkernel/intern/text.c72
-rw-r--r--source/blender/blenkernel/intern/texture.c134
-rw-r--r--source/blender/blenkernel/intern/tracking.c44
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c109
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c148
-rw-r--r--source/blender/blenkernel/intern/unit.c11
-rw-r--r--source/blender/blenkernel/intern/world.c54
-rw-r--r--source/blender/blenkernel/tracking_private.h1
-rw-r--r--source/blender/blenlib/BLI_array.h9
-rw-r--r--source/blender/blenlib/BLI_compiler_compat.h7
-rw-r--r--source/blender/blenlib/BLI_dial.h4
-rw-r--r--source/blender/blenlib/BLI_ghash.h4
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h4
-rw-r--r--source/blender/blenlib/BLI_kdtree.h4
-rw-r--r--source/blender/blenlib/BLI_math_base.h3
-rw-r--r--source/blender/blenlib/BLI_math_geom.h10
-rw-r--r--source/blender/blenlib/BLI_math_inline.h7
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h8
-rw-r--r--source/blender/blenlib/BLI_math_vector.h6
-rw-r--r--source/blender/blenlib/BLI_rect.h3
-rw-r--r--source/blender/blenlib/BLI_stack.h8
-rw-r--r--source/blender/blenlib/BLI_strict_flags.h2
-rw-r--r--source/blender/blenlib/BLI_string_utils.h19
-rw-r--r--source/blender/blenlib/BLI_task.h7
-rw-r--r--source/blender/blenlib/BLI_utildefines.h25
-rw-r--r--source/blender/blenlib/BLI_variadic_defines.h50
-rw-r--r--source/blender/blenlib/BLI_vfontdata.h2
-rw-r--r--source/blender/blenlib/CMakeLists.txt1
-rw-r--r--source/blender/blenlib/intern/BLI_dial.c4
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c46
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c74
-rw-r--r--source/blender/blenlib/intern/BLI_kdtree.c120
-rw-r--r--source/blender/blenlib/intern/array_store.c2
-rw-r--r--source/blender/blenlib/intern/freetypefont.c30
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c15
-rw-r--r--source/blender/blenlib/intern/math_color_blend_inline.c2
-rw-r--r--source/blender/blenlib/intern/math_geom.c46
-rw-r--r--source/blender/blenlib/intern/math_matrix.c25
-rw-r--r--source/blender/blenlib/intern/math_rotation.c51
-rw-r--r--source/blender/blenlib/intern/math_vector.c96
-rw-r--r--source/blender/blenlib/intern/noise.c10
-rw-r--r--source/blender/blenlib/intern/rct.c46
-rw-r--r--source/blender/blenlib/intern/storage.c4
-rw-r--r--source/blender/blenlib/intern/string_utf8.c2
-rw-r--r--source/blender/blenlib/intern/string_utils.c88
-rw-r--r--source/blender/blenlib/intern/task.c122
-rw-r--r--source/blender/blenloader/intern/readfile.c6
-rw-r--r--source/blender/blenloader/intern/versioning_270.c34
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c7
-rw-r--r--source/blender/blenloader/intern/writefile.c3
-rw-r--r--source/blender/blentranslation/CMakeLists.txt4
-rw-r--r--source/blender/blentranslation/msgfmt/msgfmt.c9
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c3
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c200
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c69
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c62
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h4
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c2
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c8
-rw-r--r--source/blender/bmesh/operators/bmo_create.c18
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c10
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c114
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c313
-rw-r--r--source/blender/collada/AnimationExporter.cpp2
-rw-r--r--source/blender/collada/ArmatureExporter.cpp5
-rw-r--r--source/blender/collada/ControllerExporter.cpp5
-rw-r--r--source/blender/collada/DocumentExporter.cpp8
-rw-r--r--source/blender/collada/DocumentImporter.cpp8
-rw-r--r--source/blender/collada/EffectExporter.cpp134
-rw-r--r--source/blender/collada/EffectExporter.h1
-rw-r--r--source/blender/collada/ErrorHandler.cpp9
-rw-r--r--source/blender/collada/ExportSettings.h4
-rw-r--r--source/blender/collada/GeometryExporter.cpp303
-rw-r--r--source/blender/collada/GeometryExporter.h34
-rw-r--r--source/blender/collada/ImageExporter.cpp28
-rw-r--r--source/blender/collada/InstanceWriter.cpp63
-rw-r--r--source/blender/collada/InstanceWriter.h3
-rw-r--r--source/blender/collada/MaterialExporter.cpp35
-rw-r--r--source/blender/collada/MeshImporter.cpp5
-rw-r--r--source/blender/collada/SceneExporter.cpp5
-rw-r--r--source/blender/collada/collada.cpp6
-rw-r--r--source/blender/collada/collada.h14
-rw-r--r--source/blender/collada/collada_internal.cpp8
-rw-r--r--source/blender/collada/collada_internal.h1
-rw-r--r--source/blender/collada/collada_utils.cpp158
-rw-r--r--source/blender/collada/collada_utils.h10
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp33
-rw-r--r--source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp77
-rw-r--r--source/blender/compositor/operations/COM_MovieClipAttributeOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp6
-rw-r--r--source/blender/datatoc/datatoc.c5
-rw-r--r--source/blender/depsgraph/CMakeLists.txt1
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc352
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h15
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc97
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc8
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc959
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h45
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc165
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.cc4
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc121
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc127
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h23
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc72
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc8
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc8
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc18
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type_defines.cc14
-rw-r--r--source/blender/depsgraph/intern/depsgraph_types.h143
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc12
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_debug.cc6
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc46
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.cc103
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.h53
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc53
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.h10
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_operation.cc16
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_operation.h13
-rw-r--r--source/blender/editors/animation/anim_filter.c2
-rw-r--r--source/blender/editors/animation/anim_markers.c2
-rw-r--r--source/blender/editors/animation/keyframes_edit.c2
-rw-r--r--source/blender/editors/animation/keyframes_general.c1
-rw-r--r--source/blender/editors/animation/keyframing.c51
-rw-r--r--source/blender/editors/animation/keyingsets.c2
-rw-r--r--source/blender/editors/armature/armature_edit.c30
-rw-r--r--source/blender/editors/armature/armature_naming.c4
-rw-r--r--source/blender/editors/armature/armature_relations.c4
-rw-r--r--source/blender/editors/armature/pose_lib.c2
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/curve/editcurve_paint.c104
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c8
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c23
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c102
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h94
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c13
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c17
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c62
-rw-r--r--source/blender/editors/include/ED_anim_api.h2
-rw-r--r--source/blender/editors/include/ED_armature.h6
-rw-r--r--source/blender/editors/include/ED_transform.h15
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h8
-rw-r--r--source/blender/editors/include/ED_view3d.h9
-rw-r--r--source/blender/editors/include/UI_icons.h4
-rw-r--r--source/blender/editors/include/UI_interface.h4
-rw-r--r--source/blender/editors/include/UI_resources.h1
-rw-r--r--source/blender/editors/include/UI_view2d.h1
-rw-r--r--source/blender/editors/interface/interface.c54
-rw-r--r--source/blender/editors/interface/interface_handlers.c149
-rw-r--r--source/blender/editors/interface/interface_intern.h4
-rw-r--r--source/blender/editors/interface/interface_layout.c43
-rw-r--r--source/blender/editors/interface/interface_ops.c73
-rw-r--r--source/blender/editors/interface/interface_regions.c10
-rw-r--r--source/blender/editors/interface/interface_utils.c13
-rw-r--r--source/blender/editors/interface/interface_widgets.c14
-rw-r--r--source/blender/editors/interface/resources.c18
-rw-r--r--source/blender/editors/interface/view2d.c8
-rw-r--r--source/blender/editors/io/io_alembic.c22
-rw-r--r--source/blender/editors/io/io_cache.c32
-rw-r--r--source/blender/editors/io/io_collada.c46
-rw-r--r--source/blender/editors/mask/mask_ops.c2
-rw-r--r--source/blender/editors/mesh/editface.c48
-rw-r--r--source/blender/editors/mesh/editmesh_add.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c14
-rw-r--r--source/blender/editors/mesh/editmesh_select.c6
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c8
-rw-r--r--source/blender/editors/object/object_add.c172
-rw-r--r--source/blender/editors/object/object_bake_api.c27
-rw-r--r--source/blender/editors/object/object_edit.c27
-rw-r--r--source/blender/editors/object/object_group.c3
-rw-r--r--source/blender/editors/object/object_relations.c193
-rw-r--r--source/blender/editors/object/object_transform.c57
-rw-r--r--source/blender/editors/object/object_vgroup.c104
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c36
-rw-r--r--source/blender/editors/physics/particle_edit.c3
-rw-r--r--source/blender/editors/physics/particle_object.c2
-rw-r--r--source/blender/editors/physics/physics_pointcache.c42
-rw-r--r--source/blender/editors/render/render_internal.c11
-rw-r--r--source/blender/editors/render/render_preview.c2
-rw-r--r--source/blender/editors/render/render_shading.c12
-rw-r--r--source/blender/editors/screen/screen_context.c27
-rw-r--r--source/blender/editors/screen/screen_edit.c33
-rw-r--r--source/blender/editors/screen/screen_ops.c35
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c7
-rw-r--r--source/blender/editors/space_action/action_select.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_clip/clip_draw.c16
-rw-r--r--source/blender/editors/space_clip/space_clip.c1
-rw-r--r--source/blender/editors/space_clip/tracking_ops_track.c2
-rw-r--r--source/blender/editors/space_file/filelist.c81
-rw-r--r--source/blender/editors/space_file/filelist.h3
-rw-r--r--source/blender/editors/space_file/space_file.c5
-rw-r--r--source/blender/editors/space_image/image_ops.c18
-rw-r--r--source/blender/editors/space_info/info_ops.c1
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c2
-rw-r--r--source/blender/editors/space_node/node_draw.c107
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_node/node_group.c11
-rw-r--r--source/blender/editors/space_node/node_intern.h5
-rw-r--r--source/blender/editors/space_node/node_relationships.c13
-rw-r--r--source/blender/editors/space_node/space_node.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c11
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c11
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c13
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c19
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c2
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c1
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c2
-rw-r--r--source/blender/editors/space_text/text_format_pov.c925
-rw-r--r--source/blender/editors/space_text/text_format_pov_ini.c131
-rw-r--r--source/blender/editors/space_time/space_time.c2
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c10
-rw-r--r--source/blender/editors/space_view3d/drawobject.c10
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c46
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c37
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c112
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c13
-rw-r--r--source/blender/editors/transform/transform.c101
-rw-r--r--source/blender/editors/transform/transform.h3
-rw-r--r--source/blender/editors/transform/transform_conversions.c193
-rw-r--r--source/blender/editors/transform/transform_generics.c17
-rw-r--r--source/blender/editors/transform/transform_input.c11
-rw-r--r--source/blender/editors/transform/transform_manipulator.c2
-rw-r--r--source/blender/editors/transform/transform_ops.c27
-rw-r--r--source/blender/editors/transform/transform_orientations.c42
-rw-r--r--source/blender/editors/transform/transform_snap.c17
-rw-r--r--source/blender/editors/transform/transform_snap_object.c1410
-rw-r--r--source/blender/editors/util/undo.c8
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c9
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp2
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.h6
-rw-r--r--source/blender/gpu/GPU_material.h2
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c4
-rw-r--r--source/blender/gpu/intern/gpu_material.c10
-rw-r--r--source/blender/gpu/intern/gpu_select.c6
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl87
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c50
-rw-r--r--source/blender/imbuf/IMB_imbuf.h3
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h22
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c2
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c2
-rw-r--r--source/blender/imbuf/intern/colormanagement.c36
-rw-r--r--source/blender/imbuf/intern/jp2.c2
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp2
-rw-r--r--source/blender/imbuf/intern/png.c2
-rw-r--r--source/blender/imbuf/intern/rectop.c49
-rw-r--r--source/blender/imbuf/intern/tiff.c2
-rw-r--r--source/blender/makesdna/DNA_ID.h12
-rw-r--r--source/blender/makesdna/DNA_action_types.h4
-rw-r--r--source/blender/makesdna/DNA_anim_types.h2
-rw-r--r--source/blender/makesdna/DNA_brush_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h10
-rw-r--r--source/blender/makesdna/DNA_node_types.h9
-rw-r--r--source/blender/makesdna/DNA_particle_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h21
-rw-r--r--source/blender/makesdna/DNA_screen_types.h2
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h130
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h3
-rw-r--r--source/blender/makesrna/RNA_access.h3
-rw-r--r--source/blender/makesrna/RNA_define.h7
-rw-r--r--source/blender/makesrna/RNA_enum_types.h2
-rw-r--r--source/blender/makesrna/RNA_types.h4
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt3
-rw-r--r--source/blender/makesrna/intern/makesrna.c20
-rw-r--r--source/blender/makesrna/intern/rna_access.c99
-rw-r--r--source/blender/makesrna/intern/rna_animation.c5
-rw-r--r--source/blender/makesrna/intern/rna_armature.c2
-rw-r--r--source/blender/makesrna/intern/rna_curve_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_define.c134
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c36
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c2
-rw-r--r--source/blender/makesrna/intern/rna_image.c2
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_key.c2
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c1
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c1
-rw-r--r--source/blender/makesrna/intern/rna_meta_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c13
-rw-r--r--source/blender/makesrna/intern/rna_nla.c5
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c155
-rw-r--r--source/blender/makesrna/intern/rna_particle.c38
-rw-r--r--source/blender/makesrna/intern/rna_render.c16
-rw-r--r--source/blender/makesrna/intern/rna_rna.c32
-rw-r--r--source/blender/makesrna/intern/rna_scene.c57
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c14
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c5
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c8
-rw-r--r--source/blender/makesrna/intern/rna_space.c4
-rw-r--r--source/blender/makesrna/intern/rna_texture.c2
-rw-r--r--source/blender/makesrna/intern/rna_ui.c45
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c43
-rw-r--r--source/blender/makesrna/intern/rna_wm.c316
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c8
-rw-r--r--source/blender/modifiers/intern/MOD_array.c43
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c14
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c3
-rw-r--r--source/blender/modifiers/intern/MOD_build.c2
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c5
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c7
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c7
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c11
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c1
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c2
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c15
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.c3
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_pc2.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c6
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c26
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c2
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c2
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c31
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c61
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c3
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c4
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c6
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c8
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c17
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switchview.c1
-rw-r--r--source/blender/nodes/intern/node_exec.c3
-rw-r--r--source/blender/nodes/shader/node_shader_util.c52
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_fresnel.c19
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_layer_weight.c19
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c6
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c43
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c78
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c5
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c11
-rw-r--r--source/blender/python/generic/bpy_internal_import.c13
-rw-r--r--source/blender/python/generic/idprop_py_api.c6
-rw-r--r--source/blender/python/generic/py_capi_utils.c187
-rw-r--r--source/blender/python/generic/py_capi_utils.h43
-rw-r--r--source/blender/python/generic/python_utildefines.h6
-rw-r--r--source/blender/python/intern/CMakeLists.txt9
-rw-r--r--source/blender/python/intern/bpy_app.c24
-rw-r--r--source/blender/python/intern/bpy_app_alembic.c6
-rw-r--r--source/blender/python/intern/bpy_app_ffmpeg.c5
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c8
-rw-r--r--source/blender/python/intern/bpy_app_ocio.c7
-rw-r--r--source/blender/python/intern/bpy_app_oiio.c7
-rw-r--r--source/blender/python/intern/bpy_app_opensubdiv.c110
-rw-r--r--source/blender/python/intern/bpy_app_opensubdiv.h32
-rw-r--r--source/blender/python/intern/bpy_app_openvdb.c7
-rw-r--r--source/blender/python/intern/bpy_app_sdl.c8
-rw-r--r--source/blender/python/intern/bpy_interface.c1
-rw-r--r--source/blender/python/intern/bpy_library_load.c4
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c14
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.h4
-rw-r--r--source/blender/python/intern/bpy_props.c41
-rw-r--r--source/blender/python/intern/bpy_rna.c161
-rw-r--r--source/blender/python/intern/bpy_rna_array.c4
-rw-r--r--source/blender/python/intern/bpy_rna_driver.c10
-rw-r--r--source/blender/python/intern/gpu_offscreen.c34
-rw-r--r--source/blender/python/mathutils/mathutils.c39
-rw-r--r--source/blender/python/mathutils/mathutils.h11
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c67
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.h5
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c891
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c5
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c2
-rw-r--r--source/blender/render/intern/include/render_types.h2
-rw-r--r--source/blender/render/intern/include/shading.h2
-rw-r--r--source/blender/render/intern/raytrace/rayobject_rtbuild.cpp12
-rw-r--r--source/blender/render/intern/raytrace/rayobject_rtbuild.h5
-rw-r--r--source/blender/render/intern/source/bake_api.c4
-rw-r--r--source/blender/render/intern/source/convertblender.c23
-rw-r--r--source/blender/render/intern/source/pipeline.c4
-rw-r--r--source/blender/render/intern/source/rendercore.c38
-rw-r--r--source/blender/render/intern/source/shadeinput.c6
-rw-r--r--source/blender/render/intern/source/sunsky.c2
-rw-r--r--source/blender/render/intern/source/zbuf.c1
-rw-r--r--source/blender/windowmanager/WM_api.h5
-rw-r--r--source/blender/windowmanager/intern/wm.c11
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c17
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c98
-rw-r--r--source/blender/windowmanager/intern/wm_files.c135
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c3
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c7
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c71
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c5
-rw-r--r--source/blender/windowmanager/intern/wm_window.c31
-rw-r--r--source/blender/windowmanager/wm_event_system.h3
-rw-r--r--source/blender/windowmanager/wm_files.h2
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c17
-rw-r--r--source/creator/CMakeLists.txt119
-rw-r--r--source/gameengine/GameLogic/CMakeLists.txt3
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp6
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_MouseDevice.h2
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_FontObject.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp2
-rw-r--r--source/gameengine/VideoTexture/FilterBase.cpp1
-rw-r--r--source/gameengine/VideoTexture/ImageBase.cpp1
-rw-r--r--tests/CMakeLists.txt5
-rw-r--r--tests/check_deprecated.py6
-rw-r--r--tests/gtests/blenlib/BLI_kdopbvh_test.cc97
-rw-r--r--tests/gtests/blenlib/BLI_math_geom_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_polyfill2d_test.cc2
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt28
-rw-r--r--tests/gtests/blenlib/stubs/bf_intern_eigen_stubs.h18
-rw-r--r--tests/python/CMakeLists.txt246
-rwxr-xr-xtests/python/alembic_tests.py2
-rw-r--r--tests/python/batch_import.py6
-rw-r--r--tests/python/bl_alembic_import_test.py56
-rw-r--r--tests/python/bl_keymap_completeness.py1
-rw-r--r--tests/python/bl_load_py_modules.py69
-rw-r--r--tests/python/bl_pyapi_bpy_utils_units.py19
-rw-r--r--tests/python/bl_run_operators.py6
-rwxr-xr-xtests/python/cycles_render_tests.py298
-rw-r--r--tests/python/pep8.py1
-rw-r--r--tests/python/rna_info_dump.py1
1039 files changed, 28006 insertions, 14058 deletions
diff --git a/.gitignore b/.gitignore
index 977fd9c2627..814b7661bc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,7 +21,6 @@ Desktop.ini
# commonly used paths in blender
/blender.bin
-/user-config.py
/BUILD_NOTES.txt
# local patches
@@ -34,8 +33,6 @@ Desktop.ini
/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
+
+# in-source lib downloads
+/build_files/build_environment/downloads
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 66ee215864d..5ca1eda8ebb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,7 +32,7 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
if(NOT DEFINED WITH_IN_SOURCE_BUILD)
message(FATAL_ERROR
"CMake generation for blender is not allowed within the source directory!"
- "\n Remove the CMakeCache.txt file and try again from another folder, e.g.:"
+ "\n Remove \"${CMAKE_SOURCE_DIR}/CMakeCache.txt\" and try again from another folder, e.g.:"
"\n "
"\n rm CMakeCache.txt"
"\n cd .."
@@ -58,7 +58,9 @@ 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")
+if(NOT DEFINED CMAKE_BUILD_TYPE_INIT)
+ set(CMAKE_BUILD_TYPE_INIT "Release")
+endif()
# quiet output for Makefiles, 'make -s' helps too
# set_property(GLOBAL PROPERTY RULE_MESSAGES OFF)
@@ -287,7 +289,7 @@ if(WITH_X11)
endif()
if(UNIX AND NOT APPLE)
- option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" ON)
+ option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
else()
# not an option for other OS's
diff --git a/GNUmakefile b/GNUmakefile
index 86964e68873..d1e575cfc3c 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -43,6 +43,11 @@ ifndef BUILD_DIR
BUILD_DIR:=$(shell dirname "$(BLENDER_DIR)")/build_$(OS_NCASE)
endif
+# Dependencies DIR's
+DEPS_SOURCE_DIR:=$(BLENDER_DIR)/build_files/build_environment
+DEPS_BUILD_DIR:=$(BUILD_DIR)/deps
+DEPS_INSTALL_DIR:=$(shell dirname "$(BLENDER_DIR)")/lib/$(OS_NCASE)
+
# Allow to use alternative binary (pypy3, etc)
ifndef PYTHON
PYTHON:=python3
@@ -86,13 +91,7 @@ ifndef NPROCS
ifeq ($(OS), Linux)
NPROCS:=$(shell nproc)
endif
- ifeq ($(OS), Darwin)
- NPROCS:=$(shell sysctl -n hw.ncpu)
- endif
- ifeq ($(OS), FreeBSD)
- NPROCS:=$(shell sysctl -n hw.ncpu)
- endif
- ifeq ($(OS), NetBSD)
+ ifneq (,$(filter $(OS),Darwin FreeBSD NetBSD))
NPROCS:=$(shell sysctl -n hw.ncpu)
endif
endif
@@ -104,7 +103,7 @@ endif
CMAKE_CONFIG = cmake $(BUILD_CMAKE_ARGS) \
-H"$(BLENDER_DIR)" \
-B"$(BUILD_DIR)" \
- -DCMAKE_BUILD_TYPE:STRING=$(BUILD_TYPE)
+ -DCMAKE_BUILD_TYPE_INIT:STRING=$(BUILD_TYPE)
# -----------------------------------------------------------------------------
@@ -146,6 +145,27 @@ cycles: all
headless: all
bpy: all
+# -----------------------------------------------------------------------------
+# Build dependencies
+DEPS_TARGET = install
+ifneq "$(findstring clean, $(MAKECMDGOALS))" ""
+ DEPS_TARGET = clean
+endif
+
+deps: .FORCE
+ @echo
+ @echo Configuring dependencies in \"$(DEPS_BUILD_DIR)\"
+
+ @cmake -H"$(DEPS_SOURCE_DIR)" \
+ -B"$(DEPS_BUILD_DIR)" \
+ -DHARVEST_TARGET=$(DEPS_INSTALL_DIR)
+
+ @echo
+ @echo Building dependencies ...
+ $(MAKE) -C "$(DEPS_BUILD_DIR)" -s -j $(NPROCS) $(DEPS_TARGET)
+ @echo
+ @echo Dependencies successfully built and installed to $(DEPS_INSTALL_DIR).
+ @echo
# -----------------------------------------------------------------------------
# Configuration (save some cd'ing around)
@@ -164,6 +184,7 @@ help: .FORCE
@echo " * headless - build without an interface (renderfarm or server automation)"
@echo " * cycles - build Cycles standalone only, without Blender"
@echo " * bpy - build as a python module which can be loaded from python directly"
+ @echo " * deps - build library dependencies (intended only for platform maintainers)"
@echo ""
@echo " * config - run cmake configuration tool to set build options"
@echo ""
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
new file mode 100644
index 00000000000..5bcfd477d71
--- /dev/null
+++ b/build_files/build_environment/CMakeLists.txt
@@ -0,0 +1,130 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+####################################################################################################
+#
+# This is a build system used by platform maintainers to build library dependencies on
+# Windows and macOS. There is some support for Linux as well, but not ready for releases.
+#
+# Windows and macOS users should download the precompiled libraries in lib/, Linux users
+# should run install_deps.sh for building dependencies.
+#
+# WINDOWS USAGE:
+# Don't call this cmake file your self, use build_deps.cmd
+# build_deps 2013 x64 / build_deps 2013 x86
+# build_deps 2015 x64 / build_deps 2015 x86
+#
+# MAC OS X USAGE:
+# Install with homebrew: brew install autoconf automake libtool yasm openssl xz
+# Run "make deps" from main Blender directory
+#
+# LINUX USAGE:
+# Install compiler, cmake, autoconf, automake, libtool, yasm
+# Run "make deps" from main Blender directory
+#
+####################################################################################################
+
+project("BlenderDependencies")
+cmake_minimum_required(VERSION 3.5)
+
+include(ExternalProject)
+include(cmake/options.cmake)
+include(cmake/versions.cmake)
+include(cmake/zlib.cmake)
+include(cmake/blendthumb.cmake)
+include(cmake/openal.cmake)
+include(cmake/png.cmake)
+include(cmake/jpeg.cmake)
+include(cmake/boost.cmake)
+include(cmake/blosc.cmake)
+include(cmake/pthreads.cmake)
+include(cmake/ilmbase.cmake)
+include(cmake/openexr.cmake)
+include(cmake/freetype.cmake)
+include(cmake/freeglut.cmake)
+include(cmake/glew.cmake)
+include(cmake/hdf5.cmake)
+include(cmake/alembic.cmake)
+include(cmake/glfw.cmake)
+include(cmake/clew.cmake)
+include(cmake/cuew.cmake)
+include(cmake/opensubdiv.cmake)
+include(cmake/sdl.cmake)
+include(cmake/opencollada.cmake)
+include(cmake/opencolorio.cmake)
+include(cmake/llvm.cmake)
+include(cmake/clang.cmake)
+include(cmake/openimageio.cmake)
+include(cmake/tiff.cmake)
+include(cmake/flexbison.cmake)
+include(cmake/osl.cmake)
+include(cmake/tbb.cmake)
+include(cmake/openvdb.cmake)
+include(cmake/python.cmake)
+include(cmake/requests.cmake)
+include(cmake/numpy.cmake)
+include(cmake/webp.cmake)
+if(WIN32)
+ include(cmake/hidapi.cmake)
+endif()
+
+if(ENABLE_MINGW64)
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+ include(cmake/setup_mingw64.cmake)
+ else()
+ include(cmake/setup_mingw32.cmake)
+ endif()
+else()
+ set(mingw_LIBDIR ${LIBDIR})
+endif()
+
+if(NOT WIN32 OR ENABLE_MINGW64)
+ if(BUILD_MODE STREQUAL Release)
+ if(WIN32)
+ include(cmake/zlib_mingw.cmake)
+ endif()
+ include(cmake/lame.cmake)
+ include(cmake/ogg.cmake)
+ include(cmake/vorbis.cmake)
+ include(cmake/theora.cmake)
+ include(cmake/vpx.cmake)
+ include(cmake/orc.cmake)
+ include(cmake/schroedinger.cmake)
+ include(cmake/x264.cmake)
+ include(cmake/xvidcore.cmake)
+ include(cmake/openjpeg.cmake)
+ include(cmake/faad.cmake)
+ include(cmake/ffmpeg.cmake)
+ include(cmake/fftw.cmake)
+ include(cmake/sndfile.cmake)
+ if(WIN32)
+ include(cmake/iconv.cmake)
+ include(cmake/lapack.cmake)
+ endif()
+ if(UNIX)
+ include(cmake/flac.cmake)
+ if(NOT APPLE)
+ include(cmake/spnav.cmake)
+ include(cmake/jemalloc.cmake)
+ include(cmake/xml2.cmake)
+ endif()
+ endif()
+ endif()
+endif()
+
+include(cmake/harvest.cmake)
diff --git a/build_files/build_environment/cmake/alembic.cmake b/build_files/build_environment/cmake/alembic.cmake
new file mode 100644
index 00000000000..a49047ec102
--- /dev/null
+++ b/build_files/build_environment/cmake/alembic.cmake
@@ -0,0 +1,75 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(ALEMBIC_HDF5)
+ set(ALEMBIC_HDF5_HL)
+ # in debug mode we do not build HDF5_hdf5_hl_LIBRARY which makes cmake really
+ # unhappy, stub it with the debug mode lib. it's not linking it in at this
+ # point in time anyhow
+ if(BUILD_MODE STREQUAL Debug)
+ set(ALEMBIC_HDF5_HL -DHDF5_hdf5_hl_LIBRARY=${LIBDIR}/hdf5/lib/libhdf5_hl_D.${LIBEXT})
+ endif()
+endif()
+
+set(ALEMBIC_EXTRA_ARGS
+ -DBUILDSTATIC=ON
+ -DLINKSTATIC=ON
+ -DALEMBIC_LIB_USES_BOOST=ON
+ -DBoost_COMPILER:STRING=${BOOST_COMPILER_STRING}
+ -DBoost_USE_MULTITHREADED=ON
+ -DUSE_STATIC_BOOST=On
+ -DBoost_USE_STATIC_LIBS=ON
+ -DBoost_USE_STATIC_RUNTIME=ON
+ -DBoost_DEBUG=ON
+ -DBOOST_ROOT=${LIBDIR}/boost
+ -DBoost_NO_SYSTEM_PATHS=ON
+ -DILMBASE_ROOT=${LIBDIR}/ilmbase
+ -DALEMBIC_ILMBASE_INCLUDE_DIRECTORY=${LIBDIR}/ilmbase/include/OpenEXR
+ -DALEMBIC_ILMBASE_HALF_LIB=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Half${LIBEXT}
+ -DALEMBIC_ILMBASE_IMATH_LIB=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Imath-2_2${LIBEXT}
+ -DALEMBIC_ILMBASE_ILMTHREAD_LIB=${LIBDIR}/ilmbase/lib/${LIBPREFIX}IlmThread-2_2${LIBEXT}
+ -DALEMBIC_ILMBASE_IEX_LIB=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Iex-2_2${LIBEXT}
+ -DUSE_PYILMBASE=0
+ -DUSE_PYALEMBIC=0
+ -DUSE_ARNOLD=0
+ -DUSE_MAYA=0
+ -DUSE_PRMAN=0
+ -DUSE_HDF5=Off
+ -DUSE_STATIC_HDF5=Off
+ -DHDF5_ROOT=${LIBDIR}/hdf5
+ -DUSE_TESTS=Off
+ -DALEMBIC_NO_OPENGL=1
+ -DUSE_BINARIES=ON
+ -DALEMBIC_ILMBASE_LINK_STATIC=On
+ -DALEMBIC_SHARED_LIBS=OFF
+ -DGLUT_INCLUDE_DIR=""
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include/
+ ${ALEMBIC_HDF5_HL}
+)
+
+ExternalProject_Add(external_alembic
+ URL ${ALEMBIC_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${ALEMBIC_MD5}
+ PREFIX ${BUILD_DIR}/alembic
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/alembic -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${ALEMBIC_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/alembic
+)
+
+add_dependencies(external_alembic external_boost external_zlib external_ilmbase)
diff --git a/build_files/build_environment/cmake/blendthumb.cmake b/build_files/build_environment/cmake/blendthumb.cmake
new file mode 100644
index 00000000000..624869971c6
--- /dev/null
+++ b/build_files/build_environment/cmake/blendthumb.cmake
@@ -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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(BUILD_MODE STREQUAL Release)
+ if(WIN32)
+ set(THUMB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../release/windows/blendthumb)
+
+ ExternalProject_Add(external_zlib_32
+ URL ${ZLIB_URI}
+ CMAKE_GENERATOR ${GENERATOR_32}
+ URL_HASH MD5=${ZLIB_HASH}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ PREFIX ${BUILD_DIR}/zlib32
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/zlib32 ${DEFAULT_CMAKE_FLAGS}
+ INSTALL_DIR ${LIBDIR}/zlib32
+ )
+
+ ExternalProject_Add(external_zlib_64
+ URL ${ZLIB_URI}
+ CMAKE_GENERATOR ${GENERATOR_64}
+ URL_HASH MD5=${ZLIB_HASH}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ PREFIX ${BUILD_DIR}/zlib64
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/zlib64 ${DEFAULT_CMAKE_FLAGS}
+ INSTALL_DIR ${LIBDIR}/zlib64
+ )
+
+ ExternalProject_Add(external_blendthumb_32
+ CMAKE_GENERATOR ${GENERATOR_32}
+ SOURCE_DIR ${THUMB_DIR}
+ PREFIX ${BUILD_DIR}/blendthumb32
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/blendThumb32 ${DEFAULT_CMAKE_FLAGS} -DZLIB_INCLUDE=${LIBDIR}/zlib32/include -DZLIB_LIBS=${LIBDIR}/zlib32/lib/zlibstatic.lib
+ INSTALL_DIR ${LIBDIR}/blendthumb32
+ )
+ add_dependencies(external_blendthumb_32 external_zlib_32)
+
+ ExternalProject_Add(external_blendthumb_64
+ CMAKE_GENERATOR ${GENERATOR_64}
+ SOURCE_DIR ${THUMB_DIR}
+ PREFIX ${BUILD_DIR}/blendthumb64
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/blendThumb64 ${DEFAULT_CMAKE_FLAGS} -DZLIB_INCLUDE=${LIBDIR}/zlib64/include -DZLIB_LIBS=${LIBDIR}/zlib64/lib/zlibstatic.lib
+ INSTALL_DIR ${LIBDIR}/blendthumb64
+ )
+ add_dependencies(external_blendthumb_64 external_zlib_64)
+ endif()
+endif()
diff --git a/build_files/build_environment/cmake/blosc.cmake b/build_files/build_environment/cmake/blosc.cmake
new file mode 100644
index 00000000000..68df525b802
--- /dev/null
+++ b/build_files/build_environment/cmake/blosc.cmake
@@ -0,0 +1,43 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(BLOSC_EXTRA_ARGS
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include/
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DBUILD_TESTS=OFF
+ -DBUILD_BENCHMARKS=OFF
+ -DCMAKE_DEBUG_POSTFIX=_d
+ -DThreads_FOUND=1
+ -DPTHREAD_LIBS=${LIBDIR}/pthreads/lib/pthreadVC2.lib
+ -DPTHREAD_INCLUDE_DIR=${LIBDIR}/pthreads/inc
+)
+
+ExternalProject_Add(external_blosc
+ URL ${BLOSC_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${BLOSC_HASH}
+ PREFIX ${BUILD_DIR}/blosc
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/blosc/src/external_blosc < ${PATCH_DIR}/blosc.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/blosc ${DEFAULT_CMAKE_FLAGS} ${BLOSC_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/blosc
+)
+
+add_dependencies(external_blosc external_zlib)
+if(WIN32)
+ add_dependencies(external_blosc external_pthreads)
+endif()
diff --git a/build_files/build_environment/cmake/boost.cmake b/build_files/build_environment/cmake/boost.cmake
new file mode 100644
index 00000000000..554db6583b7
--- /dev/null
+++ b/build_files/build_environment/cmake/boost.cmake
@@ -0,0 +1,99 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+ set(PYTHON_ARCH x64)
+ set(PYTHON_ARCH2 win-AMD64)
+ set(PYTHON_OUTPUTDIR ${BUILD_DIR}/python/src/external_python/pcbuild/amd64/)
+ else()
+ set(PYTHON_ARCH x86)
+ set(PYTHON_ARCH2 win32)
+ set(PYTHON_OUTPUTDIR ${BUILD_DIR}/python/src/external_python/pcbuild/win32/)
+ endif()
+ if(MSVC12)
+ set(BOOST_TOOLSET toolset=msvc-12.0)
+ set(BOOST_COMPILER_STRING -vc120)
+ set(PYTHON_COMPILER_STRING v120)
+ endif()
+ if(MSVC14)
+ set(BOOST_TOOLSET toolset=msvc-14.0)
+ set(BOOST_COMPILER_STRING -vc140)
+ set(PYTHON_COMPILER_STRING v140)
+ endif()
+ set(JAM_FILE ${BUILD_DIR}/boost/src/external_boost/user-config.jam)
+ set(semi_path "${PATCH_DIR}/semi.txt")
+ FILE(TO_NATIVE_PATH ${semi_path} semi_path)
+ set(BOOST_CONFIGURE_COMMAND bootstrap.bat &&
+ echo using python : 3.5 : ${PYTHON_OUTPUTDIR}\\python.exe > "${JAM_FILE}" &&
+ echo. : ${BUILD_DIR}/python/src/external_python/include ${BUILD_DIR}/python/src/external_python/pc >> "${JAM_FILE}" &&
+ echo. : ${BUILD_DIR}/python/src/external_python/pcbuild >> "${JAM_FILE}" &&
+ type ${semi_path} >> "${JAM_FILE}"
+ )
+ set(BOOST_BUILD_COMMAND bjam)
+ set(BOOST_BUILD_OPTIONS runtime-link=static --user-config=user-config.jam)
+ set(BOOST_WITH_PYTHON --with-python)
+elseif(APPLE)
+ set(BOOST_CONFIGURE_COMMAND ./bootstrap.sh)
+ set(BOOST_BUILD_COMMAND ./bjam)
+ set(BOOST_BUILD_OPTIONS toolset=clang cxxflags=${PLATFORM_CXXFLAGS} linkflags=${PLATFORM_LDFLAGS} --disable-icu boost.locale.icu=off)
+else()
+ set(BOOST_CONFIGURE_COMMAND ./bootstrap.sh)
+ set(BOOST_BUILD_COMMAND ./bjam)
+ set(BOOST_BUILD_OPTIONS cxxflags=${PLATFORM_CXXFLAGS} --disable-icu boost.locale.icu=off)
+endif()
+
+set(BOOST_OPTIONS
+ --with-filesystem
+ --with-locale
+ --with-thread
+ --with-regex
+ --with-system
+ --with-date_time
+ --with-wave
+ --with-atomic
+ --with-serialization
+ --with-program_options
+ --with-iostreams
+ ${BOOST_WITH_PYTHON}
+ ${BOOST_TOOLSET}
+)
+
+if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+ set(BOOST_ADDRESS_MODEL 64)
+else()
+ set(BOOST_ADDRESS_MODEL 32)
+endif()
+
+string(TOLOWER ${BUILD_MODE} BOOST_BUILD_TYPE)
+
+ExternalProject_Add(external_boost
+ URL ${BOOST_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${BOOST_MD5}
+ PREFIX ${BUILD_DIR}/boost
+ UPDATE_COMMAND ""
+ CONFIGURE_COMMAND ${BOOST_CONFIGURE_COMMAND}
+ BUILD_COMMAND ${BOOST_BUILD_COMMAND} ${BOOST_BUILD_OPTIONS} -j${MAKE_THREADS} architecture=x86 address-model=${BOOST_ADDRESS_MODEL} variant=${BOOST_BUILD_TYPE} link=static threading=multi ${BOOST_OPTIONS} --prefix=${LIBDIR}/boost install
+ BUILD_IN_SOURCE 1
+ INSTALL_COMMAND ""
+)
+
+if(WIN32)
+ add_dependencies(external_boost Make_Python_Environment)
+endif()
diff --git a/build_files/build_environment/cmake/clang.cmake b/build_files/build_environment/cmake/clang.cmake
new file mode 100644
index 00000000000..8d57c4dfc6f
--- /dev/null
+++ b/build_files/build_environment/cmake/clang.cmake
@@ -0,0 +1,35 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(CLANG_EXTRA_ARGS
+ -DCLANG_PATH_TO_LLVM_SOURCE=${BUILD_DIR}/ll/src/ll
+ -DCLANG_PATH_TO_LLVM_BUILD=${LIBDIR}/llvm
+ -DLLVM_USE_CRT_RELEASE=MT
+ -DLLVM_USE_CRT_DEBUG=MTd
+)
+ExternalProject_Add(external_clang
+ URL ${CLANG_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${CLANG_HASH}
+ PATCH_COMMAND ${PATCH_CMD} -p 2 -N -R -d ${BUILD_DIR}/clang/src/external_clang < ${PATCH_DIR}/clang.diff
+ PREFIX ${BUILD_DIR}/clang
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/llvm ${DEFAULT_CMAKE_FLAGS} ${CLANG_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/llvm
+)
+
+add_dependencies(external_clang ll)
diff --git a/build_files/build_environment/cmake/clew.cmake b/build_files/build_environment/cmake/clew.cmake
new file mode 100644
index 00000000000..0dcc1f24db7
--- /dev/null
+++ b/build_files/build_environment/cmake/clew.cmake
@@ -0,0 +1,28 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(CLEW_EXTRA_ARGS)
+
+ExternalProject_Add(external_clew
+ URL ${CLEW_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${CLEW_HASH}
+ PREFIX ${BUILD_DIR}/clew
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/clew -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${CLEW_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/clew
+)
diff --git a/build_files/build_environment/cmake/cuew.cmake b/build_files/build_environment/cmake/cuew.cmake
new file mode 100644
index 00000000000..99b7bb5c06d
--- /dev/null
+++ b/build_files/build_environment/cmake/cuew.cmake
@@ -0,0 +1,29 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(CUEW_EXTRA_ARGS)
+
+ExternalProject_Add(external_cuew
+ URL ${CUEW_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${CUEW_HASH}
+ PREFIX ${BUILD_DIR}/cuew
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/cuew/src/external_cuew < ${PATCH_DIR}/cuew.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/cuew -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${CUEW_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/cuew
+)
diff --git a/build_files/build_environment/cmake/faad.cmake b/build_files/build_environment/cmake/faad.cmake
new file mode 100644
index 00000000000..3dd90971b84
--- /dev/null
+++ b/build_files/build_environment/cmake/faad.cmake
@@ -0,0 +1,35 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(FAAD_EXTRA_ARGS)
+
+ExternalProject_Add(external_faad
+ URL ${FAAD_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${FAAD_HASH}
+ PREFIX ${BUILD_DIR}/faad
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/faad/src/external_faad < ${PATCH_DIR}/libfaad.diff
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/faad/src/external_faad/ && ${CONFIGURE_COMMAND} --disable-shared --enable-static --prefix=${LIBDIR}/faad
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/faad/src/external_faad/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/faad/src/external_faad/ && make install
+ INSTALL_DIR ${LIBDIR}/faad
+)
+
+if(MSVC)
+ set_target_properties(external_faad PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/ffmpeg.cmake b/build_files/build_environment/cmake/ffmpeg.cmake
new file mode 100644
index 00000000000..2a45849acf5
--- /dev/null
+++ b/build_files/build_environment/cmake/ffmpeg.cmake
@@ -0,0 +1,119 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(FFMPEG_CFLAGS "-I${mingw_LIBDIR}/lame/include -I${mingw_LIBDIR}/openjpeg/include/ -I${mingw_LIBDIR}/ogg/include -I${mingw_LIBDIR}/vorbis/include -I${mingw_LIBDIR}/theora/include -I${mingw_LIBDIR}/vpx/include -I${mingw_LIBDIR}/x264/include -I${mingw_LIBDIR}/xvidcore/include -I${mingw_LIBDIR}/dirac/include/dirac -I${mingw_LIBDIR}/schroedinger/include/schroedinger-1.0 -I${mingw_LIBDIR}/zlib/include")
+set(FFMPEG_LDFLAGS "-L${mingw_LIBDIR}/lame/lib -L${mingw_LIBDIR}/openjpeg/lib -L${mingw_LIBDIR}/ogg/lib -L${mingw_LIBDIR}/vorbis/lib -L${mingw_LIBDIR}/theora/lib -L${mingw_LIBDIR}/vpx/lib -L${mingw_LIBDIR}/x264/lib -L${mingw_LIBDIR}/xvidcore/lib -L${mingw_LIBDIR}/dirac/lib -L${mingw_LIBDIR}/schroedinger/lib -L${mingw_LIBDIR}/orc/lib -L${mingw_LIBDIR}/zlib/lib")
+set(FFMPEG_EXTRA_FLAGS --extra-cflags=${FFMPEG_CFLAGS} --extra-ldflags=${FFMPEG_LDFLAGS})
+set(FFMPEG_ENV PKG_CONFIG_PATH=${mingw_LIBDIR}/schroedinger/lib/pkgconfig:${mingw_LIBDIR}/orc/lib/pkgconfig:${mingw_LIBDIR}/x264/lib/pkgconfig:${mingw_LIBDIR})
+
+if(WIN32)
+ set(FFMPEG_ENV set ${FFMPEG_ENV} &&)
+ set(FFMPEG_EXTRA_FLAGS
+ ${FFMPEG_EXTRA_FLAGS}
+ --disable-static
+ --enable-shared
+ --enable-w32threads
+ --disable-pthreads
+ --enable-libopenjpeg
+ )
+else()
+ set(FFMPEG_EXTRA_FLAGS
+ ${FFMPEG_EXTRA_FLAGS}
+ --enable-static
+ --disable-shared
+ --enable-libopenjpeg)
+endif()
+
+if(APPLE)
+ set(FFMPEG_EXTRA_FLAGS
+ ${FFMPEG_EXTRA_FLAGS}
+ --target-os=darwin
+ )
+endif()
+
+ExternalProject_Add(external_ffmpeg
+ URL ${FFMPEG_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${FFMPEG_HASH}
+ PREFIX ${BUILD_DIR}/ffmpeg
+ CONFIGURE_COMMAND ${CONFIGURE_ENV_NO_PERL} &&
+ cd ${BUILD_DIR}/ffmpeg/src/external_ffmpeg/ &&
+ ${FFMPEG_ENV} ${CONFIGURE_COMMAND_NO_TARGET} ${FFMPEG_EXTRA_FLAGS}
+ --disable-lzma
+ --disable-avfilter
+ --disable-vdpau
+ --disable-bzlib
+ --disable-libgsm
+ --disable-libspeex
+ --enable-libvpx
+ --prefix=${LIBDIR}/ffmpeg
+ --enable-libschroedinger
+ --enable-libtheora
+ --enable-libvorbis
+ --enable-zlib
+ --enable-stripping
+ --enable-runtime-cpudetect
+ --disable-vaapi
+ --disable-nonfree
+ --enable-gpl
+ --disable-postproc
+ --disable-x11grab
+ --enable-libmp3lame
+ --disable-librtmp
+ --enable-libx264
+ --enable-libxvid
+ --disable-libopencore-amrnb
+ --disable-libopencore-amrwb
+ --disable-libdc1394
+ --disable-version3
+ --disable-debug
+ --enable-optimizations
+ --disable-sse
+ --disable-ssse3
+ --enable-ffplay
+ --disable-openssl
+ --disable-securetransport
+ --disable-indev=avfoundation
+ --disable-indev=qtkit
+ --disable-sdl
+ --disable-gnutls
+ --disable-vda
+ --disable-videotoolbox
+ --disable-libxcb
+ --disable-xlib
+ --disable-audiotoolbox
+ --disable-cuvid
+ --disable-nvenc
+ --disable-indev=jack
+ --disable-indev=alsa
+ --disable-outdev=alsa
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/ffmpeg/src/external_ffmpeg < ${PATCH_DIR}/ffmpeg.diff
+ BUILD_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/ffmpeg/src/external_ffmpeg/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/ffmpeg/src/external_ffmpeg/ && make install
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/ffmpeg ${DEFAULT_CMAKE_FLAGS}
+ INSTALL_DIR ${LIBDIR}/ffmpeg
+)
+
+if(MSVC)
+ set_target_properties(external_ffmpeg PROPERTIES FOLDER Mingw)
+endif(MSVC)
+
+add_dependencies(external_ffmpeg external_zlib external_faad external_openjpeg external_xvidcore external_x264 external_schroedinger external_vpx external_theora external_vorbis external_ogg external_lame)
+if(WIN32)
+ add_dependencies(external_ffmpeg external_zlib_mingw)
+endif()
diff --git a/build_files/build_environment/cmake/fftw.cmake b/build_files/build_environment/cmake/fftw.cmake
new file mode 100644
index 00000000000..e6e6165199c
--- /dev/null
+++ b/build_files/build_environment/cmake/fftw.cmake
@@ -0,0 +1,40 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(FFTW_EXTRA_ARGS)
+
+if(WIN32)
+ set(FFTW3_ENV set CFLAGS=-fno-stack-check -fno-stack-protector -mno-stack-arg-probe -fno-lto &&)
+ set(FFTW3_PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/fftw3/src/external_fftw3 < ${PATCH_DIR}/fftw3.diff)
+endif()
+
+ExternalProject_Add(external_fftw3
+ URL ${FFTW_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${FFTW_HASH}
+ PREFIX ${BUILD_DIR}/fftw3
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && ${FFTW3_ENV} cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && ${CONFIGURE_COMMAND} --enable-static --prefix=${mingw_LIBDIR}/fftw3
+ PATCH_COMMAND ${FFTW3_PATCH_COMMAND}
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && make install
+ INSTALL_DIR ${LIBDIR}/fftw3
+)
+
+if(MSVC)
+ set_target_properties(external_fftw3 PROPERTIES FOLDER Mingw)
+endif(MSVC)
diff --git a/build_files/build_environment/cmake/flac.cmake b/build_files/build_environment/cmake/flac.cmake
new file mode 100644
index 00000000000..74d222632d0
--- /dev/null
+++ b/build_files/build_environment/cmake/flac.cmake
@@ -0,0 +1,32 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_flac
+ URL ${FLAC_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${FLAC_HASH}
+ PREFIX ${BUILD_DIR}/flac
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/flac/src/external_flac/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/flac --disable-shared --enable-static
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/flac/src/external_flac/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/flac/src/external_flac/ && make install
+ INSTALL_DIR ${LIBDIR}/flac
+)
+
+if(MSVC)
+ set_target_properties(external_flac PROPERTIES FOLDER Mingw)
+endif(MSVC)
diff --git a/build_files/build_environment/cmake/flexbison.cmake b/build_files/build_environment/cmake/flexbison.cmake
new file mode 100644
index 00000000000..f2908e1ce2c
--- /dev/null
+++ b/build_files/build_environment/cmake/flexbison.cmake
@@ -0,0 +1,31 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(FLEXBISON_EXTRA_ARGS)
+
+ExternalProject_Add(external_flexbison
+ URL ${FLEXBISON_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${FLEXBISON_HASH}
+ PREFIX ${BUILD_DIR}/flexbison
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/flexbison ${DEFAULT_CMAKE_FLAGS} ${FLEXBISON_EXTRA_ARGS}
+ CONFIGURE_COMMAND echo .
+ BUILD_COMMAND echo .
+ INSTALL_COMMAND COMMAND ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/flexbison/src/external_flexbison/ ${LIBDIR}/flexbison/
+ INSTALL_DIR ${LIBDIR}/flexbison
+)
diff --git a/build_files/build_environment/cmake/freeglut.cmake b/build_files/build_environment/cmake/freeglut.cmake
new file mode 100644
index 00000000000..043b382e8fd
--- /dev/null
+++ b/build_files/build_environment/cmake/freeglut.cmake
@@ -0,0 +1,35 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ if(BUILD_MODE STREQUAL Release)
+ set(FREEGLUT_EXTRA_ARGS
+ -DFREEGLUT_BUILD_SHARED_LIBS=Off
+ -DFREEGLUT_BUILD_STATIC_LIBS=On
+ )
+
+ ExternalProject_Add(external_freeglut
+ URL ${FREEGLUT_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${FREEGLUT_HASH}
+ PREFIX ${BUILD_DIR}/freeglut
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/freeglut ${DEFAULT_C_FLAGS} ${DEFAULT_CXX_FLAGS} ${FREEGLUT_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/freeglut
+ )
+ endif()
+endif()
diff --git a/build_files/build_environment/cmake/freetype.cmake b/build_files/build_environment/cmake/freetype.cmake
new file mode 100644
index 00000000000..751b2b1f383
--- /dev/null
+++ b/build_files/build_environment/cmake/freetype.cmake
@@ -0,0 +1,28 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(FREETYPE_EXTRA_ARGS -DCMAKE_RELEASE_POSTFIX:STRING=2ST -DCMAKE_DEBUG_POSTFIX:STRING=2ST_d -DWITH_BZip2=OFF -DWITH_HarfBuzz=OFF)
+
+ExternalProject_Add(external_freetype
+ URL ${FREETYPE_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${FREETYPE_HASH}
+ PREFIX ${BUILD_DIR}/freetype
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/freetype ${DEFAULT_CMAKE_FLAGS} ${FREETYPE_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/freetype
+)
diff --git a/build_files/build_environment/cmake/glew.cmake b/build_files/build_environment/cmake/glew.cmake
new file mode 100644
index 00000000000..b5d9e4d3310
--- /dev/null
+++ b/build_files/build_environment/cmake/glew.cmake
@@ -0,0 +1,32 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(GLEW_EXTRA_ARGS
+ -DBUILD_UTILS=Off
+ -DBUILD_SHARED_LIBS=Off
+)
+
+ExternalProject_Add(external_glew
+ URL ${GLEW_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${GLEW_HASH}
+ PATCH_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/cmakelists_glew.txt ${BUILD_DIR}/glew/src/external_glew/CMakeLists.txt
+ PREFIX ${BUILD_DIR}/glew
+ CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=${LIBDIR}/glew ${DEFAULT_CMAKE_FLAGS} ${GLEW_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/glew
+)
diff --git a/build_files/build_environment/cmake/glfw.cmake b/build_files/build_environment/cmake/glfw.cmake
new file mode 100644
index 00000000000..ae80080525c
--- /dev/null
+++ b/build_files/build_environment/cmake/glfw.cmake
@@ -0,0 +1,28 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(GLFW_EXTRA_ARGS)
+
+ExternalProject_Add(external_glfw
+ URL ${GLFW_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${GLFW_HASH}
+ PREFIX ${BUILD_DIR}/glfw
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/glfw -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${GLFW_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/glfw
+)
diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake
new file mode 100644
index 00000000000..fbc9f8687f9
--- /dev/null
+++ b/build_files/build_environment/cmake/harvest.cmake
@@ -0,0 +1,292 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+########################################################################
+# Copy all generated files to the proper strucure as blender prefers
+########################################################################
+
+if(NOT DEFINED HARVEST_TARGET)
+ set(HARVEST_TARGET ${CMAKE_CURRENT_SOURCE_DIR}/Harvest)
+endif()
+message("HARVEST_TARGET = ${HARVEST_TARGET}")
+
+if(WIN32)
+
+if(BUILD_MODE STREQUAL Release)
+ add_custom_target(Harvest_Release_Results
+ # Zlib Rename the lib file and copy the include/bin folders
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/zlib/lib/zlibstatic.lib ${HARVEST_TARGET}/zlib/lib/libz_st.lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/zlib/include/ ${HARVEST_TARGET}/zlib/include/ &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/zlib/bin/ ${HARVEST_TARGET}/zlib/bin/ &&
+ # Boost copy lib + rename boost_1_60 to boost
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/boost/lib/ ${HARVEST_TARGET}/boost/lib/ &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/boost/include/boost-1_60/ ${HARVEST_TARGET}/boost/include/ &&
+ # jpeg rename libfile + copy include
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/jpg/lib/jpeg-static.lib ${HARVEST_TARGET}/jpeg/lib/libjpeg.lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/jpg/include/ ${HARVEST_TARGET}/jpeg/include/ &&
+ # FreeType, straight up copy
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freetype ${HARVEST_TARGET}/freetype &&
+ # pthreads, rename include dir
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/pthreads/inc/ ${HARVEST_TARGET}/pthreads/include/ &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/pthreads/lib/ ${HARVEST_TARGET}/pthreads/lib &&
+ # ffmpeg copy include+bin
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/ffmpeg/include ${HARVEST_TARGET}/ffmpeg/include &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/ffmpeg/bin ${HARVEST_TARGET}/ffmpeg/lib &&
+ # sdl merge bin/lib folder, copy include
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/sdl/include/sdl2 ${HARVEST_TARGET}/sdl/include &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/sdl/lib ${HARVEST_TARGET}/sdl/lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/sdl/bin ${HARVEST_TARGET}/sdl/lib &&
+ # openal
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/openal/lib/openal32.lib ${HARVEST_TARGET}/openal/lib/openal32.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/openal/bin/openal32.dll ${HARVEST_TARGET}/openal/lib/openal32.dll &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openal/include/ ${HARVEST_TARGET}/openal/include/ &&
+ # OpenImageIO
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/include ${HARVEST_TARGET}/OpenImageIO/include &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/lib ${HARVEST_TARGET}/OpenImageIO/lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/OpenImageIO/bin/idiff.exe ${HARVEST_TARGET}/OpenImageIO/bin/idiff.exe &&
+ # openEXR
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/ilmbase ${HARVEST_TARGET}/openexr &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openexr/lib ${HARVEST_TARGET}/openexr/lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openexr/include ${HARVEST_TARGET}/openexr/include &&
+ # png
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static.lib ${HARVEST_TARGET}/png/lib/libpng.lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ &&
+ # fftw3
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/lib/libfftw3.a ${HARVEST_TARGET}/fftw3/lib/libfftw.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/include/fftw3.h ${HARVEST_TARGET}/fftw3/include/fftw3.h &&
+ # freeglut-> opengl
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/freeglut/lib/freeglut_static.lib ${HARVEST_TARGET}/opengl/lib/freeglut_static.lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freeglut/include/ ${HARVEST_TARGET}/opengl/include/ &&
+ # glew-> opengl
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/glew/lib/libglew32.lib ${HARVEST_TARGET}/opengl/lib/glew.lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/glew/include/ ${HARVEST_TARGET}/opengl/include/ &&
+ # sndfile
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/lib/libsndfile.dll.a ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/bin/libsndfile-1.dll ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.dll &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/include/sndfile.h ${HARVEST_TARGET}/sndfile/include/sndfile.h &&
+ # tiff
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/tiff/lib/tiff.lib ${HARVEST_TARGET}/tiff/lib/libtiff.lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/tiff/include/ ${HARVEST_TARGET}/tiff/include/ &&
+ # iconv
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/iconv/lib/libiconv.a ${HARVEST_TARGET}/iconv/lib/iconv.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/iconv/include/iconv.h ${HARVEST_TARGET}/iconv/include/iconv.h &&
+ # opencolorIO
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenColorIO/ ${HARVEST_TARGET}/opencolorio &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/OpenColorIO/lib/OpenColorIO.dll ${HARVEST_TARGET}/opencolorio/bin/OpenColorIO.dll &&
+ # Osl
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/osl/ ${HARVEST_TARGET}/osl &&
+ # OpenVDB
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openVDB/ ${HARVEST_TARGET}/openVDB &&
+ # blosc
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/blosc/lib/libblosc.lib ${HARVEST_TARGET}/blosc/lib/libblosc.lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/blosc/include/ ${HARVEST_TARGET}/blosc/include/ &&
+ # tbb
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_static.lib ${HARVEST_TARGET}/tbb/lib/tbb.lib &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/tbb/include/ ${HARVEST_TARGET}/tbb/include/ &&
+ # llvm
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/llvm/ ${HARVEST_TARGET}/llvm/ &&
+ # opencollada
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencollada/ ${HARVEST_TARGET}/opencollada/ &&
+ # opensubdiv
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opensubdiv ${HARVEST_TARGET}/opensubdiv &&
+ # python
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/python/ ${HARVEST_TARGET}/python/ &&
+ # alembic
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/alembic ${HARVEST_TARGET}/alembic &&
+ # hdf5
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/hdf5 ${HARVEST_TARGET}/hdf5 &&
+ # BlendThumb
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/BlendThumb64/bin/blendthumb.dll ${HARVEST_TARGET}/ThumbHandler/lib/BlendThumb64.dll &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/BlendThumb32/bin/blendthumb.dll ${HARVEST_TARGET}/ThumbHandler/lib/BlendThumb.dll &&
+ # python
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/python35.tar.gz ${HARVEST_TARGET}/Release/python35.tar.gz &&
+ # requests
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/requests ${HARVEST_TARGET}/Release/site-packages/requests &&
+ # numpy
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/python35_numpy${PYTHON_POSTFIX}_1.10.tar.gz ${HARVEST_TARGET}/Release/python35_numpy_1.10.tar.gz &&
+ # hidapi
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/hidapi/ ${HARVEST_TARGET}/hidapi/ &&
+ # webp, straight up copy
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/webp ${HARVEST_TARGET}/webp
+ DEPENDS
+)
+endif(BUILD_MODE STREQUAL Release)
+
+if(BUILD_MODE STREQUAL Debug)
+ add_custom_target(Harvest_Debug_Results
+ # OpenImageIO
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO_Util.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_Util_d.lib &&
+ # ilmbase+openexr
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/ilmbase/lib/Half.lib ${HARVEST_TARGET}/openexr/lib/Half_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/ilmbase/lib/Iex-2_2.lib ${HARVEST_TARGET}/openexr/lib/Iex-2_2_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/ilmbase/lib/IexMath-2_2.lib ${HARVEST_TARGET}/openexr/lib/IexMath-2_2_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/ilmbase/lib/IlmThread-2_2.lib ${HARVEST_TARGET}/openexr/lib/IlmThread-2_2_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/ilmbase/lib/Imath-2_2.lib ${HARVEST_TARGET}/openexr/lib/Imath-2_2_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/openexr/lib/IlmImf-2_2.lib ${HARVEST_TARGET}/openexr/lib/IlmImf-2_2_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/openexr/lib/IlmImfUtil-2_2.lib ${HARVEST_TARGET}/openexr/lib/IlmImfUtil-2_2_d.lib &&
+ # opencollada
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/buffer.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/buffer_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/ftoa.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/ftoa_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/GeneratedSaxParser.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/GeneratedSaxParser_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/MathMLSolver.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/MathMLSolver_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADABaseUtils.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADABaseUtils_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAFramework.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAFramework_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/pcre.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/pcre_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/UTF.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/UTF_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/xml.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/xml_d.lib &&
+ # blosc
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/blosc/lib/libblosc_d.lib ${HARVEST_TARGET}/blosc/lib/libblosc_d.lib &&
+ # boost
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/boost/lib/ ${HARVEST_TARGET}/boost/lib/ &&
+ # llvm
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/llvm/lib/ ${HARVEST_TARGET}/llvm/debug/lib/ &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/llvm/bin/ ${HARVEST_TARGET}/llvm/debug/bin/ &&
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/llvm/include/ ${HARVEST_TARGET}/llvm/debug/include/ &&
+ # osl
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslcomp.lib ${HARVEST_TARGET}/osl/lib/oslcomp_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslexec.lib ${HARVEST_TARGET}/osl/lib/oslexec_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslquery.lib ${HARVEST_TARGET}/osl/lib/oslquery_d.lib &&
+ # opensubdiv
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opensubdiv/lib/osdCPU.lib ${HARVEST_TARGET}/opensubdiv/lib/osdCPU_d.lib &&
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/opensubdiv/lib/osdGPU.lib ${HARVEST_TARGET}/opensubdiv/lib/osdGPU_d.lib &&
+ # tbb
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_static.lib ${HARVEST_TARGET}/tbb/lib/tbb_debug.lib &&
+ # openvdb
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/openvdb/lib/openvdb.lib ${HARVEST_TARGET}/openvdb/lib/openvdb_d.lib &&
+ # python
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/python/ ${HARVEST_TARGET}/python/ &&
+ # alembic
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/alembic/lib/alembic.lib ${HARVEST_TARGET}/alembic/lib/alembic_d.lib &&
+ # hdf5
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/hdf5/lib ${HARVEST_TARGET}/hdf5/lib &&
+ # numpy
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/python35_numpy_1.10d.tar.gz ${HARVEST_TARGET}/Release/python35_numpy_1.10d.tar.gz &&
+ # python
+ ${CMAKE_COMMAND} -E copy ${LIBDIR}/python35_d.tar.gz ${HARVEST_TARGET}/Release/python35_d.tar.gz
+ DEPENDS Package_Python
+)
+endif(BUILD_MODE STREQUAL Debug)
+
+else(WIN32)
+
+function(harvest from to)
+ set(pattern "")
+ foreach(f ${ARGN})
+ set(pattern ${f})
+ endforeach()
+
+ if(pattern STREQUAL "")
+ get_filename_component(dirpath ${to} DIRECTORY)
+ get_filename_component(filename ${to} NAME)
+ install(
+ FILES ${LIBDIR}/${from}
+ DESTINATION ${HARVEST_TARGET}/${dirpath}
+ RENAME ${filename})
+ else()
+ install(
+ DIRECTORY ${LIBDIR}/${from}/
+ DESTINATION ${HARVEST_TARGET}/${to}
+ USE_SOURCE_PERMISSIONS
+ FILES_MATCHING PATTERN ${pattern}
+ PATTERN "pkgconfig" EXCLUDE
+ PATTERN "cmake" EXCLUDE
+ PATTERN "clang" EXCLUDE
+ PATTERN "__pycache__" EXCLUDE
+ PATTERN "tests" EXCLUDE)
+ endif()
+endfunction()
+
+harvest(alembic/include alembic/include "*.h")
+harvest(alembic/lib/libAlembic.a alembic/lib/libAlembic.a)
+harvest(alembic/bin alembic/bin "*")
+harvest(blosc/lib openvdb/lib "*.a")
+harvest(boost/include boost/include "*")
+harvest(boost/lib boost/lib "*.a")
+harvest(ffmpeg/include ffmpeg/include "*.h")
+harvest(ffmpeg/lib ffmpeg/lib "*.a")
+harvest(fftw3/include fftw3/include "*.h")
+harvest(fftw3/lib fftw3/lib "*.a")
+harvest(flac/lib sndfile/lib "libFLAC.a")
+harvest(freetype/include freetype/include "*.h")
+harvest(freetype/lib/libfreetype2ST.a freetype/lib/libfreetype.a)
+harvest(glew/include glew/include "*.h")
+harvest(glew/lib glew/lib "*.a")
+harvest(ilmbase openexr "*")
+harvest(ilmbase/include openexr/include "*.h")
+harvest(jemalloc/include jemalloc/include "*.h")
+harvest(jemalloc/lib jemalloc/lib "*.a")
+harvest(jpg/include jpeg/include "*.h")
+harvest(jpg/lib jpeg/lib "libjpeg.a")
+harvest(lame/lib ffmpeg/lib "*.a")
+harvest(llvm/bin llvm/bin "llvm-config")
+harvest(llvm/lib llvm/lib "libLLVM*.a")
+harvest(ogg/lib ffmpeg/lib "*.a")
+harvest(openal/include openal/include "*.h")
+if(UNIX AND NOT APPLE)
+ harvest(openal/lib openal/lib "*.a")
+endif()
+harvest(opencollada/include/opencollada opencollada/include "*.h")
+harvest(opencollada/lib/opencollada opencollada/lib "*.a")
+harvest(opencolorio/include opencolorio/include "*.h")
+harvest(opencolorio/lib opencolorio/lib "*.a")
+harvest(openexr/include openexr/include "*.h")
+harvest(openexr/lib openexr/lib "*.a")
+harvest(openimageio/bin openimageio/bin "idiff")
+harvest(openimageio/bin openimageio/bin "maketx")
+harvest(openimageio/bin openimageio/bin "oiiotool")
+harvest(openimageio/include openimageio/include "*")
+harvest(openimageio/lib openimageio/lib "*.a")
+harvest(openjpeg/include/openjpeg-1.5 openjpeg/include "*.h")
+harvest(openjpeg/lib openjpeg/lib "*.a")
+harvest(opensubdiv/include opensubdiv/include "*.h")
+harvest(opensubdiv/lib opensubdiv/lib "*.a")
+harvest(openvdb/include/openvdb/openvdb openvdb/include/openvdb "*.h")
+harvest(openvdb/lib openvdb/lib "*.a")
+harvest(orc/lib/liborc-0.4.a ffmpeg/lib/liborc.a)
+harvest(osl/bin osl/bin "oslc")
+harvest(osl/include osl/include "*.h")
+harvest(osl/lib osl/lib "*.a")
+harvest(osl/shaders osl/shaders "*.h")
+harvest(png/include png/include "*.h")
+harvest(png/lib png/lib "*.a")
+harvest(python/bin python/bin "python${PYTHON_SHORT_VERSION}m")
+harvest(python/include python/include "*h")
+harvest(python/lib python/lib "*")
+harvest(schroedinger/lib/libschroedinger-1.0.a ffmpeg/lib/libschroedinger.a)
+harvest(sdl/include/SDL2 sdl/include "*.h")
+harvest(sdl/lib sdl/lib "libSDL2.a")
+harvest(sndfile/include sndfile/include "*.h")
+harvest(sndfile/lib sndfile/lib "*.a")
+harvest(spnav/include spnav/include "*.h")
+harvest(spnav/lib spnav/lib "*.a")
+harvest(tbb/include tbb/include "*.h")
+harvest(tbb/lib/libtbb_static.a tbb/lib/libtbb.a)
+harvest(theora/lib ffmpeg/lib "*.a")
+harvest(tiff/include tiff/include "*.h")
+harvest(tiff/lib tiff/lib "*.a")
+harvest(vorbis/lib ffmpeg/lib "*.a")
+harvest(vpx/lib ffmpeg/lib "*.a")
+harvest(webp/lib ffmpeg/lib "*.a")
+harvest(x264/lib ffmpeg/lib "*.a")
+harvest(xml2/lib opencollada/lib "*.a")
+harvest(xvidcore/lib ffmpeg/lib "*.a")
+
+endif(WIN32)
diff --git a/build_files/build_environment/cmake/hdf5.cmake b/build_files/build_environment/cmake/hdf5.cmake
new file mode 100644
index 00000000000..09d40d0605f
--- /dev/null
+++ b/build_files/build_environment/cmake/hdf5.cmake
@@ -0,0 +1,42 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(HDF5_EXTRA_ARGS
+ -DHDF5_ENABLE_THREADSAFE=Off
+ -DHDF5_BUILD_CPP_LIB=Off
+ -DBUILD_TESTING=Off
+ -DHDF5_BUILD_TOOLS=Off
+ -DHDF5_BUILD_EXAMPLES=Off
+ -DHDF5_BUILD_HL_LIB=On
+ -DBUILD_STATIC_CRT_LIBS=On
+ -DBUILD_SHARED_LIBS=On
+)
+
+if(WIN32)
+ set(HDF5_PATCH ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/hdf5/src/external_hdf5 < ${PATCH_DIR}/hdf5.diff)
+endif()
+
+ExternalProject_Add(external_hdf5
+ URL ${HDF5_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${HDF5_HASH}
+ PREFIX ${BUILD_DIR}/hdf5
+ PATCH_COMMAND ${HDF5_PATCH}
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/hdf5 ${HDF5_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/hdf5
+)
diff --git a/build_files/build_environment/cmake/hidapi.cmake b/build_files/build_environment/cmake/hidapi.cmake
new file mode 100644
index 00000000000..cfa4cc53d2d
--- /dev/null
+++ b/build_files/build_environment/cmake/hidapi.cmake
@@ -0,0 +1,29 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(HIDAPI_EXTRA_ARGS)
+
+ExternalProject_Add(external_hidapi
+ URL ${HIDAPI_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${HIDAPI_HASH}
+ PREFIX ${BUILD_DIR}/hidapi
+ PATCH_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/cmakelists_hidapi.txt ${BUILD_DIR}/hidapi/src/external_hidapi/cmakelists.txt && ${PATCH_CMD} -p 0 -d ${BUILD_DIR}/hidapi/src/external_hidapi < ${PATCH_DIR}/hidapi.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/hidapi -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${HIDAPI_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/hidapi
+)
diff --git a/build_files/build_environment/cmake/iconv.cmake b/build_files/build_environment/cmake/iconv.cmake
new file mode 100644
index 00000000000..cd6cf9547df
--- /dev/null
+++ b/build_files/build_environment/cmake/iconv.cmake
@@ -0,0 +1,34 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(ICONV_EXTRA_ARGS)
+
+ExternalProject_Add(external_iconv
+ URL ${ICONV_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${ICONV_HASH}
+ PREFIX ${BUILD_DIR}/iconv
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/iconv/src/external_iconv/ && ${CONFIGURE_COMMAND} --enable-static --prefix=${mingw_LIBDIR}/iconv
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/iconv/src/external_iconv/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/iconv/src/external_iconv/ && make install
+ INSTALL_DIR ${LIBDIR}/iconv
+)
+
+if(MSVC)
+ set_target_properties(external_iconv PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/ilmbase.cmake b/build_files/build_environment/cmake/ilmbase.cmake
new file mode 100644
index 00000000000..0639848346f
--- /dev/null
+++ b/build_files/build_environment/cmake/ilmbase.cmake
@@ -0,0 +1,35 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ set(ILMBASE_CMAKE_CXX_STANDARD_LIBRARIES "kernel32${LIBEXT} user32${LIBEXT} gdi32${LIBEXT} winspool${LIBEXT} shell32${LIBEXT} ole32${LIBEXT} oleaut32${LIBEXT} uuid${LIBEXT} comdlg32${LIBEXT} advapi32${LIBEXT} psapi${LIBEXT}")
+endif()
+
+set(ILMBASE_EXTRA_ARGS
+ -DBUILD_SHARED_LIBS=OFF
+ -DCMAKE_CXX_STANDARD_LIBRARIES=${ILMBASE_CMAKE_CXX_STANDARD_LIBRARIES}
+)
+
+ExternalProject_Add(external_ilmbase
+ URL ${ILMBASE_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${ILMBASE_HASH}
+ PREFIX ${BUILD_DIR}/ilmbase
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/ilmbase ${DEFAULT_CMAKE_FLAGS} ${ILMBASE_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/openexr
+)
diff --git a/build_files/build_environment/cmake/jemalloc.cmake b/build_files/build_environment/cmake/jemalloc.cmake
new file mode 100644
index 00000000000..c39ba448917
--- /dev/null
+++ b/build_files/build_environment/cmake/jemalloc.cmake
@@ -0,0 +1,28 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_jemalloc
+ URL ${JEMALLOC_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${JEMALLOC_HASH}
+ PREFIX ${BUILD_DIR}/jemalloc
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/jemalloc/src/external_jemalloc/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/jemalloc --disable-shared --enable-static --with-pic
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/jemalloc/src/external_jemalloc/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/jemalloc/src/external_jemalloc/ && make install
+ INSTALL_DIR ${LIBDIR}/jemalloc
+)
diff --git a/build_files/build_environment/cmake/jpeg.cmake b/build_files/build_environment/cmake/jpeg.cmake
new file mode 100644
index 00000000000..1f2b04387f0
--- /dev/null
+++ b/build_files/build_environment/cmake/jpeg.cmake
@@ -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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ # cmake for windows
+ set(JPEG_EXTRA_ARGS -DWITH_JPEG8=ON -DCMAKE_DEBUG_POSTFIX=d)
+
+ ExternalProject_Add(external_jpeg
+ URL ${JPEG_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${JPEG_HASH}
+ PREFIX ${BUILD_DIR}/jpg
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/jpg ${DEFAULT_CMAKE_FLAGS} ${JPEG_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/jpg
+ )
+
+ if(BUILD_MODE STREQUAL Debug)
+ ExternalProject_Add_Step(external_jpeg after_install
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/jpg/lib/jpegd${LIBEXT} ${LIBDIR}/jpg/lib/jpeg${LIBEXT}
+ DEPENDEES install
+ )
+ endif()
+
+ if(BUILD_MODE STREQUAL Release)
+ set(JPEG_LIBRARY jpeg-static${LIBEXT})
+ else()
+ set(JPEG_LIBRARY jpeg-staticd${LIBEXT})
+ endif()
+else(WIN32)
+ # autoconf for unix
+ if(APPLE)
+ set(JPEG_EXTRA_ARGS --host x86_64-apple-darwin --with-jpeg8)
+ else()
+ set(JPEG_EXTRA_ARGS --with-jpeg8)
+ endif()
+
+ ExternalProject_Add(external_jpeg
+ URL ${JPEG_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${JPEG_HASH}
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && autoreconf -fiv && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/jpg NASM=yasm ${JPEG_EXTRA_ARGS}
+ BUILD_IN_SOURCE 1
+ BUILD_COMMAND ${CONFIGURE_ENV} && make install
+ PREFIX ${BUILD_DIR}/jpg
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/jpg ${DEFAULT_CMAKE_FLAGS} ${JPEG_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/jpg
+ )
+
+ set(JPEG_LIBRARY libjpeg${LIBEXT})
+endif(WIN32)
diff --git a/build_files/build_environment/cmake/lame.cmake b/build_files/build_environment/cmake/lame.cmake
new file mode 100644
index 00000000000..a489b2302ce
--- /dev/null
+++ b/build_files/build_environment/cmake/lame.cmake
@@ -0,0 +1,47 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(LAME_EXTRA_ARGS)
+if(MSVC)
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
+ set(LAME_EXTRA_ARGS CFLAGS=-msse)
+ endif()
+endif()
+
+ExternalProject_Add(external_lame
+ URL ${LAME_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${LAME_HASH}
+ PREFIX ${BUILD_DIR}/lame
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/lame/src/external_lame/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/lame --disable-shared --enable-static ${LAME_EXTRA_ARGS}
+ --enable-export=full
+ --with-fileio=sndfile
+ --without-vorbis
+ --with-pic
+ --disable-mp3x
+ --disable-mp3rtp
+ --disable-gtktest
+ --enable-export=full
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/lame/src/external_lame/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/lame/src/external_lame/ && make install
+ INSTALL_DIR ${LIBDIR}/lame
+)
+
+if(MSVC)
+ set_target_properties(external_lame PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/lapack.cmake b/build_files/build_environment/cmake/lapack.cmake
new file mode 100644
index 00000000000..3110503db52
--- /dev/null
+++ b/build_files/build_environment/cmake/lapack.cmake
@@ -0,0 +1,43 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(LAPACK_EXTRA_ARGS)
+
+if(WIN32)
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+ set(LAPACK_EXTRA_ARGS -G "MSYS Makefiles" -DCMAKE_Fortran_COMPILER=${DOWNLOAD_DIR}/mingw/mingw64/bin/gfortran.exe)
+ else()
+ set(LAPACK_EXTRA_ARGS -G "MSYS Makefiles" -DCMAKE_Fortran_COMPILER=${DOWNLOAD_DIR}/mingw/mingw32/bin/gfortran.exe)
+ endif()
+endif()
+
+ExternalProject_Add(external_lapack
+ URL ${LAPACK_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${LAPACK_HASH}
+ PREFIX ${BUILD_DIR}/lapack
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/lapack/src/external_lapack/ && ${CMAKE_COMMAND} ${LAPACK_EXTRA_ARGS} -DBUILD_TESTING=Off -DCMAKE_INSTALL_PREFIX=${LIBDIR}/lapack .
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/lapack/src/external_lapack/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/lapack/src/external_lapack/ && make install
+
+ INSTALL_DIR ${LIBDIR}/lapack
+)
+
+if(MSVC)
+ set_target_properties(external_lapack PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/llvm.cmake b/build_files/build_environment/cmake/llvm.cmake
new file mode 100644
index 00000000000..b9afa4d1b7b
--- /dev/null
+++ b/build_files/build_environment/cmake/llvm.cmake
@@ -0,0 +1,44 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(LLVM_EXTRA_ARGS
+ -DLLVM_USE_CRT_RELEASE=MT
+ -DLLVM_USE_CRT_DEBUG=MTd
+ -DLLVM_INCLUDE_TESTS=OFF
+ -DLLVM_TARGETS_TO_BUILD=X86
+ -DLLVM_INCLUDE_EXAMPLES=OFF
+ -DLLVM_ENABLE_TERMINFO=OFF
+)
+
+if(WIN32)
+ set(LLVM_GENERATOR "NMake Makefiles")
+else()
+ set(LLVM_GENERATOR "Unix Makefiles")
+endif()
+
+# short project name due to long filename issues on windows
+ExternalProject_Add(ll
+ URL ${LLVM_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${LLVM_HASH}
+ CMAKE_GENERATOR ${LLVM_GENERATOR}
+ PREFIX ${BUILD_DIR}/ll
+ PATCH_COMMAND ${PATCH_CMD} -p 0 -d ${BUILD_DIR}/ll/src/ll < ${PATCH_DIR}/llvm-alloca-fix.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/llvm ${DEFAULT_CMAKE_FLAGS} ${LLVM_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/llvm
+)
diff --git a/build_files/build_environment/cmake/mingw.cmake b/build_files/build_environment/cmake/mingw.cmake
new file mode 100644
index 00000000000..d8b87d8bd4e
--- /dev/null
+++ b/build_files/build_environment/cmake/mingw.cmake
@@ -0,0 +1,40 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(MSVC)
+ if(BUILD_MODE STREQUAL Release)
+ set(NUMPY_POSTFIX)
+ message("Python_binary = ${PYTHON_BINARY}")
+ message("Python_post = ${PYTHON_POSTFIX}")
+
+ ExternalProject_Add(external_numpy
+ URL ${NUMPY_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${NUMPY_HASH}
+ PREFIX ${BUILD_DIR}/numpy
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/numpy/src/external_numpy < ${PATCH_DIR}/numpy.diff
+ CONFIGURE_COMMAND ""
+ LOG_BUILD 1
+ BUILD_COMMAND ${PYTHON_BINARY} ${BUILD_DIR}/numpy/src/external_numpy/setup.py build
+ INSTALL_COMMAND ${CMAKE_COMMAND} -E chdir "${BUILD_DIR}/numpy/src/external_numpy/build/lib.${PYTHON_ARCH2}-3.5"
+ ${CMAKE_COMMAND} -E tar "cfvz" "${LIBDIR}/python35_numpy${PYTHON_POSTFIX}_1.11.tar.gz" "."
+ )
+
+ add_dependencies(external_numpy Make_Python_Environment)
+ endif()
+endif()
diff --git a/build_files/build_environment/cmake/numpy.cmake b/build_files/build_environment/cmake/numpy.cmake
new file mode 100644
index 00000000000..b1bf1691a28
--- /dev/null
+++ b/build_files/build_environment/cmake/numpy.cmake
@@ -0,0 +1,55 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(MSVC)
+ if(BUILD_MODE STREQUAL Debug)
+ set(NUMPY_DIR_POSTFIX -pydebug)
+ set(NUMPY_ARCHIVE_POSTFIX d)
+ set(NUMPY_BUILD_OPTION --debug)
+ else()
+ set(NUMPY_DIR_POSTFIX)
+ set(NUMPY_ARCHIVE_POSTFIX)
+ set(NUMPY_BUILD_OPTION)
+ endif(BUILD_MODE STREQUAL Debug)
+endif()
+
+set(NUMPY_POSTFIX)
+
+if(WIN32)
+ set(NUMPY_INSTALL
+ ${CMAKE_COMMAND} -E copy_directory "${BUILD_DIR}/python/src/external_python/run/lib/site-packages/numpy/core/include/numpy" "${LIBDIR}/python/include/python3.5/numpy" &&
+ ${CMAKE_COMMAND} -E chdir "${BUILD_DIR}/numpy/src/external_numpy/build/lib.${PYTHON_ARCH2}-3.5${NUMPY_DIR_POSTFIX}"
+ ${CMAKE_COMMAND} -E tar "cfvz" "${LIBDIR}/python35_numpy_${NUMPY_SHORT_VERSION}${NUMPY_ARCHIVE_POSTFIX}.tar.gz" "."
+ )
+else()
+ set(NUMPY_INSTALL echo .)
+endif()
+
+ExternalProject_Add(external_numpy
+ URL ${NUMPY_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${NUMPY_HASH}
+ PREFIX ${BUILD_DIR}/numpy
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/numpy/src/external_numpy < ${PATCH_DIR}/numpy.diff
+ CONFIGURE_COMMAND ""
+ LOG_BUILD 1
+ BUILD_COMMAND ${PYTHON_BINARY} ${BUILD_DIR}/numpy/src/external_numpy/setup.py build ${NUMPY_BUILD_OPTION} install
+ INSTALL_COMMAND ${NUMPY_INSTALL}
+)
+
+add_dependencies(external_numpy Make_Python_Environment)
diff --git a/build_files/build_environment/cmake/ogg.cmake b/build_files/build_environment/cmake/ogg.cmake
new file mode 100644
index 00000000000..1f69cee0996
--- /dev/null
+++ b/build_files/build_environment/cmake/ogg.cmake
@@ -0,0 +1,32 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_ogg
+ URL ${OGG_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${OGG_HASH}
+ PREFIX ${BUILD_DIR}/ogg
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/ogg/src/external_ogg/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/ogg --disable-shared --enable-static
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/ogg/src/external_ogg/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/ogg/src/external_ogg/ && make install
+ INSTALL_DIR ${LIBDIR}/ogg
+)
+
+if(MSVC)
+ set_target_properties(external_ogg PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/openal.cmake b/build_files/build_environment/cmake/openal.cmake
new file mode 100644
index 00000000000..d63c4443ca0
--- /dev/null
+++ b/build_files/build_environment/cmake/openal.cmake
@@ -0,0 +1,42 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(BUILD_MODE STREQUAL Release)
+ set(OPENAL_EXTRA_ARGS
+ -DALSOFT_UTILS=Off
+ -DALSOFT_NO_CONFIG_UTIL=On
+ -DALSOFT_EXAMPLES=Off
+ -DALSOFT_TESTS=Off
+ -DALSOFT_CONFIG=Off
+ -DALSOFT_HRTF_DEFS=Off
+ -DALSOFT_INSTALL=On
+ )
+
+ if(UNIX)
+ set(OPENAL_EXTRA_ARGS ${OPENAL_EXTRA_ARGS} -DLIBTYPE=STATIC)
+ endif()
+
+ ExternalProject_Add(external_openal
+ URL ${OPENAL_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${OPENAL_HASH}
+ PREFIX ${BUILD_DIR}/openal
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openal ${DEFAULT_CMAKE_FLAGS} ${OPENAL_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/openal
+ )
+endif()
diff --git a/build_files/build_environment/cmake/opencollada.cmake b/build_files/build_environment/cmake/opencollada.cmake
new file mode 100644
index 00000000000..9b2a2d9dc4d
--- /dev/null
+++ b/build_files/build_environment/cmake/opencollada.cmake
@@ -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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(UNIX AND NOT APPLE)
+ set(OPENCOLLADA_EXTRA_ARGS
+ -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2
+ -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2.a)
+endif()
+
+ExternalProject_Add(external_opencollada
+ URL ${OPENCOLLADA_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${OPENCOLLADA_HASH}
+ PREFIX ${BUILD_DIR}/opencollada
+ PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/opencollada/src/external_opencollada < ${PATCH_DIR}/opencollada.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opencollada ${DEFAULT_CMAKE_FLAGS} ${OPENCOLLADA_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/opencollada
+)
+
+if(UNIX AND NOT APPLE)
+ add_dependencies(external_opencollada external_xml2)
+endif()
diff --git a/build_files/build_environment/cmake/opencolorio.cmake b/build_files/build_environment/cmake/opencolorio.cmake
new file mode 100644
index 00000000000..14fb62af672
--- /dev/null
+++ b/build_files/build_environment/cmake/opencolorio.cmake
@@ -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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(OPENCOLORIO_EXTRA_ARGS
+ -DBoost_COMPILER:STRING=${BOOST_COMPILER_STRING}
+ -DBoost_USE_MULTITHREADED=ON
+ -DBoost_USE_STATIC_LIBS=ON
+ -DBoost_USE_STATIC_RUNTIME=ON
+ -DBOOST_ROOT=${LIBDIR}/boost
+ -DBOOST_INCLUDEDIR=${LIBDIR}/boost/include/boost_1_60/boost
+ -DBoost_NO_SYSTEM_PATHS=ON
+ -DBoost_DEBUG=ON
+ -DBoost_MAJOR_VERSION=1
+ -DBoost_MINOR_VERSION=60
+ -DOCIO_BUILD_APPS=OFF
+ -DOCIO_BUILD_PYGLUE=OFF
+ -DOCIO_BUILD_NUKE=OFF
+)
+
+if(WIN32)
+ set(OPENCOLORIO_EXTRA_ARGS
+ ${OPENCOLORIO_EXTRA_ARGS}
+ -DOCIO_USE_BOOST_PTR=ON
+ -DOCIO_BUILD_STATIC=OFF
+ -DOCIO_BUILD_SHARED=ON
+ )
+else()
+ set(OPENCOLORIO_EXTRA_ARGS
+ ${OPENCOLORIO_EXTRA_ARGS}
+ -DOCIO_USE_BOOST_PTR=OFF
+ -DOCIO_BUILD_STATIC=ON
+ -DOCIO_BUILD_SHARED=OFF
+ )
+endif()
+
+ExternalProject_Add(external_opencolorio
+ URL ${OPENCOLORIO_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${OPENCOLORIO_HASH}
+ PREFIX ${BUILD_DIR}/opencolorio
+ PATCH_COMMAND ${PATCH_CMD} -p 0 -N -d ${BUILD_DIR}/opencolorio/src/external_opencolorio < ${PATCH_DIR}/opencolorio.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opencolorio ${DEFAULT_CMAKE_FLAGS} ${OPENCOLORIO_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/opencolorio
+)
+
+if(NOT WIN32)
+ add_custom_command(
+ OUTPUT ${LIBDIR}/opencolorio/lib/libtinyxml.a
+ COMMAND cp ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/libtinyxml.a ${LIBDIR}/opencolorio/lib/libtinyxml.a
+ COMMAND cp ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/libyaml-cpp.a ${LIBDIR}/opencolorio/lib/libyaml-cpp.a
+ )
+ add_custom_target(external_opencolorio_extra ALL DEPENDS external_opencolorio ${LIBDIR}/opencolorio/lib/libtinyxml.a)
+endif()
+
+add_dependencies(external_opencolorio external_boost)
diff --git a/build_files/build_environment/cmake/openexr.cmake b/build_files/build_environment/cmake/openexr.cmake
new file mode 100644
index 00000000000..53a1bc4c146
--- /dev/null
+++ b/build_files/build_environment/cmake/openexr.cmake
@@ -0,0 +1,41 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ set(OPENEXR_CMAKE_CXX_STANDARD_LIBRARIES "kernel32${LIBEXT} user32${LIBEXT} gdi32${LIBEXT} winspool${LIBEXT} shell32${LIBEXT} ole32${LIBEXT} oleaut32${LIBEXT} uuid${LIBEXT} comdlg32${LIBEXT} advapi32${LIBEXT} psapi${LIBEXT}")
+endif()
+
+set(OPENEXR_EXTRA_ARGS
+ -DBUILD_SHARED_LIBS=OFF
+ -DCMAKE_CXX_STANDARD_LIBRARIES=${OPENEXR_CMAKE_CXX_STANDARD_LIBRARIES}
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include/
+ -DILMBASE_PACKAGE_PREFIX=${LIBDIR}/ilmbase
+)
+
+ExternalProject_Add(external_openexr
+ URL ${OPENEXR_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${OPENEXR_HASH}
+ PREFIX ${BUILD_DIR}/openexr
+ PATCH_COMMAND ${PATCH_CMD} -p 0 -d ${BUILD_DIR}/openexr/src/external_openexr < ${PATCH_DIR}/openexr.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openexr ${DEFAULT_CMAKE_FLAGS} ${OPENEXR_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/openexr
+)
+
+add_dependencies(external_openexr external_zlib external_ilmbase)
diff --git a/build_files/build_environment/cmake/openimageio.cmake b/build_files/build_environment/cmake/openimageio.cmake
new file mode 100644
index 00000000000..f323161d5f2
--- /dev/null
+++ b/build_files/build_environment/cmake/openimageio.cmake
@@ -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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(BUILD_MODE STREQUAL Release)
+ set(OIIO_TOOLS ON)
+else()
+ set(OIIO_TOOLS OFF)
+endif()
+
+if(UNIX AND NOT APPLE)
+ # This causes linking to static pthread libraries which gives link errors.
+ # Since we manually specify library paths it should static link other libs.
+ set(OPENIMAGEIO_LINKSTATIC -DLINKSTATIC=OFF)
+else()
+ set(OPENIMAGEIO_LINKSTATIC -DLINKSTATIC=ON)
+endif()
+
+if(WIN32)
+ set(PNG_LIBNAME libpng16_static${LIBEXT})
+ set(OIIO_SIMD_FLAGS -DUSE_SIMD=sse2)
+else()
+ set(PNG_LIBNAME libpng${LIBEXT})
+ set(OIIO_SIMD_FLAGS)
+endif()
+
+set(OPENIMAGEIO_EXTRA_ARGS
+ -DBUILDSTATIC=ON
+ ${OPENIMAGEIO_LINKSTATIC}
+ -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/openexr/
+ -DOPENEXR_ILMIMF_LIBRARIES=${LIBDIR}/openexr/lib/IlmImf-2_2${LIBEXT}
+ -DBoost_COMPILER:STRING=${BOOST_COMPILER_STRING}
+ -DBoost_USE_MULTITHREADED=ON
+ -DBoost_USE_STATIC_LIBS=ON
+ -DBoost_USE_STATIC_RUNTIME=ON
+ -DBOOST_ROOT=${LIBDIR}/boost
+ -DBOOST_LIBRARYDIR=${LIBDIR}/boost/lib/
+ -DBoost_NO_SYSTEM_PATHS=ON
+ -OIIO_BUILD_CPP11=ON
+ -DUSE_OPENGL=OFF
+ -DUSE_TBB=OFF
+ -DUSE_FIELD3D=OFF
+ -DUSE_QT=OFF
+ -DUSE_PYTHON=OFF
+ -DUSE_GIF=OFF
+ -DUSE_OPENCV=OFF
+ -DUSE_OPENSSL=OFF
+ -DUSE_OPENJPEG=OFF
+ -DUSE_FFMPEG=OFF
+ -DUSE_PTEX=OFF
+ -DUSE_FREETYPE=OFF
+ -DUSE_LIBRAW=OFF
+ -DUSE_PYTHON=OFF
+ -DUSE_PYTHON3=OFF
+ -DUSE_OCIO=OFF
+ -DOIIO_BUILD_TOOLS=${OIIO_TOOLS}
+ -DOIIO_BUILD_TESTS=OFF
+ -DBUILD_TESTING=OFF
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include
+ -DPNG_LIBRARY=${LIBDIR}/png/lib/${PNG_LIBNAME}
+ -DPNG_PNG_INCLUDE_DIR=${LIBDIR}/png/include
+ -DTIFF_LIBRARY=${LIBDIR}/tiff/lib/${LIBPREFIX}tiff${LIBEXT}
+ -DTIFF_INCLUDE_DIR=${LIBDIR}/tiff/include
+ -DJPEG_LIBRARY=${LIBDIR}/jpg/lib/${JPEG_LIBRARY}
+ -DJPEG_INCLUDE_DIR=${LIBDIR}/jpg/include
+ -DOCIO_PATH=${LIBDIR}/opencolorio/
+ -DOpenEXR_USE_STATIC_LIBS=On
+ -DOPENEXR_HOME=${LIBDIR}/openexr/
+ -DILMBASE_INCLUDE_PATH=${LIBDIR}/ilmbase/
+ -DILMBASE_PACKAGE_PREFIX=${LIBDIR}/ilmbase/
+ -DILMBASE_INCLUDE_DIR=${LIBDIR}/ilmbase/include/
+ -DOPENEXR_HALF_LIBRARY=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Half${LIBEXT}
+ -DOPENEXR_IMATH_LIBRARY=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Imath-2_2${LIBEXT}
+ -DOPENEXR_ILMTHREAD_LIBRARY=${LIBDIR}/ilmbase/lib/${LIBPREFIX}IlmThread-2_2${LIBEXT}
+ -DOPENEXR_IEX_LIBRARY=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Iex-2_2${LIBEXT}
+ -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/
+ -DOPENEXR_ILMIMF_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf-2_2${LIBEXT}
+ -DSTOP_ON_WARNING=OFF
+ -DWEBP_INCLUDE_DIR=${LIBDIR}/webp/include
+ -DWEBP_LIBRARY=${LIBDIR}/webp/lib/${LIBPREFIX}webp${LIBEXT}
+ ${OIIO_SIMD_FLAGS}
+)
+
+ExternalProject_Add(external_openimageio
+ URL ${OPENIMAGEIO_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${OPENIMAGEIO_HASH}
+ PREFIX ${BUILD_DIR}/openimageio
+ PATCH_COMMAND ${PATCH_CMD} -p 0 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/src/include < ${PATCH_DIR}/openimageio_gdi.diff &&
+ ${PATCH_CMD} -p 0 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/openimageio_staticexr.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openimageio ${DEFAULT_CMAKE_FLAGS} ${OPENIMAGEIO_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/openimageio
+)
+
+add_dependencies(external_openimageio external_png external_zlib external_ilmbase external_openexr external_jpeg external_boost external_tiff external_webp external_opencolorio)
+if(NOT WIN32)
+ add_dependencies(external_openimageio external_opencolorio_extra)
+endif()
diff --git a/build_files/build_environment/cmake/openjpeg.cmake b/build_files/build_environment/cmake/openjpeg.cmake
new file mode 100644
index 00000000000..66f815034eb
--- /dev/null
+++ b/build_files/build_environment/cmake/openjpeg.cmake
@@ -0,0 +1,43 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+# Note the encoder/decoder may use png/tiff/lcms system libraries, but the
+# library itself does not depend on them, so should give no problems.
+
+set(OPENJPEG_EXTRA_ARGS -DBUILD_SHARED_LIBS=OFF)
+
+if(WIN32)
+ set(OPENJPEG_EXTRA_ARGS -G "MSYS Makefiles")
+else()
+ set(OPENJPEG_EXTRA_ARGS ${DEFAULT_CMAKE_FLAGS})
+endif()
+
+ExternalProject_Add(external_openjpeg
+ URL ${OPENJPEG_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${OPENJPEG_HASH}
+ PREFIX ${BUILD_DIR}/openjpeg
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/openjpeg/src/external_openjpeg-build && ${CMAKE_COMMAND} ${OPENJPEG_EXTRA_ARGS} -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openjpeg -DBUILD_SHARED_LIBS=Off -DBUILD_THIRDPARTY=OFF ${BUILD_DIR}/openjpeg/src/external_openjpeg
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/openjpeg/src/external_openjpeg-build/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/openjpeg/src/external_openjpeg-build/ && make install
+ INSTALL_DIR ${LIBDIR}/openjpeg
+)
+
+if(MSVC)
+ set_target_properties(external_openjpeg PROPERTIES FOLDER Mingw)
+endif(MSVC)
diff --git a/build_files/build_environment/cmake/opensubdiv.cmake b/build_files/build_environment/cmake/opensubdiv.cmake
new file mode 100644
index 00000000000..5a3a4d142fa
--- /dev/null
+++ b/build_files/build_environment/cmake/opensubdiv.cmake
@@ -0,0 +1,71 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(OPENSUBDIV_EXTRA_ARGS
+ -DNO_EXAMPLES=ON
+ -DNO_REGRESSION=ON
+ -DNO_PYTHON=ON
+ -DNO_MAYA=ON
+ -DNO_PTEX=ON
+ -DNO_DOC=ON
+ -DNO_CLEW=OFF
+ -DNO_OPENCL=OFF
+ -DNO_TUTORIALS=ON
+ -DGLEW_INCLUDE_DIR=${LIBDIR}/glew/include
+ -DGLEW_LIBRARY=${LIBDIR}/glew/lib/libGLEW${LIBEXT}
+ -DGLFW_INCLUDE_DIR=${LIBDIR}/glfw/include
+ -DGLFW_LIBRARIES=${LIBDIR}/glfw/lib/glfw3${LIBEXT}
+)
+
+if(WIN32)
+ #no cuda support for vc15 yet
+ if(msvc15)
+ set(OPENSUBDIV_CUDA ON)
+ else()
+ set(OPENSUBDIV_CUDA ON)
+ endif()
+
+ set(OPENSUBDIV_EXTRA_ARGS
+ ${OPENSUBDIV_EXTRA_ARGS}
+ -DNO_CUDA=${OPENSUBDIV_CUDA}
+ -DCLEW_INCLUDE_DIR=${LIBDIR}/clew/include/cl
+ -DCLEW_LIBRARY=${LIBDIR}/clew/lib/clew${LIBEXT}
+ -DCUEW_INCLUDE_DIR=${LIBDIR}/cuew/include
+ -DCUEW_LIBRARY=${LIBDIR}/cuew/lib/cuew${LIBEXT}
+ -DCMAKE_EXE_LINKER_FLAGS_RELEASE=libcmt.lib
+ )
+else()
+ set(OPENSUBDIV_EXTRA_ARGS
+ ${OPENSUBDIV_EXTRA_ARGS}
+ -DNO_CUDA=ON
+ -DCUEW_INCLUDE_DIR=${LIBDIR}/cuew/include
+ -DCLEW_LIBRARY=${LIBDIR}/clew/lib/static/${LIBPREFIX}clew${LIBEXT}
+ )
+endif()
+
+ExternalProject_Add(external_opensubdiv
+ URL ${OPENSUBDIV_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${OPENSUBDIV_Hash}
+ PREFIX ${BUILD_DIR}/opensubdiv
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/opensubdiv/src/external_opensubdiv < ${PATCH_DIR}/opensubdiv.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opensubdiv -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${OPENSUBDIV_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/opensubdiv
+)
+
+add_dependencies(external_opensubdiv external_glew external_glfw external_clew external_cuew)
diff --git a/build_files/build_environment/cmake/openvdb.cmake b/build_files/build_environment/cmake/openvdb.cmake
new file mode 100644
index 00000000000..a71598c1a3b
--- /dev/null
+++ b/build_files/build_environment/cmake/openvdb.cmake
@@ -0,0 +1,71 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(BUILD_MODE STREQUAL Debug)
+ set(BLOSC_POST _d)
+endif()
+
+set(OPENVDB_EXTRA_ARGS
+ -DILMBASE_HOME=${LIBDIR}/ilmbase/
+ -DILMBASE_CUSTOM=ON
+ -DILMBASE_CUSTOM_LIBRARIES=Half;Imath-2_2;IlmThread-2_2;Iex-2_2
+ -DILMBASE_INCLUDE_DIR=${LIBDIR}/ilmbase/include/
+ -DILMBASE_HALF_LIBRARIES=${LIBDIR}/ilmbase/lib/Half${LIBEXT}
+ -DILMBASE_IMATH_LIBRARIES=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Imath-2_2${LIBEXT}
+ -DILMBASE_ILMTHREAD_LIBRARIES=${LIBDIR}/ilmbase/lib/${LIBPREFIX}IlmThread-2_2${LIBEXT}
+ -DILMBASE_IEX_LIBRARIES=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Iex-2_2${LIBEXT}
+ -DOPENEXR_HOME=${LIBDIR}/openexr/
+ -DOPENEXR_USE_STATIC_LIBS=ON
+ -DOPENEXR_CUSTOM=ON
+ -DOPENEXR_CUSTOM_LIBRARY=IlmImf-2_2
+ -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/
+ -DOPENEXR_ILMIMF_LIBRARIES=${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf-2_2${LIBEXT}
+ -DTBB_ROOT_DIR=${LIBDIR}/tbb/
+ -DTBB_INCLUDE_DIRS=${LIBDIR}/tbb/include
+ -DTBB_LIBRARY=${LIBDIR}/tbb/lib/tbb_static${LIBEXT}
+ -DBoost_COMPILER:STRING=${BOOST_COMPILER_STRING}
+ -DBoost_USE_MULTITHREADED=ON
+ -DBoost_USE_STATIC_LIBS=ON
+ -DBoost_USE_STATIC_RUNTIME=ON
+ -DBOOST_ROOT=${LIBDIR}/boost
+ -DBoost_NO_SYSTEM_PATHS=ON
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include/
+ -DWITH_BLOSC=ON
+ -DBLOSC_INCLUDE_DIR=${LIBDIR}/blosc/include/
+ -DBLOSC_LIBRARY=${LIBDIR}/blosc/lib/libblosc${BLOSC_POST}${LIBEXT}
+)
+
+set(OPENVDB_EXTRA_ARGS ${OPENVDB_EXTRA_ARGS})
+
+# CMake script for OpenVDB based on https://raw.githubusercontent.com/diekev/openvdb-cmake/master/CMakeLists.txt
+# can't be in external_openvdb because of how the includes are setup.
+
+ExternalProject_Add(openvdb
+ URL ${OPENVDB_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${OPENVDB_HASH}
+ PREFIX ${BUILD_DIR}/openvdb
+ PATCH_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/cmakelists_openvdb.txt ${BUILD_DIR}/openvdb/src/openvdb/CMakeLists.txt &&
+ ${CMAKE_COMMAND} -E copy_directory ${PATCH_DIR}/cmake/ ${BUILD_DIR}/openvdb/src/openvdb/cmake/ &&
+ ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/openvdb/src/openvdb < ${PATCH_DIR}/openvdb_vc2013.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openvdb ${DEFAULT_CMAKE_FLAGS} ${OPENVDB_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/openvdb
+)
+
+add_dependencies(openvdb external_tbb external_boost external_ilmbase external_openexr external_zlib external_blosc)
diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake
new file mode 100644
index 00000000000..6dbf3f46b1a
--- /dev/null
+++ b/build_files/build_environment/cmake/options.cmake
@@ -0,0 +1,205 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ option(ENABLE_MINGW64 "Enable building of ffmpeg/iconv/libsndfile/lapack/fftw3 by installing mingw64" ON)
+endif()
+set(MAKE_THREADS 1 CACHE STRING "Number of threads to run make with")
+
+if(NOT BUILD_MODE)
+ set(BUILD_MODE "Release")
+ message(STATUS "Build type not specified: defaulting to a release build.")
+endif()
+Message("BuildMode = ${BUILD_MODE}")
+
+if(BUILD_MODE STREQUAL "Debug")
+ set(LIBDIR ${CMAKE_CURRENT_BINARY_DIR}/Debug)
+ELSE(BUILD_MODE STREQUAL "Debug")
+ set(LIBDIR ${CMAKE_CURRENT_BINARY_DIR}/Release)
+ENDIF(BUILD_MODE STREQUAL "Debug")
+
+option(DOWNLOAD_DIR "Path for downloaded files" ${CMAKE_CURRENT_SOURCE_DIR}/downloads)
+file(TO_CMAKE_PATH ${DOWNLOAD_DIR} DOWNLOAD_DIR)
+set(PATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}/patches)
+set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/build)
+
+message("LIBDIR = ${LIBDIR}")
+message("DOWNLOAD_DIR = ${DOWNLOAD_DIR}")
+message("PATCH_DIR = ${PATCH_DIR}")
+message("BUILD_DIR = ${BUILD_DIR}")
+
+if(WIN32)
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+ set(PATCH_CMD ${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/patch.exe)
+ else()
+ set(PATCH_CMD ${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/patch.exe)
+ endif()
+ set(LIBEXT ".lib")
+ set(LIBPREFIX "")
+
+ # For OIIO and OSL
+ set(COMMON_DEFINES /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS)
+
+ # TODO FIXME highly MSVC specific
+ if(WITH_OPTIMIZED_DEBUG)
+ set(BLENDER_CMAKE_C_FLAGS_DEBUG "/MTd /O2 /Ob2 /DNDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+ else()
+ set(BLENDER_CMAKE_C_FLAGS_DEBUG "/MTd /Zi /Ob0 /Od /RTC1 /D_DEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+ endif()
+ set(BLENDER_CMAKE_C_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+ set(BLENDER_CMAKE_C_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+ set(BLENDER_CMAKE_C_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+
+ if(WITH_OPTIMIZED_DEBUG)
+ set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/MTd /O2 /Ob2 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+ else()
+ set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /D PLATFORM_WINDOWS /MTd /Zi /Ob0 /Od /RTC1 /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+ endif()
+ set(BLENDER_CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+ set(BLENDER_CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+ set(BLENDER_CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
+
+ set(PLATFORM_FLAGS)
+ set(PLATFORM_CXX_FLAGS)
+ set(PLATFORM_CMAKE_FLAGS)
+
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+ set(MINGW_PATH ${DOWNLOAD_DIR}/mingw/mingw64)
+ set(MINGW_SHELL ming64sh.cmd)
+ set(PERL_SHELL ${DOWNLOAD_DIR}/perl/portableshell.bat)
+ set(MINGW_HOST x86_64-w64-mingw32)
+ else()
+ set(MINGW_PATH ${DOWNLOAD_DIR}/mingw/mingw32)
+ set(MINGW_SHELL ming32sh.cmd)
+ set(PERL_SHELL ${DOWNLOAD_DIR}/perl32/portableshell.bat)
+ set(MINGW_HOST i686-w64-mingw32)
+ endif()
+
+ set(CONFIGURE_ENV
+ cd ${MINGW_PATH} &&
+ call ${MINGW_SHELL} &&
+ call ${PERL_SHELL} &&
+ set path &&
+ set CFLAGS=-g &&
+ set LDFLAGS=-Wl,--as-needed -static-libgcc
+ )
+
+ set(CONFIGURE_ENV_NO_PERL
+ cd ${MINGW_PATH} &&
+ call ${MINGW_SHELL} &&
+ set path &&
+ set CFLAGS=-g &&
+ set LDFLAGS=-Wl,--as-needed -static-libgcc
+ )
+
+ set(CONFIGURE_COMMAND sh ./configure)
+ set(CONFIGURE_COMMAND_NO_TARGET ${CONFIGURE_COMMAND})
+else()
+ set(PATCH_CMD patch)
+ set(LIBEXT ".a")
+ set(LIBPREFIX "lib")
+
+ if(APPLE)
+ set(OSX_ARCHITECTURES x86_64)
+ set(OSX_DEPLOYMENT_TARGET 10.9)
+ set(OSX_SDK_VERSION 10.12)
+ set(OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${OSX_SDK_VERSION}.sdk)
+
+ set(PLATFORM_CFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET}")
+ set(PLATFORM_CXXFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET} -std=c++11 -stdlib=libc++")
+ set(PLATFORM_LDFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET}")
+ set(PLATFORM_BUILD_TARGET --build=x86_64-apple-darwin13.0.0) # OS X 10.9
+ set(PLATFORM_CMAKE_FLAGS
+ -DCMAKE_OSX_ARCHITECTURES:STRING=${OSX_ARCHITECTURES}
+ -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${OSX_DEPLOYMENT_TARGET}
+ -DCMAKE_OSX_SYSROOT:PATH=${OSX_SYSROOT}
+ )
+ else()
+ set(PLATFORM_CFLAGS "-fPIC")
+ set(PLATFORM_CXXFLAGS "-std=c++11 -fPIC")
+ set(PLATFORM_LDFLAGS)
+ set(PLATFORM_BUILD_TARGET)
+ set(PLATFORM_CMAKE_FLAGS)
+ endif()
+
+ if(WITH_OPTIMIZED_DEBUG)
+ set(BLENDER_CMAKE_C_FLAGS_DEBUG "-O2 -DNDEBUG")
+ else()
+ set(BLENDER_CMAKE_C_FLAGS_DEBUG "-g")
+ endif()
+ set(BLENDER_CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
+ set(BLENDER_CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
+ set(BLENDER_CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG")
+
+ if(WITH_OPTIMIZED_DEBUG)
+ set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "-O2 -DNDEBUG ${PLATFORM_CXXFLAGS}")
+ else()
+ set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "-g ${PLATFORM_CXXFLAGS}")
+ endif()
+
+ set(BLENDER_CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG ${PLATFORM_CXXFLAGS}")
+ set(BLENDER_CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG ${PLATFORM_CXXFLAGS}")
+ set(BLENDER_CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG ${PLATFORM_CXXFLAGS}")
+
+ set(CONFIGURE_ENV
+ export MACOSX_DEPLOYMENT_TARGET=${OSX_DEPLOYMENT_TARGET} &&
+ export CFLAGS=${PLATFORM_CFLAGS} &&
+ export CXXFLAGS=${PLATFORM_CXXFLAGS} &&
+ export LDFLAGS=${PLATFORM_LDFLAGS}
+ )
+ set(CONFIGURE_ENV_NO_PERL ${CONFIGURE_ENV})
+ set(CONFIGURE_COMMAND ./configure ${PLATFORM_BUILD_TARGET})
+ set(CONFIGURE_COMMAND_NO_TARGET ./configure)
+endif()
+
+set(DEFAULT_CMAKE_FLAGS
+ -DCMAKE_BUILD_TYPE=${BUILD_MODE}
+ -DCMAKE_C_FLAGS_DEBUG=${BLENDER_CMAKE_C_FLAGS_DEBUG}
+ -DCMAKE_C_FLAGS_MINSIZEREL=${BLENDER_CMAKE_C_FLAGS_MINSIZEREL}
+ -DCMAKE_C_FLAGS_RELEASE=${BLENDER_CMAKE_C_FLAGS_RELEASE}
+ -DCMAKE_C_FLAGS_RELWITHDEBINFO=${BLENDER_CMAKE_C_FLAGS_RELWITHDEBINFO}
+ -DCMAKE_CXX_FLAGS_DEBUG=${BLENDER_CMAKE_CXX_FLAGS_DEBUG}
+ -DCMAKE_CXX_FLAGS_MINSIZEREL=${BLENDER_CMAKE_CXX_FLAGS_MINSIZEREL}
+ -DCMAKE_CXX_FLAGS_RELEASE=${BLENDER_CMAKE_CXX_FLAGS_RELEASE}
+ -DCMAKE_CXX_FLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO}
+ ${PLATFORM_CMAKE_FLAGS}
+)
+
+if(WIN32)
+ #we need both flavors to build the thumbnail dlls
+ if(MSVC12)
+ set(GENERATOR_32 "Visual Studio 12 2013")
+ set(GENERATOR_64 "Visual Studio 12 2013 Win64")
+ elseif(MSVC14)
+ set(GENERATOR_32 "Visual Studio 14 2015")
+ set(GENERATOR_64 "Visual Studio 14 2015 Win64")
+ endif()
+endif()
+
+
+if(WIN32)
+ set(ZLIB_LIBRARY zlibstatic${LIBEXT})
+else()
+ set(ZLIB_LIBRARY libz${LIBEXT})
+endif()
+
+if(MSVC)
+ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+endif()
+
+set(CMAKE_INSTALL_MESSAGE LAZY)
diff --git a/build_files/build_environment/cmake/orc.cmake b/build_files/build_environment/cmake/orc.cmake
new file mode 100644
index 00000000000..aac7884f49e
--- /dev/null
+++ b/build_files/build_environment/cmake/orc.cmake
@@ -0,0 +1,32 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_orc
+ URL ${ORC_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${ORC_HASH}
+ PREFIX ${BUILD_DIR}/orc
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/orc/src/external_orc/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/orc --disable-shared --enable-static
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/orc/src/external_orc/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/orc/src/external_orc/ && make install
+ INSTALL_DIR ${LIBDIR}/orc
+)
+
+if(MSVC)
+ set_target_properties(external_orc PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake
new file mode 100644
index 00000000000..5ddb981c604
--- /dev/null
+++ b/build_files/build_environment/cmake/osl.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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ set(OSL_CMAKE_CXX_STANDARD_LIBRARIES "kernel32${LIBEXT} user32${LIBEXT} gdi32${LIBEXT} winspool${LIBEXT} shell32${LIBEXT} ole32${LIBEXT} oleaut32${LIBEXT} uuid${LIBEXT} comdlg32${LIBEXT} advapi32${LIBEXT} psapi${LIBEXT}")
+ set(OSL_FLEX_BISON -DFLEX_EXECUTABLE=${LIBDIR}/flexbison/win_flex.exe -DFLEX_EXTRA_OPTIONS="--wincompat" -DBISON_EXECUTABLE=${LIBDIR}/flexbison/win_bison.exe)
+ set(OSL_OPENIMAGEIO_LIBRARY "${LIBDIR}/openimageio/lib/${LIBPREFIX}OpenImageIO${LIBEXT};${LIBDIR}/openimageio/lib/${LIBPREFIX}OpenImageIO_Util${LIBEXT};${LIBDIR}/png/lib/libpng16${LIBEXT};${LIBDIR}/jpg/lib/${LIBPREFIX}jpeg${LIBEXT};${LIBDIR}/tiff/lib/${LIBPREFIX}tiff${LIBEXT};${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf-2_2${LIBEXT}")
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
+ set(OSL_SIMD_FLAGS -DOIIO_NOSIMD=1 -DOIIO_SIMD=0)
+ else()
+ set(OSL_SIMD_FLAGS -DOIIO_NOSIMD=1 -DOIIO_SIMD=sse2)
+ endif()
+else()
+ set(OSL_CMAKE_CXX_STANDARD_LIBRARIES)
+ set(OSL_FLEX_BISON)
+ set(OSL_OPENIMAGEIO_LIBRARY "${LIBDIR}/openimageio/lib/${LIBPREFIX}OpenImageIO${LIBEXT};${LIBDIR}/openimageio/lib/${LIBPREFIX}OpenImageIO_Util${LIBEXT};${LIBDIR}/png/lib/${LIBPREFIX}png16${LIBEXT};${LIBDIR}/jpg/lib/${LIBPREFIX}jpeg${LIBEXT};${LIBDIR}/tiff/lib/${LIBPREFIX}tiff${LIBEXT};${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf-2_2${LIBEXT}")
+endif()
+
+set(OSL_ILMBASE_CUSTOM_LIBRARIES "${LIBDIR}/ilmbase/lib/Imath-2_2.lib^^${LIBDIR}/ilmbase/lib/Half.lib^^${LIBDIR}/ilmbase/lib/IlmThread-2_2.lib^^${LIBDIR}/ilmbase/lib/Iex-2_2.lib")
+set(OSL_LLVM_LIBRARY "${LIBDIR}/llvm/lib/LLVMAnalysis${LIBEXT};${LIBDIR}/llvm/lib/LLVMAsmParser${LIBEXT};${LIBDIR}/llvm/lib/LLVMAsmPrinter${LIBEXT};${LIBDIR}/llvm/lib/LLVMBitReader${LIBEXT};${LIBDIR}/llvm/lib/LLVMBitWriter${LIBEXT};${LIBDIR}/llvm/lib/LLVMCodeGen${LIBEXT};${LIBDIR}/llvm/lib/LLVMCore${LIBEXT};${LIBDIR}/llvm/lib/LLVMDebugInfo${LIBEXT};${LIBDIR}/llvm/lib/LLVMExecutionEngine${LIBEXT};${LIBDIR}/llvm/lib/LLVMInstCombine${LIBEXT};${LIBDIR}/llvm/lib/LLVMInstrumentation${LIBEXT};${LIBDIR}/llvm/lib/LLVMInterpreter${LIBEXT};${LIBDIR}/llvm/lib/LLVMJIT${LIBEXT};${LIBDIR}/llvm/lib/LLVMLinker${LIBEXT};${LIBDIR}/llvm/lib/LLVMMC${LIBEXT};${LIBDIR}/llvm/lib/LLVMMCDisassembler${LIBEXT};${LIBDIR}/llvm/lib/LLVMMCJIT${LIBEXT};${LIBDIR}/llvm/lib/LLVMMCParser${LIBEXT};${LIBDIR}/llvm/lib/LLVMObject${LIBEXT};${LIBDIR}/llvm/lib/LLVMRuntimeDyld${LIBEXT};${LIBDIR}/llvm/lib/LLVMScalarOpts${LIBEXT};${LIBDIR}/llvm/lib/LLVMSelectionDAG${LIBEXT};${LIBDIR}/llvm/lib/LLVMSupport${LIBEXT};${LIBDIR}/llvm/lib/LLVMTableGen${LIBEXT};${LIBDIR}/llvm/lib/LLVMTarget${LIBEXT};${LIBDIR}/llvm/lib/LLVMTransformUtils${LIBEXT};${LIBDIR}/llvm/lib/LLVMVectorize${LIBEXT};${LIBDIR}/llvm/lib/LLVMX86AsmParser${LIBEXT};${LIBDIR}/llvm/lib/LLVMX86AsmPrinter${LIBEXT};${LIBDIR}/llvm/lib/LLVMX86CodeGen${LIBEXT};${LIBDIR}/llvm/lib/LLVMX86Desc${LIBEXT};${LIBDIR}/llvm/lib/LLVMX86Disassembler${LIBEXT};${LIBDIR}/llvm/lib/LLVMX86Info${LIBEXT};${LIBDIR}/llvm/lib/LLVMX86Utils${LIBEXT};${LIBDIR}/llvm/lib/LLVMipa${LIBEXT};${LIBDIR}/llvm/lib/LLVMipo${LIBEXT}")
+
+set(OSL_EXTRA_ARGS
+ -DBoost_COMPILER:STRING=${BOOST_COMPILER_STRING}
+ -DBoost_USE_MULTITHREADED=ON
+ -DBoost_USE_STATIC_LIBS=ON
+ -DBoost_USE_STATIC_RUNTIME=ON
+ -DBOOST_ROOT=${LIBDIR}/boost
+ -DBOOST_LIBRARYDIR=${LIBDIR}/boost/lib/
+ -DBoost_NO_SYSTEM_PATHS=ON
+ -DLLVM_DIRECTORY=${LIBDIR}/llvm
+ -DLLVM_INCLUDES=${LIBDIR}/llvm/include
+ -DLLVM_LIB_DIR=${LIBDIR}/llvm/lib
+ -DLLVM_VERSION=3.4
+ -DLLVM_LIBRARY=${OSL_LLVM_LIBRARY}
+ -DOPENEXR_HOME=${LIBDIR}/openexr/
+ -DILMBASE_HOME=${LIBDIR}/ilmbase/
+ -DILMBASE_INCLUDE_DIR=${LIBDIR}/ilmbase/include/
+ -DOPENEXR_IMATH_LIBRARY=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Imath-2_2${LIBEXT}
+ -DOPENEXR_ILMTHREAD_LIBRARY=${LIBDIR}/ilmbase/lib/${LIBPREFIX}IlmThread-2_2${LIBEXT}
+ -DOPENEXR_IEX_LIBRARY=${LIBDIR}/ilmbase/lib/${LIBPREFIX}Iex-2_2${LIBEXT}
+ -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/
+ -DOPENEXR_ILMIMF_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf-2_2${LIBEXT}
+ -DOSL_BUILD_TESTS=OFF
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include/
+ -DOPENIMAGEIOHOME=${LIBDIR}/openimageio/
+ -DOPENIMAGEIO_LIBRARY=${OSL_OPENIMAGEIO_LIBRARY}
+ -DOPENIMAGEIO_INCLUDES=${LIBDIR}/openimageio/include
+ ${OSL_FLEX_BISON}
+ -DCMAKE_CXX_STANDARD_LIBRARIES=${OSL_CMAKE_CXX_STANDARD_LIBRARIES}
+ -DBUILDSTATIC=ON
+ -DLINKSTATIC=ON
+ -DOSL_BUILD_PLUGINS=Off
+ -DSTOP_ON_WARNING=OFF
+ -DOSL_BUILD_CPP11=ON
+ -DUSE_LLVM_BITCODE=OFF
+ ${OSL_SIMD_FLAGS}
+)
+
+ExternalProject_Add(external_osl
+ URL ${OSL_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ LIST_SEPARATOR ^^
+ URL_HASH MD5=${OSL_HASH}
+ PREFIX ${BUILD_DIR}/osl
+ PATCH_COMMAND ${PATCH_CMD} -p 3 -d ${BUILD_DIR}/osl/src/external_osl < ${PATCH_DIR}/osl.diff &&
+ ${PATCH_CMD} -p 0 -d ${BUILD_DIR}/osl/src/external_osl < ${PATCH_DIR}/osl_simd_oiio.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/osl -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} ${DEFAULT_CMAKE_FLAGS} ${OSL_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/osl
+)
+
+add_dependencies(external_osl external_boost ll external_clang external_ilmbase external_openexr external_zlib external_flexbison external_openimageio)
diff --git a/build_files/build_environment/cmake/png.cmake b/build_files/build_environment/cmake/png.cmake
new file mode 100644
index 00000000000..8d6fee871f9
--- /dev/null
+++ b/build_files/build_environment/cmake/png.cmake
@@ -0,0 +1,41 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(PNG_EXTRA_ARGS
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include/
+ -DPNG_STATIC=ON
+)
+
+ExternalProject_Add(external_png
+ URL ${PNG_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${PNG_HASH}
+ PREFIX ${BUILD_DIR}/png
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/png ${DEFAULT_CMAKE_FLAGS} ${PNG_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/png
+)
+
+add_dependencies(external_png external_zlib)
+
+if(BUILD_MODE STREQUAL Debug)
+ ExternalProject_Add_Step(external_png after_install
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_staticd${LIBEXT} ${LIBDIR}/png/lib/libpng16${LIBEXT}
+ DEPENDEES install
+ )
+endif()
diff --git a/build_files/build_environment/cmake/pthreads.cmake b/build_files/build_environment/cmake/pthreads.cmake
new file mode 100644
index 00000000000..f4301b95f3a
--- /dev/null
+++ b/build_files/build_environment/cmake/pthreads.cmake
@@ -0,0 +1,45 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ set(PTHREAD_XCFLAGS /MD)
+
+ if(MSVC14) # vs2015 has timespec
+ set(PTHREAD_CPPFLAGS "/I. /DHAVE_PTW32_CONFIG_H /D_TIMESPEC_DEFINED ")
+ else() # everything before doesn't
+ set(PTHREAD_CPPFLAGS "/I. /DHAVE_PTW32_CONFIG_H ")
+ endif()
+
+ set(PTHREADS_BUILD cd ${BUILD_DIR}/pthreads/src/external_pthreads/ && cd && nmake VC /e CPPFLAGS=${PTHREAD_CPPFLAGS} /e XCFLAGS=${PTHREAD_XCFLAGS} /e XLIBS=/NODEFAULTLIB:msvcr)
+
+ ExternalProject_Add(external_pthreads
+ URL ${PTHREADS_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA512=${PTHREADS_SHA512}
+ PREFIX ${BUILD_DIR}/pthreads
+ CONFIGURE_COMMAND echo .
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/pthreads/src/external_pthreads < ${PATCH_DIR}/pthreads.diff
+ BUILD_COMMAND ${PTHREADS_BUILD}
+ INSTALL_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/pthreadVC2.dll ${LIBDIR}/pthreads/lib/pthreadVC2.dll &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/pthreadVC2${LIBEXT} ${LIBDIR}/pthreads/lib/pthreadVC2${LIBEXT} &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/pthread.h ${LIBDIR}/pthreads/inc/pthread.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/sched.h ${LIBDIR}/pthreads/inc/sched.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/semaphore.h ${LIBDIR}/pthreads/inc/semaphore.h
+ INSTALL_DIR ${LIBDIR}/pthreads
+ )
+endif()
diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake
new file mode 100644
index 00000000000..c1c7bf7001c
--- /dev/null
+++ b/build_files/build_environment/cmake/python.cmake
@@ -0,0 +1,138 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(PYTHON_POSTFIX)
+if(BUILD_MODE STREQUAL Debug)
+ set(PYTHON_POSTFIX _d)
+endif()
+
+if(WIN32)
+ set(PYTHON_BINARY ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe)
+
+ macro(cmake_to_dos_path MsysPath ResultingPath)
+ string(REPLACE "/" "\\" ${ResultingPath} "${MsysPath}")
+ endmacro()
+
+ set(PYTHON_EXTERNALS_FOLDER ${BUILD_DIR}/python/src/external_python/externals)
+ set(DOWNLOADS_EXTERNALS_FOLDER ${DOWNLOAD_DIR}/externals)
+
+ cmake_to_dos_path(${PYTHON_EXTERNALS_FOLDER} PYTHON_EXTERNALS_FOLDER_DOS)
+ cmake_to_dos_path(${DOWNLOADS_EXTERNALS_FOLDER} DOWNLOADS_EXTERNALS_FOLDER_DOS)
+
+ message("Python externals = ${PYTHON_EXTERNALS_FOLDER}")
+ message("Python externals_dos = ${PYTHON_EXTERNALS_FOLDER_DOS}")
+ message("Python DOWNLOADS_EXTERNALS_FOLDER = ${DOWNLOADS_EXTERNALS_FOLDER}")
+ message("Python DOWNLOADS_EXTERNALS_FOLDER_DOS = ${DOWNLOADS_EXTERNALS_FOLDER_DOS}")
+
+ ExternalProject_Add(external_python
+ URL ${PYTHON_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${PYTHON_HASH}
+ PREFIX ${BUILD_DIR}/python
+ PATCH_COMMAND echo mklink /D "${PYTHON_EXTERNALS_FOLDER_DOS}" "${DOWNLOADS_EXTERNALS_FOLDER_DOS}" &&
+ mklink /D "${PYTHON_EXTERNALS_FOLDER_DOS}" "${DOWNLOADS_EXTERNALS_FOLDER_DOS}" &&
+ ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python.diff &&
+ ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/python/src/external_python/pc < ${PATCH_DIR}/pyshell.diff
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p ${PYTHON_ARCH} -c ${BUILD_MODE} -k ${PYTHON_COMPILER_STRING}
+ INSTALL_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${PYTHON_OUTPUTDIR}/python35${PYTHON_POSTFIX}.dll ${LIBDIR}/python/lib/python35${PYTHON_POSTFIX}.dll &&
+ ${CMAKE_COMMAND} -E copy ${PYTHON_OUTPUTDIR}/python35${PYTHON_POSTFIX}.lib ${LIBDIR}/python/lib/python35${PYTHON_POSTFIX}.lib &&
+ ${CMAKE_COMMAND} -E copy ${PYTHON_OUTPUTDIR}/python35${PYTHON_POSTFIX}.exp ${LIBDIR}/python/lib/python35${PYTHON_POSTFIX}.exp &&
+ ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/python/src/external_python/include ${LIBDIR}/python/include/Python3.5 &&
+ ${CMAKE_COMMAND} -E copy "${BUILD_DIR}/python/src/external_python/PC/pyconfig.h" ${LIBDIR}/python/include/Python3.5/pyconfig.h
+ )
+ Message("PythinRedist = ${BUILD_DIR}/python/src/external_python/redist")
+ Message("POutput = ${PYTHON_OUTPUTDIR}")
+else()
+ if(APPLE)
+ # we need to manually add homebrew headers to get ssl module building
+ set(PYTHON_CFLAGS "-I/usr/local/opt/openssl/include -I${OSX_SYSROOT}/usr/include ${PLATFORM_CFLAGS}")
+ set(PYTHON_LDFLAGS "-L/usr/local/opt/openssl/lib ${PLATFORM_LDFLAGS}")
+ set(PYTHON_CONFIGURE_ENV ${CONFIGURE_ENV} && export CFLAGS=${PYTHON_CFLAGS} && export LDFLAGS=${PYTHON_LDFLAGS})
+ set(PYTHON_BINARY ${BUILD_DIR}/python/src/external_python/python.exe)
+ set(PYTHON_PATCH ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_apple.diff)
+ else()
+ set(PYTHON_CONFIGURE_ENV ${CONFIGURE_ENV})
+ set(PYTHON_BINARY ${BUILD_DIR}/python/src/external_python/python)
+ endif()
+
+ ExternalProject_Add(external_python
+ URL ${PYTHON_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${PYTHON_HASH}
+ PREFIX ${BUILD_DIR}/python
+ PATCH_COMMAND ${PYTHON_PATCH}
+ CONFIGURE_COMMAND ${PYTHON_CONFIGURE_ENV} && cd ${BUILD_DIR}/python/src/external_python/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/python
+ BUILD_COMMAND ${PYTHON_CONFIGURE_ENV} && cd ${BUILD_DIR}/python/src/external_python/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${PYTHON_CONFIGURE_ENV} && cd ${BUILD_DIR}/python/src/external_python/ && make install
+ INSTALL_DIR ${LIBDIR}/python)
+
+ add_custom_target(Make_Python_Environment ALL DEPENDS external_python)
+endif()
+
+if(MSVC)
+ add_custom_command(
+ OUTPUT ${LIBDIR}/python35${PYTHON_POSTFIX}.tar.gz
+ OUTPUT ${BUILD_DIR}/python/src/external_python/redist/bin/python${PYTHON_POSTFIX}.exe
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/python/src/external_python/lib ${BUILD_DIR}/python/src/external_python/redist/lib
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python${PYTHON_POSTFIX}.exe" ${BUILD_DIR}/python/src/external_python/redist/bin/python${PYTHON_POSTFIX}.exe
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_bz2${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_bz2${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_hashlib${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_hashlib${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_lzma${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_lzma${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_sqlite3${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_sqlite3${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_ssl${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_ssl${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/pyexpat${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/pyexpat${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/select${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/select${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/unicodedata${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/unicodedata${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/winsound${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/winsound${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_ctypes${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_ctypes${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_ctypes_test${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_ctypes_test${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_decimal${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_decimal${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_elementtree${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_elementtree${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_msi${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_msi${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_multiprocessing${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_multiprocessing${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_overlapped${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_overlapped${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_socket${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_socket${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_testbuffer${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_testbuffer${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_testcapi${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_testcapi${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_testimportmultiple${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_testimportmultiple${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_testmultiphase${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_testmultiphase${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E chdir "${BUILD_DIR}/python/src/external_python/redist" ${CMAKE_COMMAND} -E tar "cfvz" "${LIBDIR}/python35${PYTHON_POSTFIX}.tar.gz" "."
+ )
+
+ add_custom_target(Package_Python ALL DEPENDS external_python ${LIBDIR}/python35${PYTHON_POSTFIX}.tar.gz ${BUILD_DIR}/python/src/external_python/redist/bin/python${PYTHON_POSTFIX}.exe)
+
+ if(MSVC12)
+ set(PYTHON_DISTUTIL_PATCH ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/python/src/external_python/run/lib/distutils < ${PATCH_DIR}/python_runtime_vc2013.diff)
+ else()
+ set(PYTHON_DISTUTIL_PATCH echo "No patch needed")
+ endif()
+
+ add_custom_command(OUTPUT ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/python/src/external_python/redist ${BUILD_DIR}/python/src/external_python/run
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/python/src/external_python/include ${BUILD_DIR}/python/src/external_python/run/include
+ COMMAND ${CMAKE_COMMAND} -E copy "${BUILD_DIR}/python/src/external_python/PC/pyconfig.h" ${BUILD_DIR}/python/src/external_python/run/include/pyconfig.h
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python35${PYTHON_POSTFIX}.dll" ${BUILD_DIR}/python/src/external_python/run/python35${PYTHON_POSTFIX}.dll
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python35${PYTHON_POSTFIX}.lib" ${BUILD_DIR}/python/src/external_python/run/libs/python35.lib #missing postfix on purpose, distutils is not expecting it
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python35${PYTHON_POSTFIX}.lib" ${BUILD_DIR}/python/src/external_python/run/libs/python35${PYTHON_POSTFIX}.lib #other things like numpy still want it though.
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python${PYTHON_POSTFIX}.exe" ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe
+ COMMAND ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe -m ensurepip --upgrade
+ COMMAND ${PYTHON_DISTUTIL_PATCH}
+ )
+ add_custom_target(Make_Python_Environment ALL DEPENDS ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe Package_Python)
+endif(MSVC)
diff --git a/build_files/build_environment/cmake/requests.cmake b/build_files/build_environment/cmake/requests.cmake
new file mode 100644
index 00000000000..f5aa26b0615
--- /dev/null
+++ b/build_files/build_environment/cmake/requests.cmake
@@ -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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(BUILD_MODE STREQUAL Release)
+ if(WIN32)
+ set(REQUESTS_INSTALL_DIR ${LIBDIR}/requests)
+ else()
+ set(REQUESTS_INSTALL_DIR ${LIBDIR}/python/lib/python${PYTHON_SHORT_VERSION}/site-packages/requests)
+ endif()
+
+ ExternalProject_Add(external_requests
+ URL ${REQUESTS_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${REQUESTS_HASH}
+ PREFIX ${BUILD_DIR}/requests
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/requests/src/external_requests/requests ${REQUESTS_INSTALL_DIR}
+ )
+
+ add_dependencies(external_requests Make_Python_Environment)
+endif(BUILD_MODE STREQUAL Release)
diff --git a/build_files/build_environment/cmake/schroedinger.cmake b/build_files/build_environment/cmake/schroedinger.cmake
new file mode 100644
index 00000000000..54a20db5b5e
--- /dev/null
+++ b/build_files/build_environment/cmake/schroedinger.cmake
@@ -0,0 +1,45 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ set(SCHROEDINGER_EXTRA_FLAGS "CFLAGS=-g -I./ -I${LIBDIR}/orc/include/orc-0.4" "LDFLAGS=-Wl,--as-needed -static-libgcc -L${LIBDIR}/orc/lib" ORC_CFLAGS=-I${LIBDIR}/orc/include/orc-0.4 ORC_LDFLAGS=-L${LIBDIR}/orc/lib ORC_LIBS=${LIBDIR}/orc/lib/liborc-0.4.a ORCC=${LIBDIR}/orc/bin/orcc.exe)
+else()
+ set(SCHROEDINGER_CFLAGS "${PLATFORM_CFLAGS} -I./ -I${LIBDIR}/orc/include/orc-0.4")
+ set(SCHROEDINGER_LDFLAGS "${PLATFORM_LDFLAGS} -L${LIBDIR}/orc/lib")
+ set(SCHROEDINGER_EXTRA_FLAGS CFLAGS=${SCHROEDINGER_CFLAGS} LDFLAGS=${SCHROEDINGER_LDFLAGS} ORC_CFLAGS=-I${LIBDIR}/orc/include/orc-0.4 ORC_LDFLAGS=-L${LIBDIR}/orc/lib ORCC=${LIBDIR}/orc/bin/orcc) # ORC_LIBS=${LIBDIR}/orc/lib/liborc-0.4.a
+endif()
+
+ExternalProject_Add(external_schroedinger
+ URL ${SCHROEDINGER_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${SCHROEDINGER_HASH}
+ PREFIX ${BUILD_DIR}/schroedinger
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/schroedinger/src/external_schroedinger < ${PATCH_DIR}/schroedinger.diff
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} &&
+ cd ${BUILD_DIR}/schroedinger/src/external_schroedinger/ &&
+ ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/schroedinger --disable-shared --enable-static ${SCHROEDINGER_EXTRA_FLAGS}
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/schroedinger/src/external_schroedinger/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/schroedinger/src/external_schroedinger/ && make install
+ INSTALL_DIR ${LIBDIR}/schroedinger
+)
+
+add_dependencies(external_schroedinger external_orc)
+
+if(MSVC)
+ set_target_properties(external_schroedinger PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/sdl.cmake b/build_files/build_environment/cmake/sdl.cmake
new file mode 100644
index 00000000000..0fbfa078eb1
--- /dev/null
+++ b/build_files/build_environment/cmake/sdl.cmake
@@ -0,0 +1,39 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ set(SDL_EXTRA_ARGS
+ -DSDL_STATIC=Off
+ )
+else()
+ set(SDL_EXTRA_ARGS
+ -DSDL_STATIC=ON
+ -DSDL_SHARED=OFF
+ -DSDL_VIDEO=OFF
+ )
+endif()
+
+ExternalProject_Add(external_sdl
+ URL ${SDL_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${SDL_HASH}
+ PREFIX ${BUILD_DIR}/sdl
+ PATCH_COMMAND ${PATCH_CMD} -p 0 -N -d ${BUILD_DIR}/sdl/src/external_sdl < ${PATCH_DIR}/sdl.diff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/sdl ${DEFAULT_CMAKE_FLAGS} ${SDL_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/sdl
+)
diff --git a/build_files/build_environment/cmake/setup_mingw32.cmake b/build_files/build_environment/cmake/setup_mingw32.cmake
new file mode 100644
index 00000000000..f0d99356da0
--- /dev/null
+++ b/build_files/build_environment/cmake/setup_mingw32.cmake
@@ -0,0 +1,219 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+####################################################################################################################
+# Mingw32 Builds
+####################################################################################################################
+# This installs mingw32+msys to compile ffmpeg/iconv/libsndfile/lapack/fftw3
+####################################################################################################################
+
+message("LIBDIR = ${LIBDIR}")
+macro(cmake_to_msys_path MsysPath ResultingPath)
+ string(REPLACE ":" "" TmpPath "${MsysPath}")
+ string(SUBSTRING ${TmpPath} 0 1 Drive)
+ string(SUBSTRING ${TmpPath} 1 255 PathPart)
+ string(TOLOWER ${Drive} LowerDrive)
+ string(CONCAT ${ResultingPath} "/" ${LowerDrive} ${PathPart})
+endmacro()
+cmake_to_msys_path(${LIBDIR} mingw_LIBDIR)
+message("mingw_LIBDIR = ${mingw_LIBDIR}")
+
+message("Checking for mingw32")
+# download mingw32
+if(NOT EXISTS "${DOWNLOAD_DIR}/i686-w64-mingw32-gcc-4.8.0-win32_rubenvb.7z")
+ message("Downloading mingw32")
+ file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/mingw-w64/Toolchains%20targetting%20Win32/Personal%20Builds/rubenvb/gcc-4.8-release/i686-w64-mingw32-gcc-4.8.0-win32_rubenvb.7z" "${DOWNLOAD_DIR}/i686-w64-mingw32-gcc-4.8.0-win32_rubenvb.7z")
+endif()
+
+# make mingw root directory
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/mingw
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}
+ )
+endif()
+
+# extract mingw32
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/mingw32env.cmd") AND (EXISTS "${DOWNLOAD_DIR}/i686-w64-mingw32-gcc-4.8.0-win32_rubenvb.7z"))
+ message("Extracting mingw32")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/i686-w64-mingw32-gcc-4.8.0-win32_rubenvb.7z
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw
+ )
+endif()
+
+message("Checking for pkg-config")
+if(NOT EXISTS "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip")
+ message("Downloading pkg-config")
+ file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/pkgconfiglite/0.28-1/pkg-config-lite-0.28-1_bin-win32.zip" "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip")
+endif()
+
+# extract pkgconfig
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/pkg-config.exe") AND (EXISTS "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip"))
+ message("Extracting pkg-config")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip"
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/
+ )
+
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1/bin/pkg-config.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/pkg-config.exe"
+ )
+
+endif()
+
+message("Checking for nasm")
+if(NOT EXISTS "${DOWNLOAD_DIR}/nasm-2.12.01-win32.zip")
+ message("Downloading nasm")
+ file(DOWNLOAD "http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win32/nasm-2.12.01-win32.zip" "${DOWNLOAD_DIR}/nasm-2.12.01-win32.zip")
+endif()
+
+# extract nasm
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe") AND (EXISTS "${DOWNLOAD_DIR}/nasm-2.12.01-win32.zip"))
+ message("Extracting nasm")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/nasm-2.12.01-win32.zip"
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/
+ )
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/nasm-2.12.01/nasm.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe"
+ )
+
+endif()
+
+message("Checking for mingwGet")
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip")
+ message("Downloading mingw-get")
+ file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/mingw/Installer/mingw-get/mingw-get-0.6.2-beta-20131004-1/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip" "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip")
+endif()
+
+# extract mingw_get
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/mingw-get.exe") AND (EXISTS "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip"))
+ message("Extracting mingw-get")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip"
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw/mingw32/
+ )
+endif()
+
+if((EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/mingw-get.exe") AND (NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/make.exe"))
+ message("Installing MSYS")
+ execute_process(
+ COMMAND ${DOWNLOAD_DIR}/mingw/mingw32/bin/mingw-get install msys msys-patch
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw/mingw32/bin/
+ )
+endif()
+
+message("Checking for CoreUtils")
+# download old core_utils for pr.exe (ffmpeg needs it to build)
+if(NOT EXISTS "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2")
+ message("Downloading CoreUtils 5.97")
+ file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/mingw/MSYS/Base/msys-core/_obsolete/coreutils-5.97-MSYS-1.0.11-2/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2" "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2")
+endif()
+
+if((EXISTS "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2") AND (NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/pr.exe"))
+ message("Installing pr from CoreUtils 5.97")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/tmp_coreutils
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}
+ )
+
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/tmp_coreutils/
+ )
+
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy ${DOWNLOAD_DIR}/tmp_coreutils/coreutils-5.97/bin/pr.exe "${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/pr.exe"
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/tmp_coreutils/
+ )
+endif()
+
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/ming32sh.cmd")
+ message("Installing ming32sh.cmd")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/ming32sh.cmd ${DOWNLOAD_DIR}/mingw/mingw32/ming32sh.cmd
+ )
+endif()
+
+message("Checking for perl")
+# download perl for libvpx
+if(NOT EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-32bit-portable.zip")
+ message("Downloading perl")
+ file(DOWNLOAD "http://strawberryperl.com/download/5.22.1.3/strawberry-perl-5.22.1.3-32bit-portable.zip" "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-32bit-portable.zip")
+endif()
+
+# make perl root directory
+if(NOT EXISTS "${DOWNLOAD_DIR}/perl32")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/perl32
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}
+ )
+endif()
+
+# extract perl
+if((NOT EXISTS "${DOWNLOAD_DIR}/perl32/portable.perl") AND (EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-32bit-portable.zip"))
+ message("Extracting perl")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-32bit-portable.zip
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/perl32
+ )
+endif()
+
+# get yasm for vpx
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/yasm.exe")
+ message("Downloading yasm")
+ file(DOWNLOAD "http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win32.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/yasm.exe")
+endif()
+
+message("checking i686-w64-mingw32-strings")
+# copy strings.exe to i686-w64-mingw32-strings for x264
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-strings.exe")
+ message("fixing i686-w64-mingw32-strings.exe")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/strings.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-strings.exe"
+ )
+endif()
+
+message("checking i686-w64-mingw32-ar.exe")
+# copy ar.exe to i686-w64-mingw32-ar.exe for x264
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ar.exe")
+ message("fixing i686-w64-mingw32-ar.exe")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/ar.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ar.exe"
+ )
+endif()
+
+message("checking i686-w64-mingw32-strip.exe")
+# copy strip.exe to i686-w64-mingw32-strip.exe for x264
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-strip.exe")
+ message("fixing i686-w64-mingw32-strip.exe")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/strip.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-strip.exe"
+ )
+endif()
+
+message("checking i686-w64-mingw32-ranlib.exe")
+# copy ranlib.exe to i686-w64-mingw32-ranlib.exe for x264
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ranlib.exe")
+ message("fixing i686-w64-mingw32-ranlib.exe")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/ranlib.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ranlib.exe"
+ )
+endif()
+
diff --git a/build_files/build_environment/cmake/setup_mingw64.cmake b/build_files/build_environment/cmake/setup_mingw64.cmake
new file mode 100644
index 00000000000..14f75d410b4
--- /dev/null
+++ b/build_files/build_environment/cmake/setup_mingw64.cmake
@@ -0,0 +1,219 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+####################################################################################################################
+# Mingw64 Builds
+####################################################################################################################
+# This installs mingw64+msys to compile ffmpeg/iconv/libsndfile/lapack/fftw3
+####################################################################################################################
+
+message("LIBDIR = ${LIBDIR}")
+macro(cmake_to_msys_path MsysPath ResultingPath)
+ string(REPLACE ":" "" TmpPath "${MsysPath}")
+ string(SUBSTRING ${TmpPath} 0 1 Drive)
+ string(SUBSTRING ${TmpPath} 1 255 PathPart)
+ string(TOLOWER ${Drive} LowerDrive)
+ string(CONCAT ${ResultingPath} "/" ${LowerDrive} ${PathPart})
+endmacro()
+cmake_to_msys_path(${LIBDIR} mingw_LIBDIR)
+message("mingw_LIBDIR = ${mingw_LIBDIR}")
+
+message("Checking for mingw64")
+# download ming64
+if(NOT EXISTS "${DOWNLOAD_DIR}/x86_64-w64-mingw32-gcc-4.8.0-win64_rubenvb.7z")
+ message("Downloading mingw64")
+ file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/mingw-w64/Toolchains%20targetting%20Win64/Personal%20Builds/rubenvb/gcc-4.8-release/x86_64-w64-mingw32-gcc-4.8.0-win64_rubenvb.7z" "${DOWNLOAD_DIR}/x86_64-w64-mingw32-gcc-4.8.0-win64_rubenvb.7z")
+endif()
+
+# make mingw root directory
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/mingw
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}
+ )
+endif()
+
+# extract mingw64
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/mingw64env.cmd") AND (EXISTS "${DOWNLOAD_DIR}/x86_64-w64-mingw32-gcc-4.8.0-win64_rubenvb.7z"))
+ message("Extracting mingw64")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/x86_64-w64-mingw32-gcc-4.8.0-win64_rubenvb.7z
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw
+ )
+endif()
+
+message("Checking for pkg-config")
+if(NOT EXISTS "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip")
+ message("Downloading pkg-config")
+ file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/pkgconfiglite/0.28-1/pkg-config-lite-0.28-1_bin-win32.zip" "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip")
+endif()
+
+# extract pkgconfig
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/pkg-config.exe") AND (EXISTS "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip"))
+ message("Extracting pkg-config")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip"
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/
+ )
+
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1/bin/pkg-config.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/pkg-config.exe"
+ )
+
+endif()
+
+message("Checking for nasm")
+if(NOT EXISTS "${DOWNLOAD_DIR}/nasm-2.12.01-win64.zip")
+ message("Downloading nasm")
+ file(DOWNLOAD "http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip" "${DOWNLOAD_DIR}/nasm-2.12.01-win64.zip")
+endif()
+
+# extract nasm
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/nasm.exe") AND (EXISTS "${DOWNLOAD_DIR}/nasm-2.12.01-win64.zip"))
+ message("Extracting nasm")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/nasm-2.12.01-win64.zip"
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/
+ )
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/nasm-2.12.01/nasm.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/nasm.exe"
+ )
+
+endif()
+
+message("Checking for mingwGet")
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip")
+ message("Downloading mingw-get")
+ file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/mingw/Installer/mingw-get/mingw-get-0.6.2-beta-20131004-1/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip" "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip")
+endif()
+
+# extract mingw_get
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/mingw-get.exe") AND (EXISTS "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip"))
+ message("Extracting mingw-get")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip"
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw/mingw64/
+ )
+endif()
+
+if((EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/mingw-get.exe") AND (NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/make.exe"))
+ message("Installing MSYS")
+ execute_process(
+ COMMAND ${DOWNLOAD_DIR}/mingw/mingw64/bin/mingw-get install msys msys-patch
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw/mingw64/bin/
+ )
+endif()
+
+message("Checking for CoreUtils")
+# download old core_utils for pr.exe (ffmpeg needs it to build)
+if(NOT EXISTS "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2")
+ message("Downloading CoreUtils 5.97")
+ file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/mingw/MSYS/Base/msys-core/_obsolete/coreutils-5.97-MSYS-1.0.11-2/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2" "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2")
+endif()
+
+if((EXISTS "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2") AND (NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/pr.exe"))
+ message("Installing pr from CoreUtils 5.97")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/tmp_coreutils
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}
+ )
+
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/tmp_coreutils/
+ )
+
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy ${DOWNLOAD_DIR}/tmp_coreutils/coreutils-5.97/bin/pr.exe "${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/pr.exe"
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/tmp_coreutils/
+ )
+endif()
+
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/ming64sh.cmd")
+ message("Installing ming64sh.cmd")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/ming64sh.cmd ${DOWNLOAD_DIR}/mingw/mingw64/ming64sh.cmd
+ )
+endif()
+
+message("Checking for perl")
+# download perl for libvpx
+if(NOT EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-64bit-portable.zip")
+ message("Downloading perl")
+ file(DOWNLOAD "http://strawberryperl.com/download/5.22.1.3/strawberry-perl-5.22.1.3-64bit-portable.zip" "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-64bit-portable.zip")
+endif()
+
+# make perl root directory
+if(NOT EXISTS "${DOWNLOAD_DIR}/perl")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/perl
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}
+ )
+endif()
+
+# extract perl
+if((NOT EXISTS "${DOWNLOAD_DIR}/perl/portable.perl") AND (EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-64bit-portable.zip"))
+ message("Extracting perl")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-64bit-portable.zip
+ WORKING_DIRECTORY ${DOWNLOAD_DIR}/perl
+ )
+endif()
+
+# get yasm for vpx
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/yasm.exe")
+ message("Downloading yasm")
+ file(DOWNLOAD "http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/yasm.exe")
+endif()
+
+message("checking x86_64-w64-mingw32-strings.exe")
+# copy strings.exe to x86_64-w64-mingw32-strings.exe for x264
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-strings.exe")
+ message("fixing x86_64-w64-mingw32-strings.exe")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw64/bin/strings.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-strings.exe"
+ )
+endif()
+
+message("checking x86_64-w64-mingw32-ar.exe")
+# copy ar.exe to x86_64-w64-mingw32-ar.exe for x264
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-ar.exe")
+ message("fixing x86_64-w64-mingw32-ar.exe")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw64/bin/ar.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-ar.exe"
+ )
+endif()
+
+message("checking x86_64-w64-mingw32-strip.exe")
+# copy strip.exe to x86_64-w64-mingw32-strip.exe for x264
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-strip.exe")
+ message("fixing x86_64-w64-mingw32-strip.exe")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw64/bin/strip.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-strip.exe"
+ )
+endif()
+
+message("checking x86_64-w64-mingw32-ranlib.exe")
+# copy ranlib.exe to x86_64-w64-mingw32-ranlib.exe for x264
+if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-ranlib.exe")
+ message("fixing x86_64-w64-mingw32-ranlib.exe")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw64/bin/ranlib.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-ranlib.exe"
+ )
+endif()
+
diff --git a/build_files/build_environment/cmake/sndfile.cmake b/build_files/build_environment/cmake/sndfile.cmake
new file mode 100644
index 00000000000..13368c05fbe
--- /dev/null
+++ b/build_files/build_environment/cmake/sndfile.cmake
@@ -0,0 +1,44 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(SNDFILE_EXTRA_ARGS)
+set(SNDFILE_ENV PKG_CONFIG_PATH=${mingw_LIBDIR}/ogg/lib/pkgconfig:${mingw_LIBDIR}/vorbis/lib/pkgconfig:${mingw_LIBDIR}/flac/lib/pkgconfig:${mingw_LIBDIR})
+
+if(WIN32)
+ set(SNDFILE_ENV set ${SNDFILE_ENV} &&)
+endif()
+
+ExternalProject_Add(external_sndfile
+ URL ${SNDFILE_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${SNDFILE_HASH}
+ PREFIX ${BUILD_DIR}/sndfile
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && ${SNDFILE_ENV} ${CONFIGURE_COMMAND} --enable-static --disable-shared --prefix=${mingw_LIBDIR}/sndfile
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make install
+ INSTALL_DIR ${LIBDIR}/sndfile
+)
+
+if(MSVC)
+ set_target_properties(external_sndfile PROPERTIES FOLDER Mingw)
+endif()
+
+add_dependencies(external_sndfile external_ogg external_vorbis)
+if(UNIX)
+ add_dependencies(external_sndfile external_flac)
+endif()
diff --git a/build_files/build_environment/cmake/spnav.cmake b/build_files/build_environment/cmake/spnav.cmake
new file mode 100644
index 00000000000..0dec9799715
--- /dev/null
+++ b/build_files/build_environment/cmake/spnav.cmake
@@ -0,0 +1,28 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_spnav
+ URL ${SPNAV_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${SPNAV_HASH}
+ PREFIX ${BUILD_DIR}/spnav
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/spnav/src/external_spnav/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/spnav --disable-shared --enable-static --with-pic
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/spnav/src/external_spnav/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/spnav/src/external_spnav/ && make install
+ INSTALL_DIR ${LIBDIR}/spnav
+)
diff --git a/build_files/build_environment/cmake/tbb.cmake b/build_files/build_environment/cmake/tbb.cmake
new file mode 100644
index 00000000000..c4055d55648
--- /dev/null
+++ b/build_files/build_environment/cmake/tbb.cmake
@@ -0,0 +1,36 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(TBB_EXTRA_ARGS
+ -DTBB_BUILD_SHARED=Off
+ -DTBB_BUILD_TBBMALLOC=Off
+ -DTBB_BUILD_TBBMALLOC_PROXY=Off
+ -DTBB_BUILD_STATIC=On
+)
+
+# CMake script for TBB from https://github.com/wjakob/tbb/blob/master/CMakeLists.txt
+ExternalProject_Add(external_tbb
+ URL ${TBB_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${TBB_HASH}
+ PREFIX ${BUILD_DIR}/tbb
+ PATCH_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/cmakelists_tbb.txt ${BUILD_DIR}/tbb/src/external_tbb/CMakeLists.txt &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/tbb/src/external_tbb/build/vs2010/version_string.ver ${BUILD_DIR}/tbb/src/external_tbb/src/tbb/version_string.ver
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/tbb ${DEFAULT_CMAKE_FLAGS} ${TBB_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/tbb
+)
diff --git a/build_files/build_environment/cmake/theora.cmake b/build_files/build_environment/cmake/theora.cmake
new file mode 100644
index 00000000000..03aad42f2db
--- /dev/null
+++ b/build_files/build_environment/cmake/theora.cmake
@@ -0,0 +1,40 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_theora
+ URL ${THEORA_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${THEORA_HASH}
+ PREFIX ${BUILD_DIR}/theora
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/theora/src/external_theora/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/theora
+ --disable-shared
+ --enable-static
+ --with-pic
+ --with-ogg=${LIBDIR}/ogg
+ --with-vorbis=${LIBDIR}/vorbis
+ --disable-examples
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/theora/src/external_theora/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/theora/src/external_theora/ && make install
+ INSTALL_DIR ${LIBDIR}/theora
+)
+
+add_dependencies(external_theora external_vorbis external_ogg)
+
+if(MSVC)
+ set_target_properties(external_theora PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/tiff.cmake b/build_files/build_environment/cmake/tiff.cmake
new file mode 100644
index 00000000000..2c01341eb21
--- /dev/null
+++ b/build_files/build_environment/cmake/tiff.cmake
@@ -0,0 +1,44 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(TIFF_EXTRA_ARGS
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include
+ -DPNG_STATIC=ON
+ -DBUILD_SHARED_LIBS=OFF
+ -Dlzma=OFF
+ -Djbig=OFF
+)
+
+ExternalProject_Add(external_tiff
+ URL ${TIFF_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${TIFF_HASH}
+ PREFIX ${BUILD_DIR}/tiff
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/tiff ${DEFAULT_CMAKE_FLAGS} ${TIFF_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/tiff
+)
+
+add_dependencies(external_tiff external_zlib)
+
+if(BUILD_MODE STREQUAL Debug)
+ ExternalProject_Add_Step(external_tiff after_install
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tiff/lib/tiffd${LIBEXT} ${LIBDIR}/tiff/lib/tiff${LIBEXT}
+ DEPENDEES install
+ )
+endif()
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
new file mode 100644
index 00000000000..f9f9fdcface
--- /dev/null
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -0,0 +1,245 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(ZLIB_VERSION 1.2.8)
+set(ZLIB_URI https://netcologne.dl.sourceforge.net/project/libpng/zlib/${ZLIB_VERSION}/zlib-${ZLIB_VERSION}.tar.gz)
+set(ZLIB_HASH 44d667c142d7cda120332623eab69f40)
+
+set(OPENAL_VERSION 1.17.2)
+set(OPENAL_URI http://kcat.strangesoft.net/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
+set(OPENAL_HASH 1764e0d8fec499589b47ebc724e0913d)
+
+set(PNG_VERSION 1.6.21)
+set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.gz)
+set(PNG_HASH aca36ec8e0a3b406a5912243bc243717)
+
+set(JPEG_VERSION 1.4.2)
+set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz)
+set(JPEG_HASH f9804884c1c41eb7f4febb9353a2cb27)
+
+set(BOOST_VERSION 1.60.0)
+set(BOOST_VERSION_NODOTS 1_60_0)
+set(BOOST_URI http://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/boost_${BOOST_VERSION_NODOTS}.tar.bz2/download)
+set(BOOST_MD5 65a840e1a0b13a558ff19eeb2c4f0cbe)
+
+set(BLOSC_VERSION 1.7.1)
+set(BLOSC_URI https://github.com/Blosc/c-blosc/archive/v${BLOSC_VERSION}.zip)
+set(BLOSC_HASH ff5cc729a5a25934ef714217218eed26)
+
+set(PTHREADS_VERSION 2-9-1)
+set(PTHREADS_URI ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-${PTHREADS_VERSION}-release.tar.gz)
+set(PTHREADS_SHA512 9c06e85310766834370c3dceb83faafd397da18a32411ca7645c8eb6b9495fea54ca2872f4a3e8d83cb5fdc5dea7f3f0464be5bb9af3222a6534574a184bd551)
+
+set(ILMBASE_VERSION 2.2.0)
+set(ILMBASE_URI http://download.savannah.nongnu.org/releases/openexr/ilmbase-${ILMBASE_VERSION}.tar.gz)
+set(ILMBASE_HASH b540db502c5fa42078249f43d18a4652)
+
+set(OPENEXR_VERSION 2.2.0)
+set(OPENEXR_URI http://download.savannah.nongnu.org/releases/openexr/openexr-2.2.0.tar.gz)
+set(OPENEXR_HASH b64e931c82aa3790329c21418373db4e)
+
+set(FREETYPE_VERSION 263)
+set(FREETYPE_URI http://download.savannah.gnu.org/releases/freetype/ft${FREETYPE_VERSION}.zip)
+set(FREETYPE_HASH 0db2a43301572e5c2b4a0864f237aeeb)
+
+set(GLEW_VERSION 1.13.0)
+set(GLEW_URI http://prdownloads.sourceforge.net/glew/glew/${GLEW_VERSION}/glew-${GLEW_VERSION}.tgz)
+set(GLEW_HASH 7cbada3166d2aadfc4169c4283701066)
+
+set(FREEGLUT_VERSION 3.0.0)
+set(FREEGLUT_URI http://pilotfiber.dl.sourceforge.net/project/freeglut/freeglut/${FREEGLUT_VERSION}/freeglut-${FREEGLUT_VERSION}.tar.gz)
+set(FREEGLUT_HASH 90c3ca4dd9d51cf32276bc5344ec9754)
+
+set(HDF5_VERSION 1.8.17)
+set(HDF5_URI https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.8/hdf5-${HDF5_VERSION}/src/hdf5-${HDF5_VERSION}.tar.gz)
+set(HDF5_HASH 7d572f8f3b798a628b8245af0391a0ca)
+
+set(ALEMBIC_VERSION 1.7.1)
+set(ALEMBIC_URI https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.zip)
+set(ALEMBIC_MD5 cf7705055501d5ea0cb8256866496f79)
+
+## hash is for 3.1.2
+set(GLFW_GIT_UID 30306e54705c3adae9fe082c816a3be71963485c)
+set(GLFW_URI https://github.com/glfw/glfw/archive/${GLFW_GIT_UID}.zip)
+set(GLFW_HASH 20cacb1613da7eeb092f3ac4f6b2b3d0)
+
+#latest uid in git as of 2016-04-01
+set(CLEW_GIT_UID 277db43f6cafe8b27c6f1055f69dc67da4aeb299)
+set(CLEW_URI https://github.com/OpenCLWrangler/clew/archive/${CLEW_GIT_UID}.zip)
+set(CLEW_HASH 2c699d10ed78362e71f56fae2a4c5f98)
+
+#latest uid in git as of 2016-04-01
+set(CUEW_GIT_UID 1744972026de9cf27c8a7dc39cf39cd83d5f922f)
+set(CUEW_URI https://github.com/CudaWrangler/cuew/archive/${CUEW_GIT_UID}.zip)
+set(CUEW_HASH 86760d62978ebfd96cd93f5aa1abaf4a)
+
+set(OPENSUBDIV_VERSION v3_1_1)
+set(OPENSUBDIV_Hash 25a9a6a94136b0eb85ce69e9c8cb6ab3)
+set(OPENSUBDIV_URI https://github.com/PixarAnimationStudios/OpenSubdiv/archive/${OPENSUBDIV_VERSION}.zip)
+
+set(SDL_VERSION 2.0.4)
+set(SDL_URI https://www.libsdl.org/release/SDL2-${SDL_VERSION}.tar.gz)
+set(SDL_HASH 44fc4a023349933e7f5d7a582f7b886e)
+
+set(OPENCOLLADA_VERSION v1.6.51)
+set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
+set(OPENCOLLADA_HASH 23db5087faed4bc4cc1dfe456c0d4701)
+
+set(OPENCOLORIO_URI https://github.com/imageworks/OpenColorIO/archive/6de971097c7f552300f669ed69ca0b6cf5a70843.zip)
+set(OPENCOLORIO_HASH c9de0fd98f26ce6f2e08d617ca68b8e4)
+
+set(LLVM_VERSION 3.4.2)
+set(LLVM_URI http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.gz)
+set(LLVM_HASH a20669f75967440de949ac3b1bad439c)
+
+set(CLANG_URI http://llvm.org/releases/${LLVM_VERSION}/cfe-${LLVM_VERSION}.src.tar.gz)
+set(CLANG_HASH 87945973b7c73038871c5f849a818588)
+
+set(OPENIMAGEIO_VERSION 1.7.15)
+set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/Release-${OPENIMAGEIO_VERSION}.zip)
+set(OPENIMAGEIO_HASH_178 e156e3669af0e1373142ab5e8f13de66)
+set(OPENIMAGEIO_HASH_179 4121cb0e0433bda6a7ef32c8628a149f)
+set(OPENIMAGEIO_HASH_1713 42a662775b834161ba88c6abdb299360)
+set(OPENIMAGEIO_HASH_1715 e2ece0f62c013d64c478f82265988b0b)
+set(OPENIMAGEIO_HASH ${OPENIMAGEIO_HASH_1715})
+
+
+set(TIFF_VERSION 4.0.6)
+set(TIFF_URI http://download.osgeo.org/libtiff/tiff-${TIFF_VERSION}.tar.gz)
+set(TIFF_HASH d1d2e940dea0b5ad435f21f03d96dd72)
+
+set(FLEXBISON_VERSION 2.5.5)
+set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison//win_flex_bison-2.5.5.zip)
+set(FLEXBISON_HASH d87a3938194520d904013abef3df10ce)
+
+set(OSL_VERSION 1.7.5)
+set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.zip)
+set(OSL_HASH 6924dd5d453159e7b6eb106a08c358cf)
+
+set(PYTHON_VERSION 3.5.3)
+set(PYTHON_SHORT_VERSION 3.5)
+set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
+set(PYTHON_HASH 57d1f8bfbabf4f2500273fb0706e6f21)
+
+set(TBB_VERSION 44_20160128)
+set(TBB_URI https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb${TBB_VERSION}oss_src_0.tgz)
+set(TBB_HASH 9d8a4cdf43496f1b3f7c473a5248e5cc)
+
+set(OPENVDB_VERSION 3.1.0)
+set(OPENVDB_URI https://github.com/dreamworksanimation/openvdb/archive/v${OPENVDB_VERSION}.tar.gz)
+set(OPENVDB_HASH 30a7e9571a03ab7bcf1a39fb62aa436f)
+
+set(REQUESTS_VERSION v2.10.0)
+set(REQUESTS_URI https://github.com/kennethreitz/requests/archive/${REQUESTS_VERSION}.zip)
+set(REQUESTS_HASH 6ebefdf0210c7f0933f61501334e46c3)
+
+set(NUMPY_VERSION v1.10.1)
+set(NUMPY_SHORT_VERSION 1.10)
+set(NUMPY_URI https://pypi.python.org/packages/a5/2e/5412784108f5dc0f827fb460ccdeaa9d76286979fe5ddd070d526d168a59/numpy-1.10.1.zip)
+set(NUMPY_HASH 6f57c58bc5b28440fbeccd505da63d58)
+
+set(LAME_VERSION 3.99.5)
+set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.99/lame-${LAME_VERSION}.tar.gz)
+set(LAME_HASH 84835b313d4a8b68f5349816d33e07ce)
+
+set(OGG_VERSION 1.3.2)
+set(OGG_URI http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz)
+set(OGG_HASH e19ee34711d7af328cb26287f4137e70630e7261b17cbe3cd41011d73a654692)
+
+set(VORBIS_VERSION 1.3.5)
+set(VORBIS_URI http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERSION}.tar.gz)
+set(VORBIS_HASH 6efbcecdd3e5dfbf090341b485da9d176eb250d893e3eb378c428a2db38301ce)
+
+set(THEORA_VERSION 1.1.1)
+set(THEORA_URI http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.bz2)
+set(THEORA_HASH b6ae1ee2fa3d42ac489287d3ec34c5885730b1296f0801ae577a35193d3affbc)
+
+set(FLAC_VERSION 1.3.1)
+set(FLAC_URI http://downloads.xiph.org/releases/flac/flac-${FLAC_VERSION}.tar.xz)
+set(FLAC_HASH 4773c0099dba767d963fd92143263be338c48702172e8754b9bc5103efe1c56c)
+
+set(VPX_VERSION 1.5.0)
+set(VPX_URI http://storage.googleapis.com/downloads.webmproject.org/releases/webm/libvpx-${VPX_VERSION}.tar.bz2)
+set(VPX_HASH 306d67908625675f8e188d37a81fbfafdf5068b09d9aa52702b6fbe601c76797)
+
+set(ORC_VERSION 0.4.25)
+set(ORC_URI https://gstreamer.freedesktop.org/src/orc/orc-${ORC_VERSION}.tar.xz)
+set(ORC_HASH c1b1d54a58f26d483f0b3881538984789fe5d5460ab8fab74a1cacbd3d1c53d1)
+
+set(SCHROEDINGER_VERSION 1.0.11)
+set(SCHROEDINGER_URI https://download.videolan.org/contrib/schroedinger/schroedinger-${SCHROEDINGER_VERSION}.tar.gz)
+set(SCHROEDINGER_HASH 1e572a0735b92aca5746c4528f9bebd35aa0ccf8619b22fa2756137a8cc9f912)
+
+set(X264_URI http://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-20160401-2245-stable.tar.bz2)
+set(X264_HASH 1e9a7b835e80313aade53a9b6ff353e099de3856bf5f30a4d8dfc91281f786f5)
+
+set(XVIDCORE_VERSION 1.3.4)
+set(XVIDCORE_URI http://downloads.xvid.org/downloads/xvidcore-${XVIDCORE_VERSION}.tar.gz)
+set(XVIDCORE_HASH 4e9fd62728885855bc5007fe1be58df42e5e274497591fec37249e1052ae316f)
+
+set(OPENJPEG_VERSION 1.5)
+set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/version.${OPENJPEG_VERSION}.tar.gz)
+set(OPENJPEG_HASH 60662566595e02104c0f6d1052f8b1669624c646e62b6280d5fd5a66d4e92f8d)
+
+set(FAAD_VERSION 2-2.7)
+set(FAAD_URI http://downloads.sourceforge.net/faac/faad${FAAD_VERSION}.tar.bz2)
+set(FAAD_HASH 4c332fa23febc0e4648064685a3d4332)
+
+set(FFMPEG_VERSION 3.2.1)
+set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
+set(FFMPEG_HASH cede174178e61f882844f5870c35ce72)
+
+set(FFTW_VERSION 3.3.4)
+set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz)
+set(FFTW_HASH 2edab8c06b24feeb3b82bbb3ebf3e7b3)
+
+set(ICONV_VERSION 1.14)
+set(ICONV_URI http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz)
+set(ICONV_HASH e34509b1623cec449dfeb73d7ce9c6c6)
+
+set(LAPACK_VERSION 3.6.0)
+set(LAPACK_URI http://www.netlib.org/lapack/lapack-${LAPACK_VERSION}.tgz)
+set(LAPACK_HASH f2f6c67134e851fe189bb3ca1fbb5101)
+
+set(SNDFILE_VERSION 1.0.26)
+set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_VERSION}.tar.gz)
+set(SNDFILE_HASH ec810a0c60c08772a8a5552704b63393)
+
+#set(HIDAPI_VERSION 0.8.0-rc1)
+#set(HIDAPI_URI https://github.com/signal11/hidapi/archive/hidapi-${HIDAPI_VERSION}.tar.gz)
+#set(HIDAPI_HASH 069f9dd746edc37b6b6d0e3656f47199)
+
+set(HIDAPI_UID 89a6c75dc6f45ecabd4ddfbd2bf5ba6ad8ba38b5)
+set(HIDAPI_URI https://github.com/TheOnlyJoey/hidapi/archive/${HIDAPI_UID}.zip)
+set(HIDAPI_HASH b6e22f6b514f8bcf594989f20ffc46fb)
+
+set(WEBP_VERSION 0.5.1)
+set(WEBP_URI https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz)
+set(WEBP_HASH 3d7db92ebba5b4f679413d25c6040881)
+
+set(SPNAV_VERSION 0.2.3)
+set(SPNAV_URI http://downloads.sourceforge.net/project/spacenav/spacenav%20library%20%28SDK%29/libspnav%20${SPNAV_VERSION}/libspnav-${SPNAV_VERSION}.tar.gz)
+set(SPNAV_HASH 44d840540d53326d4a119c0f1aa7bf0a)
+
+set(JEMALLOC_VERSION 5.0.1)
+set(JEMALLOC_URI https://github.com/jemalloc/jemalloc/releases/download/${JEMALLOC_VERSION}/jemalloc-${JEMALLOC_VERSION}.tar.bz2)
+set(JEMALLOC_HASH 507f7b6b882d868730d644510491d18f)
+
+set(XML2_VERSION 2.9.4)
+set(XML2_URI ftp://xmlsoft.org/libxml2/libxml2-${XML2_VERSION}.tar.gz)
+set(XML2_HASH ae249165c173b1ff386ee8ad676815f5)
diff --git a/build_files/build_environment/cmake/vorbis.cmake b/build_files/build_environment/cmake/vorbis.cmake
new file mode 100644
index 00000000000..d16c7c6a1bc
--- /dev/null
+++ b/build_files/build_environment/cmake/vorbis.cmake
@@ -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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_vorbis
+ URL ${VORBIS_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${VORBIS_HASH}
+ PREFIX ${BUILD_DIR}/vorbis
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/vorbis/src/external_vorbis/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/vorbis
+ --disable-shared
+ --enable-static
+ --with-pic
+ --with-ogg=${LIBDIR}/ogg
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/vorbis/src/external_vorbis/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/vorbis/src/external_vorbis/ && make install
+ INSTALL_DIR ${LIBDIR}/vorbis
+)
+
+add_dependencies(external_vorbis external_ogg)
+
+if(MSVC)
+ set_target_properties(external_vorbis PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/vpx.cmake b/build_files/build_environment/cmake/vpx.cmake
new file mode 100644
index 00000000000..9d155be1c6c
--- /dev/null
+++ b/build_files/build_environment/cmake/vpx.cmake
@@ -0,0 +1,60 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+ set(VPX_EXTRA_FLAGS --target=x86_64-win64-gcc)
+ else()
+ set(VPX_EXTRA_FLAGS --target=x86-win32-gcc)
+ endif()
+else()
+ if(APPLE)
+ set(VPX_EXTRA_FLAGS --target=x86_64-darwin13-gcc)
+ else()
+ set(VPX_EXTRA_FLAGS --target=generic-gnu)
+ endif()
+endif()
+
+ExternalProject_Add(external_vpx
+ URL ${VPX_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${VPX_HASH}
+ PREFIX ${BUILD_DIR}/vpx
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} &&
+ cd ${BUILD_DIR}/vpx/src/external_vpx/ &&
+ ${CONFIGURE_COMMAND_NO_TARGET} --prefix=${LIBDIR}/vpx
+ --disable-shared
+ --enable-static
+ --disable-install-bins
+ --disable-install-srcs
+ --disable-sse4_1
+ --disable-sse3
+ --disable-ssse3
+ --disable-avx
+ --disable-avx2
+ --disable-unit-tests
+ --disable-examples
+ ${VPX_EXTRA_FLAGS}
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/vpx/src/external_vpx/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/vpx/src/external_vpx/ && make install
+ INSTALL_DIR ${LIBDIR}/vpx
+)
+
+if(MSVC)
+ set_target_properties(external_vpx PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/webp.cmake b/build_files/build_environment/cmake/webp.cmake
new file mode 100644
index 00000000000..0504988a088
--- /dev/null
+++ b/build_files/build_environment/cmake/webp.cmake
@@ -0,0 +1,50 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+# Note the utility apps may use png/tiff/gif system libraries, but the
+# library itself does not depend on them, so should give no problems.
+
+set(WEBP_EXTRA_ARGS
+ -DWEBP_HAVE_SSE2=ON
+ -DWEBP_HAVE_SSE41=OFF
+ -DWEBP_HAVE_AVX2=OFF
+)
+
+if(WIN32)
+ set(WEBP_BUILD_DIR ${BUILD_MODE}/)
+else()
+ set(WEBP_BUILD_DIR)
+endif()
+
+ExternalProject_Add(external_webp
+ URL ${WEBP_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${WEBP_HASH}
+ PREFIX ${BUILD_DIR}/webp
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/webp -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${WEBP_EXTRA_ARGS}
+ INSTALL_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp-build/${WEBP_BUILD_DIR}${LIBPREFIX}webp${LIBEXT} ${LIBDIR}/webp/lib/${LIBPREFIX}webp${LIBEXT} &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/decode.h ${LIBDIR}/webp/include/webp/decode.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/encode.h ${LIBDIR}/webp/include/webp/encode.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/demux.h ${LIBDIR}/webp/include/webp/demux.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/extras.h ${LIBDIR}/webp/include/webp/extras.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/format_constants.h ${LIBDIR}/webp/include/webp/format_constants.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/mux.h ${LIBDIR}/webp/include/webp/mux.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/mux_types.h ${LIBDIR}/webp/include/webp/mux_types.h &&
+ ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/types.h ${LIBDIR}/webp/include/webp/types.h
+ INSTALL_DIR ${LIBDIR}/webp
+)
diff --git a/build_files/build_environment/cmake/x264.cmake b/build_files/build_environment/cmake/x264.cmake
new file mode 100644
index 00000000000..64029ca1b5e
--- /dev/null
+++ b/build_files/build_environment/cmake/x264.cmake
@@ -0,0 +1,40 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ set(X264_EXTRA_ARGS --enable-win32thread --cross-prefix=${MINGW_HOST}- --host=${MINGW_HOST})
+endif()
+
+ExternalProject_Add(external_x264
+ URL ${X264_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${X264_HASH}
+ PREFIX ${BUILD_DIR}/x264
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/x264/src/external_x264/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/x264
+ --enable-static
+ --enable-pic
+ --disable-lavf
+ ${X264_EXTRA_ARGS}
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/x264/src/external_x264/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/x264/src/external_x264/ && make install
+ INSTALL_DIR ${LIBDIR}/x264
+)
+
+if(MSVC)
+ set_target_properties(external_x264 PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/xml2.cmake b/build_files/build_environment/cmake/xml2.cmake
new file mode 100644
index 00000000000..a8f87a67ad4
--- /dev/null
+++ b/build_files/build_environment/cmake/xml2.cmake
@@ -0,0 +1,36 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_xml2
+ URL ${XML2_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${XML2_HASH}
+ PREFIX ${BUILD_DIR}/xml2
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND}
+ --prefix=${LIBDIR}/xml2
+ --disable-shared
+ --enable-static
+ --with-pic
+ --with-python=no
+ --with-lzma=no
+ --with-zlib=no
+ --with-iconv=no
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install
+ INSTALL_DIR ${LIBDIR}/xml2
+)
diff --git a/build_files/build_environment/cmake/xvidcore.cmake b/build_files/build_environment/cmake/xvidcore.cmake
new file mode 100644
index 00000000000..a341275ea47
--- /dev/null
+++ b/build_files/build_environment/cmake/xvidcore.cmake
@@ -0,0 +1,44 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+if(WIN32)
+ set(XVIDCORE_EXTRA_ARGS --host=${MINGW_HOST})
+endif()
+
+ExternalProject_Add(external_xvidcore
+ URL ${XVIDCORE_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${XVIDCORE_HASH}
+ PREFIX ${BUILD_DIR}/xvidcore
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xvidcore/src/external_xvidcore/build/generic && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/xvidcore ${XVIDCORE_EXTRA_ARGS}
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xvidcore/src/external_xvidcore/build/generic && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} &&
+ ${CMAKE_COMMAND} -E remove ${LIBDIR}/xvidcore/lib/* && # clean because re-installing fails otherwise
+ cd ${BUILD_DIR}/xvidcore/src/external_xvidcore/build/generic && make install
+ INSTALL_DIR ${LIBDIR}/xvidcore
+)
+
+ExternalProject_Add_Step(external_xvidcore after_install
+ COMMAND ${CMAKE_COMMAND} -E rename ${LIBDIR}/xvidcore/lib/xvidcore.a ${LIBDIR}/xvidcore/lib/libxvidcore.a || true
+ COMMAND ${CMAKE_COMMAND} -E remove ${LIBDIR}/xvidcore/lib/xvidcore.dll.a
+ DEPENDEES install
+)
+
+if(MSVC)
+ set_target_properties(external_xvidcore PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/zlib.cmake b/build_files/build_environment/cmake/zlib.cmake
new file mode 100644
index 00000000000..3307cb1f167
--- /dev/null
+++ b/build_files/build_environment/cmake/zlib.cmake
@@ -0,0 +1,33 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_zlib
+ URL ${ZLIB_URI}
+ URL_HASH MD5=${ZLIB_HASH}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ PREFIX ${BUILD_DIR}/zlib
+ CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=${LIBDIR}/zlib ${DEFAULT_CMAKE_FLAGS}
+ INSTALL_DIR ${LIBDIR}/zlib
+)
+
+if(BUILD_MODE STREQUAL Debug)
+ ExternalProject_Add_Step(external_zlib after_install
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/zlib/lib/zlibstaticd${LIBEXT} ${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ DEPENDEES install
+ )
+endif()
diff --git a/build_files/build_environment/cmake/zlib_mingw.cmake b/build_files/build_environment/cmake/zlib_mingw.cmake
new file mode 100644
index 00000000000..13345f29ffa
--- /dev/null
+++ b/build_files/build_environment/cmake/zlib_mingw.cmake
@@ -0,0 +1,40 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_zlib_mingw
+ URL ${ZLIB_URI}
+ URL_HASH MD5=${ZLIB_HASH}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ PREFIX ${BUILD_DIR}/zlib_mingw
+ CONFIGURE_COMMAND echo .
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/zlib_mingw/src/external_zlib_mingw/ && make -f win32/makefile.gcc -j${MAKE_THREADS}
+ INSTALL_COMMAND echo .
+ INSTALL_DIR ${LIBDIR}/zlib_mingw
+)
+
+if(BUILD_MODE STREQUAL Release)
+ ExternalProject_Add_Step(external_zlib_mingw after_install
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/zlib_mingw/src/external_zlib_mingw/libz.a ${LIBDIR}/zlib/lib/z.lib
+ DEPENDEES install
+ )
+endif()
+
+if(MSVC)
+ set_target_properties(external_zlib_mingw PROPERTIES FOLDER Mingw)
+endif()
+
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index b996c234c67..1f25b37c979 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -26,7 +26,7 @@ ARGS=$( \
getopt \
-o s:i:t:h \
--long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,use-cxx11,\
-with-all,with-opencollada,\
+with-all,with-opencollada,with-jack,\
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,\
@@ -118,6 +118,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--with-opencollada
Build and install the OpenCOLLADA libraries.
+ --with-jack
+ Install the jack libraries.
+
--ver-ocio=<ver>
Force version of OCIO library.
@@ -322,8 +325,8 @@ OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
-OIIO_VERSION="1.7.13"
-OIIO_VERSION_MIN="1.7.13"
+OIIO_VERSION="1.7.15"
+OIIO_VERSION_MIN="1.7.15"
OIIO_VERSION_MAX="1.9.0" # UNKNOWN currently # Not supported by current OSL...
OIIO_FORCE_BUILD=false
OIIO_FORCE_REBUILD=false
@@ -366,7 +369,7 @@ ALEMBIC_FORCE_BUILD=false
ALEMBIC_FORCE_REBUILD=false
ALEMBIC_SKIP=false
-OPENCOLLADA_VERSION="1.6.47"
+OPENCOLLADA_VERSION="1.6.51"
OPENCOLLADA_FORCE_BUILD=false
OPENCOLLADA_FORCE_REBUILD=false
OPENCOLLADA_SKIP=false
@@ -507,6 +510,9 @@ while true; do
--with-opencollada)
WITH_OPENCOLLADA=true; shift; continue
;;
+ --with-jack)
+ WITH_JACK=true; shift; continue;
+ ;;
--ver-ocio)
OCIO_VERSION="$2"
OCIO_VERSION_MIN=$OCIO_VERSION
@@ -710,6 +716,9 @@ done
if [ "$WITH_ALL" = true -a "$OPENCOLLADA_SKIP" = false ]; then
WITH_OPENCOLLADA=true
fi
+if [ "$WITH_ALL" = true ]; then
+ WITH_JACK=true
+fi
WARNING "****WARNING****"
@@ -788,7 +797,7 @@ ALEMBIC_SOURCE=( "https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.
# ALEMBIC_SOURCE_REPO_BRANCH="master"
OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
-OPENCOLLADA_REPO_UID="22b1f4ff026881b4d2804d397730286ab7e3d090"
+OPENCOLLADA_REPO_UID="0c2cdc17c22cf42050e4d42154bed2176363549c"
OPENCOLLADA_REPO_BRANCH="master"
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
@@ -1590,7 +1599,7 @@ compile_OIIO() {
fi
# To be changed each time we make edits that would modify the compiled result!
- oiio_magic=16
+ oiio_magic=17
_init_oiio
# Clean install if needed!
@@ -1654,6 +1663,9 @@ compile_OIIO() {
INFO "ILMBASE_HOME=$INST/openexr"
fi
+ # ptex is only needed when nicholas bishop is ready
+ cmake_d="$cmake_d -D USE_PTEX=OFF"
+
# Optional tests and cmd tools
cmake_d="$cmake_d -D USE_QT=OFF"
cmake_d="$cmake_d -D USE_PYTHON=OFF"
@@ -1765,7 +1777,7 @@ compile_LLVM() {
cd $_src
# XXX Ugly patching hack!
- patch -p1 -i "$SCRIPT_DIR/install_deps_patches/llvm.patch"
+ patch -p1 -i "$SCRIPT_DIR/patches/install_deps_llvm.diff"
cd $CWD
@@ -1871,7 +1883,7 @@ compile_OSL() {
git reset --hard
# XXX Ugly patching hack!
- patch -p1 -i "$SCRIPT_DIR/install_deps_patches/osl.patch"
+ patch -p1 -i "$SCRIPT_DIR/patches/install_deps_osl.diff"
fi
# Always refresh the whole build!
@@ -2652,7 +2664,7 @@ install_DEB() {
PRINT ""
fi
- if [ "$WITH_ALL" = true ]; then
+ if [ "$WITH_JACK" = true ]; then
_packages="$_packages libspnav-dev"
# Only install jack if jack2 is not already installed!
JACK="libjack-dev"
@@ -3189,7 +3201,7 @@ install_RPM() {
if [ "$RPM" = "FEDORA" -o "$RPM" = "RHEL" ]; then
_packages="$_packages freetype-devel tbb-devel"
- if [ "$WITH_ALL" = true ]; then
+ if [ "$WITH_JACK" = true ]; then
_packages="$_packages jack-audio-connection-kit-devel"
fi
@@ -3663,7 +3675,11 @@ install_ARCH() {
THEORA_USE=true
if [ "$WITH_ALL" = true ]; then
- _packages="$_packages jack libspnav"
+ _packages="$_packages libspnav"
+ fi
+
+ if [ "$WITH_JACK" = true ]; then
+ _packages="$_packages jack"
fi
PRINT ""
@@ -4325,6 +4341,14 @@ print_info() {
_buildargs="$_buildargs $_1"
fi
+ if [ "$WITH_JACK" = true ]; then
+ _1="-D WITH_JACK=ON"
+ _2="-D WITH_JACK_DYNLOAD=ON"
+ PRINT " $_1"
+ PRINT " $_2"
+ _buildargs="$_buildargs $_1 $_2"
+ fi
+
if [ "$ALEMBIC_SKIP" = false ]; then
_1="-D WITH_ALEMBIC=ON"
PRINT " $_1"
diff --git a/build_files/build_environment/patches/alembic.diff b/build_files/build_environment/patches/alembic.diff
new file mode 100644
index 00000000000..f869858efb2
--- /dev/null
+++ b/build_files/build_environment/patches/alembic.diff
@@ -0,0 +1,35 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 3e09c57..26565ae 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -116,7 +116,7 @@ IF (NOT ${ALEMBIC_LIB_USES_TR1} AND NOT ${ALEMBIC_LIB_USES_BOOST})
+ INCLUDE(CheckCXXCompilerFlag)
+ CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
+ CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
+- IF (COMPILER_SUPPORTS_CXX1X)
++ IF (COMPILER_SUPPORTS_CXX11)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ ELSEIF (COMPILER_SUPPORTS_CXX0X)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+--- a/lib/Alembic/AbcCoreOgawa/StreamManager.cpp
++++ b/lib/Alembic/AbcCoreOgawa/StreamManager.cpp
+@@ -47,7 +47,18 @@
+ #define COMPARE_EXCHANGE( V, COMP, EXCH ) V.compare_exchange_weak( COMP, EXCH, std::memory_order_seq_cst, std::memory_order_seq_cst )
+ // Windows
+ #elif defined( _MSC_VER )
+-#define COMPARE_EXCHANGE( V, COMP, EXCH ) InterlockedCompareExhange64( &V, EXCH, COMP ) == COMP
++#define COMPARE_EXCHANGE( V, COMP, EXCH ) InterlockedCompareExchange64( &V, EXCH, COMP ) == COMP
++int ffsll(long long value)
++{
++ if (!value)
++ return 0;
++
++ for (int bit = 0; bit < 63; bit++)
++ {
++ if (value & (1 << bit))
++ return bit + 1;
++ }
++}
+ // gcc 4.8 and above not using C++11
+ #elif defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8
+ #define COMPARE_EXCHANGE( V, COMP, EXCH ) __atomic_compare_exchange_n( &V, &COMP, EXCH, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST )
diff --git a/build_files/build_environment/patches/blosc.diff b/build_files/build_environment/patches/blosc.diff
new file mode 100644
index 00000000000..3bd6ef28144
--- /dev/null
+++ b/build_files/build_environment/patches/blosc.diff
@@ -0,0 +1,33 @@
+diff -Naur src/blosc/CMakeLists.txt external_blosc/blosc/CMakeLists.txt
+--- src/blosc/CMakeLists.txt 2016-02-03 10:26:28 -0700
++++ external_blosc/blosc/CMakeLists.txt 2017-03-03 09:03:31 -0700
+@@ -61,6 +61,8 @@
+ set(SOURCES ${SOURCES} win32/pthread.c)
+ else(NOT Threads_FOUND)
+ set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
++ set(LIBS ${LIBS} ${PTHREAD_LIBS})
++ include_directories( ${PTHREAD_INCLUDE_DIR} )
+ endif(NOT Threads_FOUND)
+ else(WIN32)
+ find_package(Threads REQUIRED)
+diff -Naur src/blosc/blosc.c external_blosc/blosc/blosc.c
+--- src/blosc/blosc.c 2016-02-03 10:26:28 -0700
++++ external_blosc/blosc/blosc.c 2017-03-03 09:01:50 -0700
+@@ -49,12 +49,12 @@
+ #include <inttypes.h>
+ #endif /* _WIN32 */
+
+-#if defined(_WIN32) && !defined(__GNUC__)
+- #include "win32/pthread.h"
+- #include "win32/pthread.c"
+-#else
++//#if defined(_WIN32) && !defined(__GNUC__)
++// #include "win32/pthread.h"
++ //#include "win32/pthread.c"
++//#else
+ #include <pthread.h>
+-#endif
++//#endif
+
+ /* If C11 is supported, use it's built-in aligned allocation. */
+ #if __STDC_VERSION__ >= 201112L
diff --git a/build_files/build_environment/patches/clang.diff b/build_files/build_environment/patches/clang.diff
new file mode 100644
index 00000000000..724e92f8163
--- /dev/null
+++ b/build_files/build_environment/patches/clang.diff
@@ -0,0 +1,127 @@
+--- cfe/trunk/lib/Serialization/ASTWriter.cpp
++++ cfe/trunk/lib/Serialization/ASTWriter.cpp
+@@ -56,14 +56,14 @@
+ using namespace clang::serialization;
+
+ template <typename T, typename Allocator>
+-static StringRef bytes(const std::vector<T, Allocator> &v) {
++static StringRef data(const std::vector<T, Allocator> &v) {
+ if (v.empty()) return StringRef();
+ return StringRef(reinterpret_cast<const char*>(&v[0]),
+ sizeof(T) * v.size());
+ }
+
+ template <typename T>
+-static StringRef bytes(const SmallVectorImpl<T> &v) {
++static StringRef data(const SmallVectorImpl<T> &v) {
+ return StringRef(reinterpret_cast<const char*>(v.data()),
+ sizeof(T) * v.size());
+ }
+@@ -1385,7 +1385,7 @@
+ Record.push_back(INPUT_FILE_OFFSETS);
+ Record.push_back(InputFileOffsets.size());
+ Record.push_back(UserFilesNum);
+- Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets));
++ Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, data(InputFileOffsets));
+ }
+
+ //===----------------------------------------------------------------------===//
+@@ -1771,7 +1771,7 @@
+ Record.push_back(SOURCE_LOCATION_OFFSETS);
+ Record.push_back(SLocEntryOffsets.size());
+ Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy
+- Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, bytes(SLocEntryOffsets));
++ Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets));
+
+ // Write the source location entry preloads array, telling the AST
+ // reader which source locations entries it should load eagerly.
+@@ -2087,7 +2087,7 @@
+ Record.push_back(MacroOffsets.size());
+ Record.push_back(FirstMacroID - NUM_PREDEF_MACRO_IDS);
+ Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record,
+- bytes(MacroOffsets));
++ data(MacroOffsets));
+ }
+
+ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
+@@ -2185,7 +2185,7 @@
+ Record.push_back(PPD_ENTITIES_OFFSETS);
+ Record.push_back(FirstPreprocessorEntityID - NUM_PREDEF_PP_ENTITY_IDS);
+ Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
+- bytes(PreprocessedEntityOffsets));
++ data(PreprocessedEntityOffsets));
+ }
+ }
+
+@@ -2548,7 +2548,7 @@
+ Record.push_back(CXX_BASE_SPECIFIER_OFFSETS);
+ Record.push_back(CXXBaseSpecifiersOffsets.size());
+ Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record,
+- bytes(CXXBaseSpecifiersOffsets));
++ data(CXXBaseSpecifiersOffsets));
+ }
+
+ //===----------------------------------------------------------------------===//
+@@ -2623,7 +2623,7 @@
+ Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D)));
+
+ ++NumLexicalDeclContexts;
+- Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, bytes(Decls));
++ Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls));
+ return Offset;
+ }
+
+@@ -2642,7 +2642,7 @@
+ Record.push_back(TYPE_OFFSET);
+ Record.push_back(TypeOffsets.size());
+ Record.push_back(FirstTypeID - NUM_PREDEF_TYPE_IDS);
+- Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets));
++ Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, data(TypeOffsets));
+
+ // Write the declaration offsets array
+ Abbrev = new BitCodeAbbrev();
+@@ -2655,7 +2655,7 @@
+ Record.push_back(DECL_OFFSET);
+ Record.push_back(DeclOffsets.size());
+ Record.push_back(FirstDeclID - NUM_PREDEF_DECL_IDS);
+- Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets));
++ Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets));
+ }
+
+ void ASTWriter::WriteFileDeclIDsMap() {
+@@ -2680,7 +2680,7 @@
+ unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+ Record.push_back(FILE_SORTED_DECLS);
+ Record.push_back(FileSortedIDs.size());
+- Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileSortedIDs));
++ Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs));
+ }
+
+ void ASTWriter::WriteComments() {
+@@ -2893,7 +2893,7 @@
+ Record.push_back(SelectorOffsets.size());
+ Record.push_back(FirstSelectorID - NUM_PREDEF_SELECTOR_IDS);
+ Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
+- bytes(SelectorOffsets));
++ data(SelectorOffsets));
+ }
+ }
+
+@@ -3253,7 +3253,7 @@
+ Record.push_back(IdentifierOffsets.size());
+ Record.push_back(FirstIdentID - NUM_PREDEF_IDENT_IDS);
+ Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
+- bytes(IdentifierOffsets));
++ data(IdentifierOffsets));
+ }
+
+ //===----------------------------------------------------------------------===//
+@@ -4046,7 +4046,7 @@
+ Record.clear();
+ Record.push_back(TU_UPDATE_LEXICAL);
+ Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
+- bytes(NewGlobalDecls));
++ data(NewGlobalDecls));
+
+ // And a visible updates block for the translation unit.
+ Abv = new llvm::BitCodeAbbrev();
diff --git a/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake b/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake
new file mode 100644
index 00000000000..d490b7a2ff3
--- /dev/null
+++ b/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake
@@ -0,0 +1,73 @@
+# - Find BLOSC library
+# Find the native BLOSC includes and library
+# This module defines
+# BLOSC_INCLUDE_DIRS, where to find blosc.h, Set when
+# BLOSC is found.
+# BLOSC_LIBRARIES, libraries to link against to use BLOSC.
+# BLOSC_ROOT_DIR, The base directory to search for BLOSC.
+# This can also be an environment variable.
+# BLOSC_FOUND, If false, do not try to use BLOSC.
+#
+# also defined, but not for general use are
+# BLOSC_LIBRARY, where to find the BLOSC library.
+
+#=============================================================================
+# 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 BLOSC_ROOT_DIR was defined in the environment, use it.
+IF(NOT BLOSC_ROOT_DIR AND NOT $ENV{BLOSC_ROOT_DIR} STREQUAL "")
+ SET(BLOSC_ROOT_DIR $ENV{BLOSC_ROOT_DIR})
+ENDIF()
+
+SET(_blosc_SEARCH_DIRS
+ ${BLOSC_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/lib/blosc
+)
+
+FIND_PATH(BLOSC_INCLUDE_DIR
+ NAMES
+ blosc.h
+ HINTS
+ ${_blosc_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(BLOSC_LIBRARY
+ NAMES
+ blosc
+ HINTS
+ ${_blosc_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+)
+
+# handle the QUIETLY and REQUIRED arguments and set BLOSC_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(BLOSC DEFAULT_MSG
+ BLOSC_LIBRARY BLOSC_INCLUDE_DIR)
+
+IF(BLOSC_FOUND)
+ SET(BLOSC_LIBRARIES ${BLOSC_LIBRARY})
+ SET(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIR})
+ELSE()
+ SET(BLOSC_FOUND FALSE)
+ENDIF()
+
+MARK_AS_ADVANCED(
+ BLOSC_INCLUDE_DIR
+ BLOSC_LIBRARY
+)
diff --git a/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake b/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake
new file mode 100644
index 00000000000..3dd480356af
--- /dev/null
+++ b/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake
@@ -0,0 +1,73 @@
+# - Find CPPUNIT library
+# Find the native CPPUNIT includes and library
+# This module defines
+# CPPUNIT_INCLUDE_DIRS, where to find cppunit.h, Set when
+# CPPUNIT is found.
+# CPPUNIT_LIBRARIES, libraries to link against to use CPPUNIT.
+# CPPUNIT_ROOT_DIR, The base directory to search for CPPUNIT.
+# This can also be an environment variable.
+# CPPUNIT_FOUND, If false, do not try to use CPPUNIT.
+#
+# also defined, but not for general use are
+# CPPUNIT_LIBRARY, where to find the CPPUNIT library.
+
+#=============================================================================
+# 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 CPPUNIT_ROOT_DIR was defined in the environment, use it.
+IF(NOT CPPUNIT_ROOT_DIR AND NOT $ENV{CPPUNIT_ROOT_DIR} STREQUAL "")
+ SET(CPPUNIT_ROOT_DIR $ENV{CPPUNIT_ROOT_DIR})
+ENDIF()
+
+SET(_cppunit_SEARCH_DIRS
+ ${CPPUNIT_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/lib/cppunit
+)
+
+FIND_PATH(CPPUNIT_INCLUDE_DIR
+ NAMES
+ cppunit/Test.h
+ HINTS
+ ${_cppunit_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(CPPUNIT_LIBRARY
+ NAMES
+ cppunit
+ HINTS
+ ${_cppunit_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+)
+
+# handle the QUIETLY and REQUIRED arguments and set CPPUNIT_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(CPPUNIT DEFAULT_MSG
+ CPPUNIT_LIBRARY CPPUNIT_INCLUDE_DIR)
+
+IF(CPPUNIT_FOUND)
+ SET(CPPUNIT_LIBRARIES ${CPPUNIT_LIBRARY})
+ SET(CPPUNIT_INCLUDE_DIRS ${CPPUNIT_INCLUDE_DIR})
+ELSE()
+ SET(CPPUNIT_FOUND FALSE)
+ENDIF()
+
+MARK_AS_ADVANCED(
+ CPPUNIT_INCLUDE_DIR
+ CPPUNIT_LIBRARY
+)
diff --git a/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake b/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake
new file mode 100644
index 00000000000..f1a45228128
--- /dev/null
+++ b/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake
@@ -0,0 +1,260 @@
+# Module to find IlmBase
+#
+# This module will first look into the directories defined by the variables:
+# - ILMBASE_HOME, ILMBASE_VERSION, ILMBASE_LIB_AREA
+#
+# It also supports non-standard names for the library components.
+#
+# To use a custom IlmBase:
+# - Set the variable ILMBASE_CUSTOM to True
+# - Set the variable ILMBASE_CUSTOM_LIBRARIES to a list of the libraries to
+# use, e.g. "SpiImath SpiHalf SpiIlmThread SpiIex"
+# - Optionally set the variable ILMBASE_CUSTOM_INCLUDE_DIR to any
+# particularly weird place that the OpenEXR/*.h files may be found
+# - Optionally set the variable ILMBASE_CUSTOM_LIB_DIR to any
+# particularly weird place that the libraries files may be found
+#
+# This module defines the following variables:
+#
+# ILMBASE_INCLUDE_DIR - where to find half.h, IlmBaseConfig.h, etc.
+# ILMBASE_LIBRARIES - list of libraries to link against when using IlmBase.
+# ILMBASE_FOUND - True if IlmBase was found.
+
+# Other standarnd issue macros
+include (FindPackageHandleStandardArgs)
+include (FindPackageMessage)
+include (SelectLibraryConfigurations)
+
+
+if( ILMBASE_USE_STATIC_LIBS )
+ set( _ilmbase_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ if(WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ else()
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
+ endif()
+endif()
+
+# Macro to assemble a helper state variable
+macro (SET_STATE_VAR varname)
+ set (tmp_ilmbaselibs ${ILMBASE_CUSTOM_LIBRARIES})
+ separate_arguments (tmp_ilmbaselibs)
+ set (tmp_lst
+ ${ILMBASE_CUSTOM} | ${tmp_ilmbaselibs} |
+ ${ILMBASE_HOME} | ${ILMBASE_VERSION} | ${ILMBASE_LIB_AREA}
+ )
+ set (${varname} "${tmp_lst}")
+ unset (tmp_ilmbaselibs)
+ unset (tmp_lst)
+endmacro ()
+
+# To enforce that find_* functions do not use inadvertently existing versions
+if (ILMBASE_CUSTOM)
+ set (ILMBASE_FIND_OPTIONS "NO_DEFAULT_PATH")
+endif ()
+
+# Macro to search for an include directory
+macro (PREFIX_FIND_INCLUDE_DIR prefix includefile libpath_var)
+ string (TOUPPER ${prefix}_INCLUDE_DIR tmp_varname)
+ find_path(${tmp_varname} ${includefile}
+ HINTS ${${libpath_var}}
+ PATH_SUFFIXES include
+ ${ILMBASE_FIND_OPTIONS}
+ )
+ if (${tmp_varname})
+ mark_as_advanced (${tmp_varname})
+ endif ()
+ unset (tmp_varname)
+endmacro ()
+
+
+# Macro to search for the given library and adds the cached
+# variable names to the specified list
+macro (PREFIX_FIND_LIB prefix libname libpath_var liblist_var cachelist_var)
+ string (TOUPPER ${prefix}_${libname} tmp_prefix)
+ # Handle new library names for OpenEXR 2.1 build via cmake
+ string(REPLACE "." "_" _ILMBASE_VERSION ${ILMBASE_VERSION})
+ string(SUBSTRING ${_ILMBASE_VERSION} 0 3 _ILMBASE_VERSION )
+
+ find_library(${tmp_prefix}_LIBRARY_RELEASE
+ NAMES ${libname} ${libname}-${_ILMBASE_VERSION}
+ HINTS ${${libpath_var}}
+ PATH_SUFFIXES lib
+ ${ILMBASE_FIND_OPTIONS}
+ )
+ find_library(${tmp_prefix}_LIBRARY_DEBUG
+ NAMES ${libname}d ${libname}_d ${libname}debug ${libname}_debug
+ HINTS ${${libpath_var}}
+ PATH_SUFFIXES lib
+ ${ILMBASE_FIND_OPTIONS}
+ )
+ # Properly define ${tmp_prefix}_LIBRARY (cached) and ${tmp_prefix}_LIBRARIES
+ select_library_configurations (${tmp_prefix})
+ list (APPEND ${liblist_var} ${tmp_prefix}_LIBRARIES)
+
+ # Add to the list of variables which should be reset
+ list (APPEND ${cachelist_var}
+ ${tmp_prefix}_LIBRARY
+ ${tmp_prefix}_LIBRARY_RELEASE
+ ${tmp_prefix}_LIBRARY_DEBUG)
+ mark_as_advanced (
+ ${tmp_prefix}_LIBRARY
+ ${tmp_prefix}_LIBRARY_RELEASE
+ ${tmp_prefix}_LIBRARY_DEBUG)
+ unset (tmp_prefix)
+endmacro ()
+
+
+# Encode the current state of the external variables into a string
+SET_STATE_VAR (ILMBASE_CURRENT_STATE)
+
+# If the state has changed, clear the cached variables
+if (ILMBASE_CACHED_STATE AND
+ NOT ILMBASE_CACHED_STATE STREQUAL ILMBASE_CURRENT_STATE)
+
+ foreach (libvar ${ILMBASE_CACHED_VARS})
+ unset (${libvar} CACHE)
+ endforeach ()
+endif ()
+
+
+# Generic search paths
+set (IlmBase_generic_include_paths
+ ${ILMBASE_CUSTOM_INCLUDE_DIR}
+ /usr/include
+ /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}
+ /usr/local/include
+ /sw/include
+ /opt/local/include)
+set (IlmBase_generic_library_paths
+ ${ILMBASE_CUSTOM_LIB_DIR}
+ /usr/lib
+ /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
+ /usr/local/lib
+ /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE}
+ /sw/lib
+ /opt/local/lib)
+
+# Search paths for the IlmBase files
+if (ILMBASE_HOME)
+ if (ILMBASE_VERSION)
+ set (IlmBase_include_paths
+ ${ILMBASE_HOME}/ilmbase-${ILMBASE_VERSION}/include
+ ${ILMBASE_HOME}/include/ilmbase-${ILMBASE_VERSION})
+ set (IlmBase_library_paths
+ ${ILMBASE_HOME}/ilmbase-${ILMBASE_VERSION}/lib
+ ${ILMBASE_HOME}/lib/ilmbase-${ILMBASE_VERSION})
+ endif()
+ list (APPEND IlmBase_include_paths ${ILMBASE_HOME}/include)
+ set (IlmBase_library_paths
+ ${ILMBASE_HOME}/lib
+ ${ILMBASE_HOME}/lib64
+ ${ILMBASE_LIB_AREA}
+ ${IlmBase_library_paths})
+endif ()
+list (APPEND IlmBase_include_paths ${IlmBase_generic_include_paths})
+list (APPEND IlmBase_library_paths ${IlmBase_generic_library_paths})
+
+# Locate the header files
+PREFIX_FIND_INCLUDE_DIR (IlmBase
+ OpenEXR/IlmBaseConfig.h IlmBase_include_paths)
+
+if (ILMBASE_INCLUDE_DIR)
+ # Get the version from config file, if not already set.
+ if (NOT ILMBASE_VERSION)
+ FILE(STRINGS "${ILMBASE_INCLUDE_DIR}/OpenEXR/IlmBaseConfig.h" ILMBASE_BUILD_SPECIFICATION
+ REGEX "^[ \t]*#define[ \t]+ILMBASE_VERSION_STRING[ \t]+\"[.0-9]+\".*$")
+
+ if(ILMBASE_BUILD_SPECIFICATION)
+ if (NOT IlmBase_FIND_QUIETLY)
+ message(STATUS "${ILMBASE_BUILD_SPECIFICATION}")
+ endif ()
+ string(REGEX REPLACE ".*#define[ \t]+ILMBASE_VERSION_STRING[ \t]+\"([.0-9]+)\".*"
+ "\\1" XYZ ${ILMBASE_BUILD_SPECIFICATION})
+ set("ILMBASE_VERSION" ${XYZ} CACHE STRING "Version of ILMBase lib")
+ else()
+ # Old versions (before 2.0?) do not have any version string, just assuming 2.0 should be fine though.
+ message(WARNING "Could not determine ILMBase library version, assuming 2.0.")
+ set("ILMBASE_VERSION" "2.0" CACHE STRING "Version of ILMBase lib")
+ endif()
+ endif()
+endif ()
+
+
+if (ILMBASE_CUSTOM)
+ if (NOT ILMBASE_CUSTOM_LIBRARIES)
+ message (FATAL_ERROR "Custom IlmBase libraries requested but ILMBASE_CUSTOM_LIBRARIES is not set.")
+ endif()
+ set (IlmBase_Libraries ${ILMBASE_CUSTOM_LIBRARIES})
+ separate_arguments(IlmBase_Libraries)
+else ()
+#elseif (${ILMBASE_VERSION} VERSION_LESS "2.1")
+ set (IlmBase_Libraries Half Iex Imath IlmThread)
+#else ()
+# string(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _ilmbase_libs_ver ${ILMBASE_VERSION})
+# set (IlmBase_Libraries Half Iex-${_ilmbase_libs_ver} Imath-${_ilmbase_libs_ver} IlmThread-${_ilmbase_libs_ver})
+endif ()
+
+
+# Locate the IlmBase libraries
+set (IlmBase_libvars "")
+set (IlmBase_cachevars "")
+foreach (ilmbase_lib ${IlmBase_Libraries})
+ PREFIX_FIND_LIB (IlmBase ${ilmbase_lib}
+ IlmBase_library_paths IlmBase_libvars IlmBase_cachevars)
+endforeach ()
+# Create the list of variables that might need to be cleared
+set (ILMBASE_CACHED_VARS
+ ILMBASE_INCLUDE_DIR ${IlmBase_cachevars}
+ CACHE INTERNAL "Variables set by FindIlmBase.cmake" FORCE)
+
+# Store the current state so that variables might be cleared if required
+set (ILMBASE_CACHED_STATE ${ILMBASE_CURRENT_STATE}
+ CACHE INTERNAL "State last seen by FindIlmBase.cmake" FORCE)
+
+# Link with pthreads if required
+if (NOT WIN32 AND EXISTS ${ILMBASE_INCLUDE_DIR}/OpenEXR/IlmBaseConfig.h)
+ file (STRINGS ${ILMBASE_INCLUDE_DIR}/OpenEXR/IlmBaseConfig.h
+ ILMBASE_HAVE_PTHREAD
+ REGEX "^[ \\t]*#define[ \\t]+HAVE_PTHREAD[ \\t]1[ \\t]*\$"
+ )
+ if (ILMBASE_HAVE_PTHREAD)
+ find_package (Threads)
+ if (CMAKE_USE_PTHREADS_INIT)
+ set (ILMBASE_PTHREADS ${CMAKE_THREAD_LIBS_INIT})
+ endif ()
+ endif ()
+endif ()
+
+# Use the standard function to handle ILMBASE_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS (IlmBase DEFAULT_MSG
+ ILMBASE_INCLUDE_DIR ${IlmBase_libvars})
+
+if (ILMBASE_FOUND)
+ set (ILMBASE_LIBRARIES "")
+ foreach (tmplib ${IlmBase_libvars})
+ list (APPEND ILMBASE_LIBRARIES ${${tmplib}})
+ endforeach ()
+ list (APPEND ILMBASE_LIBRARIES ${ILMBASE_PTHREADS})
+ if (NOT IlmBase_FIND_QUIETLY)
+ FIND_PACKAGE_MESSAGE (ILMBASE
+ "Found IlmBase: ${ILMBASE_LIBRARIES}"
+ "[${ILMBASE_INCLUDE_DIR}][${ILMBASE_LIBRARIES}][${ILMBASE_CURRENT_STATE}]"
+ )
+ endif ()
+endif ()
+
+# Restore the original find library ordering
+if( ILMBASE_USE_STATIC_LIBS )
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${_ilmbase_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
+endif()
+
+# Unset the helper variables to avoid pollution
+unset (ILMBASE_CURRENT_STATE)
+unset (IlmBase_include_paths)
+unset (IlmBase_library_paths)
+unset (IlmBase_generic_include_paths)
+unset (IlmBase_generic_library_paths)
+unset (IlmBase_libvars)
+unset (IlmBase_cachevars)
+unset (ILMBASE_PTHREADS)
diff --git a/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake b/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake
new file mode 100644
index 00000000000..2002419cc75
--- /dev/null
+++ b/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake
@@ -0,0 +1,73 @@
+# - Find LOGC4PLUS library
+# Find the native LOGC4PLUS includes and library
+# This module defines
+# LOGC4PLUS_INCLUDE_DIRS, where to find logc4plus.h, Set when
+# LOGC4PLUS is found.
+# LOGC4PLUS_LIBRARIES, libraries to link against to use LOGC4PLUS.
+# LOGC4PLUS_ROOT_DIR, The base directory to search for LOGC4PLUS.
+# This can also be an environment variable.
+# LOGC4PLUS_FOUND, If false, do not try to use LOGC4PLUS.
+#
+# also defined, but not for general use are
+# LOGC4PLUS_LIBRARY, where to find the LOGC4PLUS library.
+
+#=============================================================================
+# 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 LOGC4PLUS_ROOT_DIR was defined in the environment, use it.
+IF(NOT LOGC4PLUS_ROOT_DIR AND NOT $ENV{LOGC4PLUS_ROOT_DIR} STREQUAL "")
+ SET(LOGC4PLUS_ROOT_DIR $ENV{LOGC4PLUS_ROOT_DIR})
+ENDIF()
+
+SET(_logc4plus_SEARCH_DIRS
+ ${LOGC4PLUS_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/lib/logc4plus
+)
+
+FIND_PATH(LOGC4PLUS_INCLUDE_DIR
+ NAMES
+ logc4plus.h
+ HINTS
+ ${_logc4plus_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(LOGC4PLUS_LIBRARY
+ NAMES
+ logc4plus
+ HINTS
+ ${_logc4plus_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+
+# handle the QUIETLY and REQUIRED arguments and set LOGC4PLUS_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LOGC4PLUS DEFAULT_MSG
+ LOGC4PLUS_LIBRARY LOGC4PLUS_INCLUDE_DIR)
+
+IF(LOGC4PLUS_FOUND)
+ SET(LOGC4PLUS_LIBRARIES ${LOGC4PLUS_LIBRARY})
+ SET(LOGC4PLUS_INCLUDE_DIRS ${LOGC4PLUS_INCLUDE_DIR})
+ELSE()
+ SET(LOGC4PLUS_LOGC4PLUS_FOUND FALSE)
+ENDIF()
+
+MARK_AS_ADVANCED(
+ LOGC4PLUS_INCLUDE_DIR
+ LOGC4PLUS_LIBRARY
+)
diff --git a/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake b/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake
new file mode 100644
index 00000000000..08d872445d7
--- /dev/null
+++ b/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake
@@ -0,0 +1,244 @@
+# Module to find OpenEXR.
+#
+# This module will first look into the directories defined by the variables:
+# - OPENEXR_HOME, OPENEXR_VERSION, OPENEXR_LIB_AREA
+#
+# It also supports non-standard names for the library components.
+#
+# To use a custom OpenEXR
+# - Set the variable OPENEXR_CUSTOM to True
+# - Set the variable OPENEXR_CUSTOM_LIBRARY to the name of the library to
+# use, e.g. "SpiIlmImf"
+# - Optionally set the variable OPENEXR_CUSTOM_INCLUDE_DIR to any
+# particularly weird place that the OpenEXR/*.h files may be found
+# - Optionally set the variable OPENEXR_CUSTOM_LIB_DIR to any
+# particularly weird place that the libraries files may be found
+#
+# This module defines the following variables:
+#
+# OPENEXR_INCLUDE_DIR - where to find ImfRgbaFile.h, OpenEXRConfig, etc.
+# OPENEXR_LIBRARIES - list of libraries to link against when using OpenEXR.
+# This list does NOT include the IlmBase libraries.
+# These are defined by the FindIlmBase module.
+# OPENEXR_FOUND - True if OpenEXR was found.
+
+# Other standarnd issue macros
+include (SelectLibraryConfigurations)
+include (FindPackageHandleStandardArgs)
+include (FindPackageMessage)
+
+if( OPENEXR_USE_STATIC_LIBS )
+ set( _openexr_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ if(WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ else()
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
+ endif()
+endif()
+
+# Macro to assemble a helper state variable
+macro (SET_STATE_VAR varname)
+ set (tmp_lst
+ ${OPENEXR_CUSTOM} | ${OPENEXR_CUSTOM_LIBRARY} |
+ ${OPENEXR_HOME} | ${OPENEXR_VERSION} | ${OPENEXR_LIB_AREA}
+ )
+ set (${varname} "${tmp_lst}")
+ unset (tmp_lst)
+endmacro ()
+
+# To enforce that find_* functions do not use inadvertently existing versions
+if (OPENEXR_CUSTOM)
+ set (OPENEXR_FIND_OPTIONS "NO_DEFAULT_PATH")
+endif ()
+
+# Macro to search for an include directory
+macro (PREFIX_FIND_INCLUDE_DIR prefix includefile libpath_var)
+ string (TOUPPER ${prefix}_INCLUDE_DIR tmp_varname)
+ find_path(${tmp_varname} ${includefile}
+ HINTS ${${libpath_var}}
+ PATH_SUFFIXES include
+ ${OPENEXR_FIND_OPTIONS}
+ )
+ if (${tmp_varname})
+ mark_as_advanced (${tmp_varname})
+ endif ()
+ unset (tmp_varname)
+endmacro ()
+
+
+# Macro to search for the given library and adds the cached
+# variable names to the specified list
+macro (PREFIX_FIND_LIB prefix libname libpath_var liblist_var cachelist_var)
+ string (TOUPPER ${prefix}_${libname} tmp_prefix)
+ # Handle new library names for OpenEXR 2.1 build via cmake
+ string(REPLACE "." "_" _ILMBASE_VERSION ${ILMBASE_VERSION})
+ string(SUBSTRING ${_ILMBASE_VERSION} 0 3 _ILMBASE_VERSION )
+ find_library(${tmp_prefix}_LIBRARY_RELEASE
+ NAMES ${libname} ${libname}-${_ILMBASE_VERSION}
+ HINTS ${${libpath_var}}
+ PATH_SUFFIXES lib
+ ${OPENEXR_FIND_OPTIONS}
+ )
+ find_library(${tmp_prefix}_LIBRARY_DEBUG
+ NAMES ${libname}d ${libname}_d ${libname}debug ${libname}_debug
+ HINTS ${${libpath_var}}
+ PATH_SUFFIXES lib
+ ${OPENEXR_FIND_OPTIONS}
+ )
+ # Properly define ${tmp_prefix}_LIBRARY (cached) and ${tmp_prefix}_LIBRARIES
+ select_library_configurations (${tmp_prefix})
+ list (APPEND ${liblist_var} ${tmp_prefix}_LIBRARIES)
+
+ # Add to the list of variables which should be reset
+ list (APPEND ${cachelist_var}
+ ${tmp_prefix}_LIBRARY
+ ${tmp_prefix}_LIBRARY_RELEASE
+ ${tmp_prefix}_LIBRARY_DEBUG)
+ mark_as_advanced (
+ ${tmp_prefix}_LIBRARY
+ ${tmp_prefix}_LIBRARY_RELEASE
+ ${tmp_prefix}_LIBRARY_DEBUG)
+ unset (tmp_prefix)
+endmacro ()
+
+
+# Encode the current state of the external variables into a string
+SET_STATE_VAR (OPENEXR_CURRENT_STATE)
+
+# If the state has changed, clear the cached variables
+if (OPENEXR_CACHED_STATE AND
+ NOT OPENEXR_CACHED_STATE STREQUAL OPENEXR_CURRENT_STATE)
+ foreach (libvar ${OPENEXR_CACHED_VARS})
+ unset (${libvar} CACHE)
+ endforeach ()
+endif ()
+
+# Generic search paths
+set (OpenEXR_generic_include_paths
+ ${OPENEXR_CUSTOM_INCLUDE_DIR}
+ /usr/include
+ /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}
+ /usr/local/include
+ /sw/include
+ /opt/local/include)
+set (OpenEXR_generic_library_paths
+ ${OPENEXR_CUSTOM_LIB_DIR}
+ /usr/lib
+ /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
+ /usr/local/lib
+ /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE}
+ /sw/lib
+ /opt/local/lib)
+
+# Search paths for the OpenEXR files
+if (OPENEXR_HOME)
+ set (OpenEXR_library_paths
+ ${OPENEXR_HOME}/lib
+ ${OPENEXR_HOME}/lib64)
+ if (OPENEXR_VERSION)
+ set (OpenEXR_include_paths
+ ${OPENEXR_HOME}/openexr-${OPENEXR_VERSION}/include
+ ${OPENEXR_HOME}/include/openexr-${OPENEXR_VERSION})
+ list (APPEND OpenEXR_library_paths
+ ${OPENEXR_HOME}/openexr-${OPENEXR_VERSION}/lib
+ ${OPENEXR_HOME}/lib/openexr-${OPENEXR_VERSION})
+ endif()
+ list (APPEND OpenEXR_include_paths ${OPENEXR_HOME}/include)
+ if (OPENEXR_LIB_AREA)
+ list (INSERT OpenEXR_library_paths 2 ${OPENEXR_LIB_AREA})
+ endif ()
+endif ()
+if (ILMBASE_HOME AND OPENEXR_VERSION)
+ list (APPEND OpenEXR_include_paths
+ ${ILMBASE_HOME}/include/openexr-${OPENEXR_VERSION})
+endif()
+list (APPEND OpenEXR_include_paths ${OpenEXR_generic_include_paths})
+list (APPEND OpenEXR_library_paths ${OpenEXR_generic_library_paths})
+
+# Locate the header files
+PREFIX_FIND_INCLUDE_DIR (OpenEXR
+ OpenEXR/ImfArray.h OpenEXR_include_paths)
+
+if (OPENEXR_INCLUDE_DIR)
+ # Get the version from config file, if not already set.
+ if (NOT OPENEXR_VERSION)
+ FILE(STRINGS "${OPENEXR_INCLUDE_DIR}/OpenEXR/OpenEXRConfig.h" OPENEXR_BUILD_SPECIFICATION
+ REGEX "^[ \t]*#define[ \t]+OPENEXR_VERSION_STRING[ \t]+\"[.0-9]+\".*$")
+
+ if(OPENEXR_BUILD_SPECIFICATION)
+ if (NOT OpenEXR_FIND_QUIETLY)
+ message(STATUS "${OPENEXR_BUILD_SPECIFICATION}")
+ endif ()
+ string(REGEX REPLACE ".*#define[ \t]+OPENEXR_VERSION_STRING[ \t]+\"([.0-9]+)\".*"
+ "\\1" XYZ ${OPENEXR_BUILD_SPECIFICATION})
+ set("OPENEXR_VERSION" ${XYZ} CACHE STRING "Version of OpenEXR lib")
+ else()
+ # Old versions (before 2.0?) do not have any version string, just assuming 2.0 should be fine though.
+ message(WARNING "Could not determine ILMBase library version, assuming 2.0.")
+ set("OPENEXR_VERSION" "2.0" CACHE STRING "Version of OpenEXR lib")
+ endif()
+ endif()
+endif ()
+
+if (OPENEXR_CUSTOM)
+ if (NOT OPENEXR_CUSTOM_LIBRARY)
+ message (FATAL_ERROR "Custom OpenEXR library requested but OPENEXR_CUSTOM_LIBRARY is not set.")
+ endif()
+ set (OpenEXR_Library ${OPENEXR_CUSTOM_LIBRARY})
+else ()
+#elseif (${OPENEXR_VERSION} VERSION_LESS "2.1")
+ set (OpenEXR_Library IlmImf)
+#else ()
+# string(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _openexr_libs_ver ${OPENEXR_VERSION})
+# set (OpenEXR_Library IlmImf-${_openexr_libs_ver})
+endif ()
+
+# Locate the OpenEXR library
+set (OpenEXR_libvars "")
+set (OpenEXR_cachevars "")
+PREFIX_FIND_LIB (OpenEXR ${OpenEXR_Library}
+ OpenEXR_library_paths OpenEXR_libvars OpenEXR_cachevars)
+
+# Create the list of variables that might need to be cleared
+set (OPENEXR_CACHED_VARS
+ OPENEXR_INCLUDE_DIR ${OpenEXR_cachevars}
+ CACHE INTERNAL "Variables set by FindOpenEXR.cmake" FORCE)
+
+# Store the current state so that variables might be cleared if required
+set (OPENEXR_CACHED_STATE ${OPENEXR_CURRENT_STATE}
+ CACHE INTERNAL "State last seen by FindOpenEXR.cmake" FORCE)
+
+# Always link explicitly with zlib
+set (OPENEXR_ZLIB ${ZLIB_LIBRARIES})
+
+# Use the standard function to handle OPENEXR_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS (OpenEXR DEFAULT_MSG
+ OPENEXR_INCLUDE_DIR ${OpenEXR_libvars})
+
+if (OPENEXR_FOUND)
+ set (OPENEXR_LIBRARIES "")
+ foreach (tmplib ${OpenEXR_libvars})
+ list (APPEND OPENEXR_LIBRARIES ${${tmplib}})
+ endforeach ()
+ list (APPEND OPENEXR_LIBRARIES ${ZLIB_LIBRARIES})
+ if (NOT OpenEXR_FIND_QUIETLY)
+ FIND_PACKAGE_MESSAGE (OPENEXR
+ "Found OpenEXR: ${OPENEXR_LIBRARIES}"
+ "[${OPENEXR_INCLUDE_DIR}][${OPENEXR_LIBRARIES}][${OPENEXR_CURRENT_STATE}]"
+ )
+ endif ()
+endif ()
+
+# Restore the original find library ordering
+if( OPENEXR_USE_STATIC_LIBS )
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${_openexr_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
+endif()
+
+# Unset the helper variables to avoid pollution
+unset (OPENEXR_CURRENT_STATE)
+unset (OpenEXR_include_paths)
+unset (OpenEXR_library_paths)
+unset (OpenEXR_generic_include_paths)
+unset (OpenEXR_generic_library_paths)
+unset (OpenEXR_libvars)
+unset (OpenEXR_cachevars)
diff --git a/build_files/build_environment/patches/cmake/modules/FindTBB.cmake b/build_files/build_environment/patches/cmake/modules/FindTBB.cmake
new file mode 100644
index 00000000000..8a821f8092e
--- /dev/null
+++ b/build_files/build_environment/patches/cmake/modules/FindTBB.cmake
@@ -0,0 +1,73 @@
+# - Find TBB library
+# Find the native TBB includes and library
+# This module defines
+# TBB_INCLUDE_DIRS, where to find tbb.h, Set when
+# TBB is found.
+# TBB_LIBRARIES, libraries to link against to use TBB.
+# TBB_ROOT_DIR, The base directory to search for TBB.
+# This can also be an environment variable.
+# TBB_FOUND, If false, do not try to use TBB.
+#
+# also defined, but not for general use are
+# TBB_LIBRARY, where to find the TBB library.
+
+#=============================================================================
+# 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 TBB_ROOT_DIR was defined in the environment, use it.
+IF(NOT TBB_ROOT_DIR AND NOT $ENV{TBB_ROOT_DIR} STREQUAL "")
+ SET(TBB_ROOT_DIR $ENV{TBB_ROOT_DIR})
+ENDIF()
+
+SET(_tbb_SEARCH_DIRS
+ ${TBB_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/lib/tbb
+)
+
+FIND_PATH(TBB_INCLUDE_DIR
+ NAMES
+ tbb/tbb.h
+ HINTS
+ ${_tbb_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(TBB_LIBRARY
+ NAMES
+ tbb
+ HINTS
+ ${_tbb_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+
+# handle the QUIETLY and REQUIRED arguments and set TBB_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(TBB DEFAULT_MSG
+ TBB_LIBRARY TBB_INCLUDE_DIR)
+
+IF(TBB_FOUND)
+ SET(TBB_LIBRARIES ${TBB_LIBRARY})
+ SET(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
+ELSE()
+ SET(TBB_TBB_FOUND FALSE)
+ENDIF()
+
+MARK_AS_ADVANCED(
+ TBB_INCLUDE_DIR
+ TBB_LIBRARY
+)
diff --git a/build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake b/build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake
new file mode 100644
index 00000000000..51b4dda0653
--- /dev/null
+++ b/build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake
@@ -0,0 +1,82 @@
+# select_library_configurations( basename )
+#
+# This macro takes a library base name as an argument, and will choose good
+# values for basename_LIBRARY, basename_LIBRARIES, basename_LIBRARY_DEBUG, and
+# basename_LIBRARY_RELEASE depending on what has been found and set. If only
+# basename_LIBRARY_RELEASE is defined, basename_LIBRARY, basename_LIBRARY_DEBUG,
+# and basename_LIBRARY_RELEASE will be set to the release value. If only
+# basename_LIBRARY_DEBUG is defined, then basename_LIBRARY,
+# basename_LIBRARY_DEBUG and basename_LIBRARY_RELEASE will take the debug value.
+#
+# If the generator supports configuration types, then basename_LIBRARY and
+# basename_LIBRARIES will be set with debug and optimized flags specifying the
+# library to be used for the given configuration. If no build type has been set
+# or the generator in use does not support configuration types, then
+# basename_LIBRARY and basename_LIBRARIES will take only the release values.
+
+#=============================================================================
+# Copyright 2009 Kitware, Inc.
+# Copyright 2009 Will Dicharry <wdicharry@stellarscience.com>
+# Copyright 2005-2009 Kitware, Inc.
+#
+# 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.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+# This macro was adapted from the FindQt4 CMake module and is maintained by Will
+# Dicharry <wdicharry@stellarscience.com>.
+
+# Utility macro to check if one variable exists while another doesn't, and set
+# one that doesn't exist to the one that exists.
+macro( _set_library_name basename GOOD BAD )
+ if( ${basename}_LIBRARY_${GOOD} AND NOT ${basename}_LIBRARY_${BAD} )
+ set( ${basename}_LIBRARY_${BAD} ${${basename}_LIBRARY_${GOOD}} )
+ set( ${basename}_LIBRARY ${${basename}_LIBRARY_${GOOD}} )
+ set( ${basename}_LIBRARIES ${${basename}_LIBRARY_${GOOD}} )
+ endif( ${basename}_LIBRARY_${GOOD} AND NOT ${basename}_LIBRARY_${BAD} )
+endmacro( _set_library_name )
+
+macro( select_library_configurations basename )
+ # if only the release version was found, set the debug to be the release
+ # version.
+ _set_library_name( ${basename} RELEASE DEBUG )
+ # if only the debug version was found, set the release value to be the
+ # debug value.
+ _set_library_name( ${basename} DEBUG RELEASE )
+ if (${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE )
+ # if the generator supports configuration types or CMAKE_BUILD_TYPE
+ # is set, then set optimized and debug options.
+ if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
+ set( ${basename}_LIBRARY
+ optimized ${${basename}_LIBRARY_RELEASE}
+ debug ${${basename}_LIBRARY_DEBUG} )
+ set( ${basename}_LIBRARIES
+ optimized ${${basename}_LIBRARY_RELEASE}
+ debug ${${basename}_LIBRARY_DEBUG} )
+ else( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
+ # If there are no configuration types or build type, just use
+ # the release version
+ set( ${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} )
+ set( ${basename}_LIBRARIES ${${basename}_LIBRARY_RELEASE} )
+ endif( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
+ endif( ${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE )
+
+ set( ${basename}_LIBRARY ${${basename}_LIBRARY} CACHE FILEPATH
+ "The ${basename} library" )
+
+ if( ${basename}_LIBRARY )
+ set( ${basename}_FOUND TRUE )
+ endif( ${basename}_LIBRARY )
+
+ mark_as_advanced( ${basename}_LIBRARY
+ ${basename}_LIBRARY_RELEASE
+ ${basename}_LIBRARY_DEBUG
+ )
+endmacro( select_library_configurations )
+
diff --git a/build_files/build_environment/patches/cmakelists_glew.txt b/build_files/build_environment/patches/cmakelists_glew.txt
new file mode 100644
index 00000000000..ec36d4bde63
--- /dev/null
+++ b/build_files/build_environment/patches/cmakelists_glew.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required (VERSION 2.4)
+add_subdirectory(build/cmake) \ No newline at end of file
diff --git a/build_files/build_environment/patches/cmakelists_hidapi.txt b/build_files/build_environment/patches/cmakelists_hidapi.txt
new file mode 100644
index 00000000000..239b9d88b16
--- /dev/null
+++ b/build_files/build_environment/patches/cmakelists_hidapi.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8)
+project(hidapi)
+
+set(SRC_FILES
+ windows/hid.c
+)
+
+set(HEADER_FILES
+ hidapi/hidapi.h
+)
+include_directories(hidapi)
+add_definitions(-DHID_API_STATIC)
+add_library(hidapi STATIC ${SRC_FILES} ${HEADER_FILES})
+
+install(TARGETS hidapi DESTINATION lib)
+
+INSTALL(FILES hidapi/hidapi.h
+ DESTINATION "include"
+ )
+
diff --git a/build_files/build_environment/patches/cmakelists_openvdb.txt b/build_files/build_environment/patches/cmakelists_openvdb.txt
new file mode 100644
index 00000000000..dd3e9c1a887
--- /dev/null
+++ b/build_files/build_environment/patches/cmakelists_openvdb.txt
@@ -0,0 +1,398 @@
+# --------------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 2.8)
+
+# --------------------------------------------------------------------------------
+
+project(OpenVDB)
+
+# --------------------------------------------------------------------------------
+
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
+
+# --------------------------------------------------------------------------------
+
+set(CMAKE_BUILD_TYPE_INIT "Release")
+
+# --------------------------------------------------------------------------------
+# Options
+
+option(WITH_BLOSC "Enable Blosc support for compression" OFF)
+option(WITH_LOGC4PLUS "Enable logging" OFF)
+option(WITH_OPENVDB_2_ABI "Enable building the library to be compability with the OpenVDB 2 ABI" OFF)
+option(WITH_PRINTER "Enable building the OpenVDB print executable" OFF)
+option(WITH_PYTHON "Enable building the OpenVDB python API" OFF)
+option(WITH_RENDERER "Enable building the OpenVDB render executable" OFF)
+option(WITH_UNITTEST "Enable building the unit tests" OFF)
+option(WITH_VIEWER "Enable building the OpenVDB viewer executable" OFF)
+
+# --------------------------------------------------------------------------------
+# Find packages
+#set(BOOST_LIBRARIES boost_iostreams boost_system boost_thread)
+
+find_package(IlmBase)
+find_package(OpenEXR)
+find_package(TBB)
+find_package(Boost)
+
+if(WITH_BLOSC)
+ find_package(Blosc)
+
+ if(NOT BLOSC_FOUND)
+ set(WITH_BLOSC OFF)
+ endif()
+endif()
+
+# todo
+if(WITH_VIEWER)
+ set(GLFW_INCLUDE_DIRS ${GLFW_INCLUDE_PATH})
+ set(GLFW_LIBRARY_DIRS ${GLFW_LIBRARY_PATH})
+endif()
+
+if(WITH_LOGC4PLUS)
+ find_package(LogC4Plus)
+
+ if(NOT LOGC4PLUS_FOUND)
+ set(WITH_LOGC4PLUS OFF)
+ endif()
+endif()
+
+# todo
+if(WITH_PYTHON)
+ set(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH})
+ set(PYTHON_LIBRARY_DIRS ${PYTHON_LIBRARY_PATH})
+endif()
+
+if(WITH_UNITTEST)
+ find_package(CppUnit)
+
+ if(NOT CPPUNIT_FOUND)
+ set(WITH_UNITTEST OFF)
+ endif()
+endif()
+
+# --------------------------------------------------------------------------------
+
+message (STATUS "BOOST_ROOT ${BOOST_ROOT}")
+message (STATUS "Boost found ${Boost_FOUND} ")
+message (STATUS "Boost version ${Boost_VERSION}")
+message (STATUS "Boost include dirs ${Boost_INCLUDE_DIRS}")
+message (STATUS "Boost library dirs ${Boost_LIBRARY_DIRS}")
+message (STATUS "Boost libraries ${Boost_LIBRARIES}")
+
+message (STATUS "ILMBase found ${ILMBASE_FOUND} ")
+message (STATUS "ILMBase include dir ${ILMBASE_INCLUDE_DIR}")
+message (STATUS "ILMBase libraries ${ILMBASE_LIBRARIES}")
+
+message (STATUS "TBB found ${TBB_FOUND} ")
+message (STATUS "TBB include dir ${TBB_INCLUDE_DIR}")
+message (STATUS "TBB libraries ${TBB_LIBRARIES}")
+
+if(MSVC)
+ set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj" )
+ set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /bigobj" )
+endif()
+
+set(OPENVDB_LIBRARIES ${BLOSC_LIBRARIES} ${BOOST_LIBRARIES} ${OPENEXR_LIBRARIES} ${ILMBASE_LIBRARIES} ${TBB_LIBRARIES} ${ZLIB_LIBRARY} )
+
+include_directories(. ${CMAKE_CURRENT_SOURCE_DIR}/../ ${Boost_INCLUDE_DIRS} ${ILMBASE_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR} ${TBB_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR})
+link_directories(${Boost_LIBRARY_DIRS} ${OPENEXR_LIBRARY_DIRS} ${TBB_INCLUDE_DIRS})
+add_definitions(-DNOMINMAX -D__TBB_NO_IMPLICIT_LINKAGE -DOPENVDB_STATICLIB -DOPENVDB_OPENEXR_STATICLIB)
+
+if(WITH_BLOSC)
+ add_definitions(-DOPENVDB_USE_BLOSC)
+ include_directories(${BLOSC_INCLUDE_DIRS})
+ link_directories(${BLOSC_LIBRARY_DIRS})
+endif()
+
+if(WITH_LOGC4PLUS)
+ add_definitions(-DOPENVDB_USE_LOG4CPLUS)
+ include_directories(${LOG4CPLUS_INCLUDE_DIRS})
+ link_directories(${LOG4CPLUS_LIBRARY_DIRS})
+endif()
+
+if(WITH_OPENVDB_2_ABI)
+ add_definitions(-DOPENVDB_2_ABI_COMPATIBLE)
+endif()
+
+# todo
+if(WITH_OPENVDB_USE_GLFW_3)
+ add_definitions(-DOPENVDB_USE_GLFW_3)
+endif()
+
+if(WITH_UNITTEST)
+ include_directories(${CPPUNIT_INCLUDE_DIRS})
+ link_directories(${CPPUNIT_LIBRARY_DIRS})
+endif()
+
+# --------------------------------------------------------------------------------
+
+set(SRC_FILES
+ openvdb/openvdb.cc
+ openvdb/io/Compression.cc
+ openvdb/io/File.cc
+ openvdb/io/Queue.cc
+ openvdb/io/Stream.cc
+ openvdb/io/TempFile.cc
+ openvdb/io/GridDescriptor.cc
+ openvdb/io/Archive.cc
+ openvdb/metadata/MetaMap.cc
+ openvdb/metadata/Metadata.cc
+ openvdb/math/Maps.cc
+ openvdb/math/Transform.cc
+ openvdb/math/QuantizedUnitVec.cc
+ openvdb/math/Proximity.cc
+ openvdb/Grid.cc
+ openvdb/util/Formats.cc
+ openvdb/util/Util.cc
+)
+
+set(HEADER_FILES
+ openvdb/openvdb.h
+ openvdb/version.h
+ openvdb/PlatformConfig.h
+ openvdb/Metadata.h
+ openvdb/Exceptions.h
+ openvdb/Grid.h
+ openvdb/Types.h
+ openvdb/Platform.h
+ openvdb/tree/ValueAccessor.h
+ openvdb/tree/NodeUnion.h
+ openvdb/tree/Tree.h
+ openvdb/tree/Iterator.h
+ openvdb/tree/LeafNodeBool.h
+ openvdb/tree/TreeIterator.h
+ openvdb/tree/LeafNode.h
+ openvdb/tree/NodeManager.h
+ openvdb/tree/LeafManager.h
+ openvdb/tree/InternalNode.h
+ openvdb/tree/RootNode.h
+ openvdb/tools/PointScatter.h
+ openvdb/tools/VolumeAdvect.h
+ openvdb/tools/LevelSetTracker.h
+ openvdb/tools/Composite.h
+ openvdb/tools/Morphology.h
+ openvdb/tools/ValueTransformer.h
+ openvdb/tools/ChangeBackground.h
+ openvdb/tools/GridTransformer.h
+ openvdb/tools/Prune.h
+ openvdb/tools/LevelSetUtil.h
+ openvdb/tools/VolumeToSpheres.h
+ openvdb/tools/LevelSetAdvect.h
+ openvdb/tools/Statistics.h
+ openvdb/tools/LevelSetMeasure.h
+ openvdb/tools/VectorTransformer.h
+ openvdb/tools/RayIntersector.h
+ openvdb/tools/PointPartitioner.h
+ openvdb/tools/Interpolation.h
+ openvdb/tools/VelocityFields.h
+ openvdb/tools/PointIndexGrid.h
+ openvdb/tools/LevelSetRebuild.h
+ openvdb/tools/Clip.h
+ openvdb/tools/SignedFloodFill.h
+ openvdb/tools/MeshToVolume.h
+ openvdb/tools/Dense.h
+ openvdb/tools/Filter.h
+ openvdb/tools/RayTracer.h
+ openvdb/tools/Diagnostics.h
+ openvdb/tools/VolumeToMesh.h
+ openvdb/tools/PoissonSolver.h
+ openvdb/tools/LevelSetFracture.h
+ openvdb/tools/GridOperators.h
+ openvdb/tools/DenseSparseTools.h
+ openvdb/tools/ParticlesToLevelSet.h
+ openvdb/tools/LevelSetSphere.h
+ openvdb/tools/LevelSetMorph.h
+ openvdb/tools/LevelSetFilter.h
+ openvdb/tools/PointAdvect.h
+ openvdb/io/Queue.h
+ openvdb/io/TempFile.h
+ openvdb/io/Stream.h
+ openvdb/io/GridDescriptor.h
+ openvdb/io/Archive.h
+ openvdb/io/io.h
+ openvdb/io/Compression.h
+ openvdb/io/File.h
+ openvdb/metadata/StringMetadata.h
+ openvdb/metadata/MetaMap.h
+ openvdb/metadata/Metadata.h
+ openvdb/math/DDA.h
+ openvdb/math/Vec2.h
+ openvdb/math/FiniteDifference.h
+ openvdb/math/Stencils.h
+ openvdb/math/BBox.h
+ openvdb/math/Mat3.h
+ openvdb/math/Mat.h
+ openvdb/math/Proximity.h
+ openvdb/math/Ray.h
+ openvdb/math/ConjGradient.h
+ openvdb/math/Quat.h
+ openvdb/math/Vec3.h
+ openvdb/math/Vec4.h
+ openvdb/math/QuantizedUnitVec.h
+ openvdb/math/Coord.h
+ openvdb/math/Operators.h
+ openvdb/math/Stats.h
+ openvdb/math/Math.h
+ openvdb/math/Tuple.h
+ openvdb/math/LegacyFrustum.h
+ openvdb/math/Mat4.h
+ openvdb/math/Maps.h
+ openvdb/math/Transform.h
+ openvdb/util/PagedArray.h
+ openvdb/util/CpuTimer.h
+ openvdb/util/Formats.h
+ openvdb/util/NullInterrupter.h
+ openvdb/util/Util.h
+ openvdb/util/Name.h
+ openvdb/util/MapsUtil.h
+ openvdb/util/NodeMasks.h
+ openvdb/util/logging.h
+)
+
+add_library(openvdb STATIC ${SRC_FILES} ${HEADER_FILES})
+
+# --------------------------------------------------------------------------------
+
+target_link_libraries(openvdb ${OPENVDB_LIBRARIES})
+
+set(OPENVDB_VERSION_MAJOR 3)
+set(OPENVDB_VERSION_MINOR 1)
+set(OPENVDB_VERSION_PATCH 0)
+set(OPENVDB_VERSION_STRING ${OPENVDB_VERSION_MAJOR}.${OPENVDB_VERSION_MINOR}.${OPENVDB_VERSION_PATCH})
+
+set_target_properties(openvdb PROPERTIES VERSION ${OPENVDB_VERSION_STRING} SOVERSION ${OPENVDB_VERSION_MAJOR})
+
+install(TARGETS openvdb DESTINATION lib)
+
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include COMPONENT Development FILES_MATCHING PATTERN "*.h"
+ PATTERN ".git" EXCLUDE PATTERN "build" EXCLUDE PATTERN "cmake" EXCLUDE)
+
+# --------------------------------------------------------------------------------
+
+if(WITH_PRINTER)
+ set(PRINT_SRC
+ openvdb/cmd/openvdb_print/main.cc
+ )
+
+ add_executable(vdb_print ${PRINT_SRC})
+ target_link_libraries(vdb_print openvdb)
+ install(TARGETS vdb_print RUNTIME DESTINATION bin)
+endif()
+
+if(WITH_RENDER)
+ set(RENDER_SRC
+ openvdb/cmd/openvdb_render/main.cc
+ )
+
+ add_executable(vdb_render ${RENDER_SRC})
+ target_link_libraries(vdb_render openvdb)
+ install(TARGETS vdb_render RUNTIME DESTINATION bin)
+endif()
+
+# todo
+if(WITH_VIEWER)
+ set(VIEWER_SRC
+ openvdb/viewer/Camera.cc
+ openvdb/viewer/ClipBox.cc
+ openvdb/viewer/Font.cc
+ openvdb/viewer/RenderModules.cc
+ openvdb/viewer/Viewer.cc
+
+ openvdb/viewer/Camera.h
+ openvdb/viewer/ClipBox.h
+ openvdb/viewer/Font.h
+ openvdb/viewer/RenderModules.h
+ openvdb/viewer/Viewer.h
+ openvdb/cmd/openvdb_viewer/main.cc
+ )
+
+ include_directories(${GLFW_INCLUDE_DIRS})
+ link_directories(${GLFW_LIBRARY_DIRS})
+
+ add_executable(vdb_viewer ${VIEWER_SRC})
+ target_link_libraries(vdb_viewer openvdb)
+ install(TARGETS vdb_viewer RUNTIME DESTINATION bin)
+endif()
+
+# todo
+if(WITH_PYTHON)
+# add_library(pyopenvdb SHARED )
+endif()
+
+set(UNITTEST_SRC
+ openvdb/unittest/main.cc
+ openvdb/unittest/TestBBox.cc
+ openvdb/unittest/TestConjGradient.cc
+ openvdb/unittest/TestCoord.cc
+ openvdb/unittest/TestCpt.cc
+ openvdb/unittest/TestCurl.cc
+ openvdb/unittest/TestDense.cc
+ openvdb/unittest/TestDenseSparseTools.cc
+ openvdb/unittest/TestDiagnostics.cc
+ openvdb/unittest/TestDivergence.cc
+ openvdb/unittest/TestDoubleMetadata.cc
+ openvdb/unittest/TestExceptions.cc
+ openvdb/unittest/TestFile.cc
+ openvdb/unittest/TestFloatMetadata.cc
+ openvdb/unittest/TestGradient.cc
+ openvdb/unittest/TestGrid.cc
+ openvdb/unittest/TestGridBbox.cc
+ openvdb/unittest/TestGridDescriptor.cc
+ openvdb/unittest/TestGridIO.cc
+ openvdb/unittest/TestGridTransformer.cc
+ openvdb/unittest/TestInit.cc
+ openvdb/unittest/TestInt32Metadata.cc
+ openvdb/unittest/TestInt64Metadata.cc
+ openvdb/unittest/TestInternalOrigin.cc
+ openvdb/unittest/TestLaplacian.cc
+ openvdb/unittest/TestLeaf.cc
+ openvdb/unittest/TestLeafBool.cc
+ openvdb/unittest/TestLeafIO.cc
+ openvdb/unittest/TestLeafOrigin.cc
+ openvdb/unittest/TestLevelSetRayIntersector.cc
+ openvdb/unittest/TestLevelSetUtil.cc
+ openvdb/unittest/TestLinearInterp.cc
+ openvdb/unittest/TestMaps.cc
+ openvdb/unittest/TestMat4Metadata.cc
+ openvdb/unittest/TestMath.cc
+ openvdb/unittest/TestMeanCurvature.cc
+ openvdb/unittest/TestMeshToVolume.cc
+ openvdb/unittest/TestMetadata.cc
+ openvdb/unittest/TestMetadataIO.cc
+ openvdb/unittest/TestMetaMap.cc
+ openvdb/unittest/TestName.cc
+ openvdb/unittest/TestNodeIterator.cc
+ openvdb/unittest/TestNodeMask.cc
+ openvdb/unittest/TestParticlesToLevelSet.cc
+ openvdb/unittest/TestPointIndexGrid.cc
+ openvdb/unittest/TestPointPartitioner.cc
+ openvdb/unittest/TestPoissonSolver.cc
+ openvdb/unittest/TestPrePostAPI.cc
+ openvdb/unittest/TestQuadraticInterp.cc
+ openvdb/unittest/TestQuantizedUnitVec.cc
+ openvdb/unittest/TestQuat.cc
+ openvdb/unittest/TestRay.cc
+ openvdb/unittest/TestStats.cc
+ openvdb/unittest/TestStream.cc
+ openvdb/unittest/TestStringMetadata.cc
+ openvdb/unittest/TestTools.cc
+ openvdb/unittest/TestTransform.cc
+ openvdb/unittest/TestTree.cc
+ openvdb/unittest/TestTreeCombine.cc
+ openvdb/unittest/TestTreeGetSetValues.cc
+ openvdb/unittest/TestTreeIterators.cc
+ openvdb/unittest/TestTreeVisitor.cc
+ openvdb/unittest/TestUtil.cc
+ openvdb/unittest/TestValueAccessor.cc
+ openvdb/unittest/TestVec2Metadata.cc
+ openvdb/unittest/TestVec3Metadata.cc
+ openvdb/unittest/TestVolumeRayIntersector.cc
+ openvdb/unittest/TestVolumeToMesh.cc
+)
+
+# todo
+if(WITH_UNITTEST)
+ add_executable(test ${UNITTEST_SRC} ${HEADER_FILES})
+ target_link_libraries(test openvdb ${CPPUNIT_LIBRARIES})
+endif()
diff --git a/build_files/build_environment/patches/cmakelists_tbb.txt b/build_files/build_environment/patches/cmakelists_tbb.txt
new file mode 100644
index 00000000000..1be9ca25f6a
--- /dev/null
+++ b/build_files/build_environment/patches/cmakelists_tbb.txt
@@ -0,0 +1,196 @@
+cmake_minimum_required (VERSION 2.8)
+project(tbb CXX)
+
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ message(STATUS "Setting build type to 'Release' as none was specified.")
+ set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
+ "MinSizeRel" "RelWithDebInfo")
+endif()
+
+include_directories(include src src/rml/include )
+
+option(TBB_BUILD_SHARED "Build TBB shared library" ON)
+option(TBB_BUILD_STATIC "Build TBB static library" ON)
+option(TBB_BUILD_TBBMALLOC "Build TBB malloc library" ON)
+option(TBB_BUILD_TBBMALLOC_PROXY "Build TBB malloc proxy library" ON)
+
+if(APPLE)
+ set(CMAKE_MACOSX_RPATH ON)
+endif()
+
+file(GLOB tbb_src "${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/old/*.cpp")
+list(APPEND tbb_src ${CMAKE_CURRENT_SOURCE_DIR}/src/rml/client/rml_tbb.cpp)
+file(GLOB to_remove "${CMAKE_CURRENT_SOURCE_DIR}/src/old/test*.cpp")
+list(REMOVE_ITEM tbb_src ${to_remove})
+
+set(tbbmalloc_static_src
+ src/tbbmalloc/backend.cpp
+ src/tbbmalloc/large_objects.cpp
+ src/tbbmalloc/backref.cpp
+ src/tbbmalloc/tbbmalloc.cpp
+ src/tbbmalloc/frontend.cpp
+ src/tbb/itt_notify.cpp)
+
+set(tbbmalloc_src ${tbbmalloc_static_src})
+
+set(tbbmalloc_proxy_src
+ src/tbbmalloc/proxy.cpp
+ src/tbbmalloc/tbb_function_replacement.cpp)
+
+if (NOT APPLE)
+ add_definitions(-DDO_ITT_NOTIFY)
+else()
+ # Disable annoying "has no symbols" warnings
+ 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>")
+endif()
+
+if (UNIX)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DUSE_PTHREAD")
+ if(NOT CMAKE_CXX_FLAGS MATCHES "-mno-rtm")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mrtm")
+ endif()
+ if (APPLE)
+ set(ARCH_PREFIX "mac")
+ else()
+ set(ARCH_PREFIX "lin")
+ endif()
+ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(ARCH_PREFIX "${ARCH_PREFIX}64")
+ else()
+ set(ARCH_PREFIX "${ARCH_PREFIX}32")
+ endif()
+ set(ENABLE_RTTI "-frtti -fexceptions ")
+ set(DISABLE_RTTI "-fno-rtti -fno-exceptions ")
+elseif(WIN32)
+ cmake_minimum_required (VERSION 3.1)
+ enable_language(ASM_MASM)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GS- /Zc:wchar_t /Zc:forScope /DUSE_WINTHREAD")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0600 /volatile:iso")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4800 /wd4146 /wd4244 /wd4018")
+
+ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+ list(APPEND tbb_src src/tbb/intel64-masm/atomic_support.asm
+ src/tbb/intel64-masm/itsx.asm src/tbb/intel64-masm/intel64_misc.asm)
+ list(APPEND tbbmalloc_src src/tbb/intel64-masm/atomic_support.asm)
+ set(CMAKE_ASM_MASM_FLAGS "/DEM64T=1")
+ set(ARCH_PREFIX "win64")
+ else()
+ list(APPEND tbb_src src/tbb/ia32-masm/atomic_support.asm
+ src/tbb/ia32-masm/itsx.asm src/tbb/ia32-masm/lock_byte.asm)
+ list(APPEND tbbmalloc_src src/tbb/ia32-masm/atomic_support.asm)
+ set(ARCH_PREFIX "win32")
+ endif()
+ set(ENABLE_RTTI "/EHsc /GR ")
+ set(DISABLE_RTTI "/EHs- /GR- ")
+endif()
+
+# Linker export definitions
+if (WIN32)
+ add_custom_command(OUTPUT tbb.def
+ COMMAND ${CMAKE_CXX_COMPILER} /TC /EP ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def -I ${CMAKE_CURRENT_SOURCE_DIR}/include > tbb.def
+ MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def
+ COMMENT "Preprocessing tbb.def"
+ )
+
+ add_custom_command(OUTPUT tbbmalloc.def
+ COMMAND ${CMAKE_CXX_COMPILER} /TC /EP ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def -I ${CMAKE_CURRENT_SOURCE_DIR}/include > tbbmalloc.def
+ MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def
+ COMMENT "Preprocessing tbbmalloc.def"
+ )
+else()
+ add_custom_command(OUTPUT tbb.def
+ COMMAND ${CMAKE_CXX_COMPILER} -xc++ -E ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def -I ${CMAKE_CURRENT_SOURCE_DIR}/include -o tbb.def
+ MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def
+ COMMENT "Preprocessing tbb.def"
+ )
+
+ add_custom_command(OUTPUT tbbmalloc.def
+ COMMAND ${CMAKE_CXX_COMPILER} -xc++ -E ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def -I ${CMAKE_CURRENT_SOURCE_DIR}/include -o tbbmalloc.def
+ MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def
+ COMMENT "Preprocessing tbbmalloc.def"
+ )
+endif()
+
+add_custom_target(tbb_def_files DEPENDS tbb.def tbbmalloc.def)
+
+# TBB library
+if (TBB_BUILD_STATIC)
+ add_library(tbb_static STATIC ${tbb_src})
+ set_property(TARGET tbb_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_BUILD=1")
+ set_property(TARGET tbb_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_SOURCE_DIRECTLY_INCLUDED=1")
+ set_property(TARGET tbb_static APPEND_STRING PROPERTY COMPILE_FLAGS ${ENABLE_RTTI})
+ install(TARGETS tbb_static ARCHIVE DESTINATION lib)
+endif()
+
+if (TBB_BUILD_SHARED)
+ add_library(tbb SHARED ${tbb_src})
+ set_property(TARGET tbb APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_BUILD=1")
+ set_property(TARGET tbb APPEND_STRING PROPERTY COMPILE_FLAGS ${ENABLE_RTTI})
+ add_dependencies(tbb tbb_def_files)
+ if (APPLE)
+ set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "-Wl,-exported_symbols_list,${CMAKE_CURRENT_BINARY_DIR}/tbb.def")
+ elseif(UNIX)
+ set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "-Wl,-version-script,${CMAKE_CURRENT_BINARY_DIR}/tbb.def")
+ elseif(WIN32)
+ set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "/DEF:${CMAKE_CURRENT_BINARY_DIR}/tbb.def")
+ endif()
+ install(TARGETS tbb DESTINATION lib)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCC)
+ # Quench a warning on GCC
+ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/governor.cpp COMPILE_FLAGS "-Wno-missing-field-initializers ")
+elseif(MSVC)
+ # Quench a warning on MSVC
+ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/scheduler.cpp COMPILE_FLAGS "/wd4458 ")
+endif()
+
+if(TBB_BUILD_TBBMALLOC)
+ # TBB malloc library
+ if (TBB_BUILD_STATIC)
+ add_library(tbbmalloc_static STATIC ${tbbmalloc_static_src})
+ set_property(TARGET tbbmalloc_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1")
+ set_property(TARGET tbbmalloc_static APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI})
+ install(TARGETS tbbmalloc_static ARCHIVE DESTINATION lib)
+ endif()
+
+ if (TBB_BUILD_SHARED)
+ add_library(tbbmalloc SHARED ${tbbmalloc_src})
+ set_property(TARGET tbbmalloc APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1")
+ set_property(TARGET tbbmalloc APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI})
+ add_dependencies(tbbmalloc tbb_def_files)
+ if (APPLE)
+ set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "-Wl,-exported_symbols_list,${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def")
+ elseif(UNIX)
+ set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "-Wl,-version-script,${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def")
+ elseif(WIN32)
+ set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "/DEF:${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def")
+ endif()
+ install(TARGETS tbbmalloc DESTINATION lib)
+ endif()
+endif()
+
+if(TBB_BUILD_TBBMALLOC_PROXY)
+ # TBB malloc proxy library
+ if (TBB_BUILD_STATIC)
+ add_library(tbbmalloc_proxy_static STATIC ${tbbmalloc_proxy_src})
+ set_property(TARGET tbbmalloc_proxy_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1")
+ set_property(TARGET tbbmalloc_proxy_static APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI})
+ link_libraries(tbbmalloc_proxy_static tbbmalloc)
+ install(TARGETS tbbmalloc_proxy_static ARCHIVE DESTINATION lib)
+ endif()
+
+ if (TBB_BUILD_SHARED)
+ add_library(tbbmalloc_proxy SHARED ${tbbmalloc_proxy_src})
+ set_property(TARGET tbbmalloc_proxy APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1")
+ set_property(TARGET tbbmalloc_proxy APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI})
+ link_libraries(tbbmalloc_proxy tbbmalloc)
+ install(TARGETS tbbmalloc_proxy DESTINATION lib)
+ endif()
+endif()
+
+install(DIRECTORY include/tbb DESTINATION include)
diff --git a/build_files/build_environment/patches/cuew.diff b/build_files/build_environment/patches/cuew.diff
new file mode 100644
index 00000000000..0363034cd93
--- /dev/null
+++ b/build_files/build_environment/patches/cuew.diff
@@ -0,0 +1,26 @@
+--- CmakeLists.txt.orig 2015-12-31 03:46:41 -0700
++++ CMakeLists.txt 2016-04-01 13:28:33 -0600
+@@ -22,3 +22,10 @@
+
+ add_executable(testcuew cuewTest/cuewTest.c include/cuew.h)
+ target_link_libraries(testcuew cuew ${CMAKE_DL_LIBS})
++
++install(TARGETS cuew
++ LIBRARY DESTINATION lib COMPONENT libraries
++ ARCHIVE DESTINATION lib/static COMPONENT libraries)
++
++INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/cuew.h
++ DESTINATION include/)
+\ No newline at end of file
+--- src/cuew.c 2016-04-01 13:41:43 -0600
++++ src/cuew.c 2016-04-01 13:41:11 -0600
+@@ -15,7 +15,9 @@
+ */
+
+ #ifdef _MSC_VER
++#if _MSC_VER < 1900
+ # define snprintf _snprintf
++#endif
+ # define popen _popen
+ # define pclose _pclose
+ # define _CRT_SECURE_NO_WARNINGS
diff --git a/build_files/build_environment/patches/distutildebugflags.diff b/build_files/build_environment/patches/distutildebugflags.diff
new file mode 100644
index 00000000000..3d6b688bc53
--- /dev/null
+++ b/build_files/build_environment/patches/distutildebugflags.diff
@@ -0,0 +1,11 @@
+--- _msvccompiler.py.orig 2017-01-17 00:57:48 -0700
++++ _msvccompiler.py 2017-05-20 09:47:26 -0600
+@@ -237,7 +237,7 @@
+ ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib'))
+
+ ldflags_debug = [
+- '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL'
++ '/nologo', '/INCREMENTAL:NO', '/LTCG'
+ ]
+
+ self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1']
diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff
new file mode 100644
index 00000000000..75fc6490031
--- /dev/null
+++ b/build_files/build_environment/patches/ffmpeg.diff
@@ -0,0 +1,32 @@
+--- libavutil/common.h 2016-02-14 19:29:42 -0700
++++ libavutil/common.h 2016-03-30 09:50:29 -0600
+@@ -99,6 +99,11 @@
+ #define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
+ #define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
+
++//msvc helper
++#ifdef _MSC_VER
++#define inline __inline
++#endif
++
+ /* misc math functions */
+
+ #ifdef HAVE_AV_CONFIG_H
+--- configure 2016-11-26 03:12:05.000000000 +0100
++++ configure 2017-04-05 03:24:35.000000000 +0200
+@@ -1899,7 +1899,6 @@
+ access
+ aligned_malloc
+ arc4random
+- clock_gettime
+ closesocket
+ CommandLineToArgvW
+ CoTaskMemFree
+@@ -5494,7 +5493,6 @@
+
+ check_func access
+ check_func_headers stdlib.h arc4random
+-check_func_headers time.h clock_gettime || { check_func_headers time.h clock_gettime -lrt && add_extralibs -lrt && LIBRT="-lrt"; }
+ check_func fcntl
+ check_func fork
+ check_func gethrtime
diff --git a/build_files/build_environment/patches/fftw3.diff b/build_files/build_environment/patches/fftw3.diff
new file mode 100644
index 00000000000..48d88414045
--- /dev/null
+++ b/build_files/build_environment/patches/fftw3.diff
@@ -0,0 +1,25 @@
+--- config.h.in 2014-03-04 11:44:58 -0700
++++ config.h.in 2016-03-30 11:42:49 -0600
+@@ -142,9 +142,6 @@
+ /* Define to 1 if you have the `gethrtime' function. */
+ #undef HAVE_GETHRTIME
+
+-/* Define to 1 if you have the `gettimeofday' function. */
+-#undef HAVE_GETTIMEOFDAY
+-
+ /* Define to 1 if hrtime_t is defined in <sys/time.h> */
+ #undef HAVE_HRTIME_T
+
+--- kernel/assert.c 2014-03-04 11:41:03 -0700
++++ kernel/assert.c 2016-04-01 09:41:05 -0600
+@@ -24,8 +24,10 @@
+
+ void X(assertion_failed)(const char *s, int line, const char *file)
+ {
++#if 0
+ fflush(stdout);
+ fprintf(stderr, "fftw: %s:%d: assertion failed: %s\n", file, line, s);
++#endif
+ #ifdef HAVE_ABORT
+ abort();
+ #else
diff --git a/build_files/build_environment/patches/hdf5.diff b/build_files/build_environment/patches/hdf5.diff
new file mode 100644
index 00000000000..cb84625810d
--- /dev/null
+++ b/build_files/build_environment/patches/hdf5.diff
@@ -0,0 +1,11 @@
+--- UserMacros.cmake
++++ UserMacros.cmake
+@@ -16,6 +16,8 @@
+ if (BUILD_USER_DEFINED_LIBS)
+ MACRO_USER_DEFINED_LIBS ()
+ endif (BUILD_USER_DEFINED_LIBS)
++
++include(Config/cmake/usermacros/windows_mt.cmake)
+ #-----------------------------------------------------------------------------
+ #------------------- E X A M P L E E N D -----------------------------------
+ #-----------------------------------------------------------------------------
diff --git a/build_files/build_environment/patches/hidapi.diff b/build_files/build_environment/patches/hidapi.diff
new file mode 100644
index 00000000000..720a8ae5ae9
--- /dev/null
+++ b/build_files/build_environment/patches/hidapi.diff
@@ -0,0 +1,15 @@
+--- hidapi/hidapi.h 2011-10-25 20:58:16 -0600
++++ hidapi/hidapi.h 2016-11-01 12:05:58 -0600
+@@ -30,7 +30,11 @@
+ #include <wchar.h>
+
+ #ifdef _WIN32
+- #define HID_API_EXPORT __declspec(dllexport)
++ #ifdef HID_API_STATIC
++ #define HID_API_EXPORT
++ #else
++ #define HID_API_EXPORT __declspec(dllexport)
++ #endif
+ #define HID_API_CALL
+ #else
+ #define HID_API_EXPORT /**< API export macro */
diff --git a/build_files/build_environment/install_deps_patches/llvm.patch b/build_files/build_environment/patches/install_deps_llvm.diff
index 968f011e57c..968f011e57c 100644
--- a/build_files/build_environment/install_deps_patches/llvm.patch
+++ b/build_files/build_environment/patches/install_deps_llvm.diff
diff --git a/build_files/build_environment/install_deps_patches/osl.patch b/build_files/build_environment/patches/install_deps_osl.diff
index 3b52403f740..3b52403f740 100644
--- a/build_files/build_environment/install_deps_patches/osl.patch
+++ b/build_files/build_environment/patches/install_deps_osl.diff
diff --git a/build_files/build_environment/patches/libfaad.diff b/build_files/build_environment/patches/libfaad.diff
new file mode 100644
index 00000000000..37605b29cd9
--- /dev/null
+++ b/build_files/build_environment/patches/libfaad.diff
@@ -0,0 +1,10 @@
+--- frontend/main.c 2008-09-22 11:55:09 -0600
++++ frontend/main.c 2016-04-06 15:20:36 -0600
+@@ -31,7 +31,6 @@
+ #ifdef _WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+-#define off_t __int64
+ #else
+ #include <time.h>
+ #endif
diff --git a/build_files/build_environment/patches/llvm-alloca-fix.diff b/build_files/build_environment/patches/llvm-alloca-fix.diff
new file mode 100644
index 00000000000..5394a472167
--- /dev/null
+++ b/build_files/build_environment/patches/llvm-alloca-fix.diff
@@ -0,0 +1,111 @@
+Index: lib/Target/X86/X86ISelLowering.cpp
+===================================================================
+--- lib/Target/X86/X86ISelLowering.cpp 2014-04-11 23:04:44.000000000 +0200
++++ lib/Target/X86/X86ISelLowering.cpp (working copy)
+@@ -15493,12 +15493,36 @@
+ // non-trivial part is impdef of ESP.
+
+ if (Subtarget->isTargetWin64()) {
++ const char *StackProbeSymbol =
++ Subtarget->isTargetCygMing() ? "___chkstk" : "__chkstk";
++
++ MachineInstrBuilder MIB;
++
++ if (getTargetMachine().getCodeModel() == CodeModel::Large) {
++ // For large code model we need to do indirect call to __chkstk.
++
++ // R11 will be used to contain the address of __chkstk.
++ // R11 is a volotiale register and assumed to be destoyed by the callee,
++ // so there is no need to save and restore it.
++ BuildMI(*BB, MI, DL, TII->get(X86::MOV64ri), X86::R11)
++ .addExternalSymbol(StackProbeSymbol);
++ // Create a call to __chkstk function which address contained in R11.
++ MIB = BuildMI(*BB, MI, DL, TII->get(X86::CALL64r))
++ .addReg(X86::R11, RegState::Kill);
++
++ } else {
++
++ // For non-large code model we can do direct call to __chkstk.
++
++ MIB = BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA))
++ .addExternalSymbol(StackProbeSymbol);
++ }
++
+ if (Subtarget->isTargetCygMing()) {
+ // ___chkstk(Mingw64):
+ // Clobbers R10, R11, RAX and EFLAGS.
+ // Updates RSP.
+- BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA))
+- .addExternalSymbol("___chkstk")
++ MIB
+ .addReg(X86::RAX, RegState::Implicit)
+ .addReg(X86::RSP, RegState::Implicit)
+ .addReg(X86::RAX, RegState::Define | RegState::Implicit)
+@@ -15507,8 +15531,7 @@
+ } else {
+ // __chkstk(MSVCRT): does not update stack pointer.
+ // Clobbers R10, R11 and EFLAGS.
+- BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA))
+- .addExternalSymbol("__chkstk")
++ MIB
+ .addReg(X86::RAX, RegState::Implicit)
+ .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit);
+ // RAX has the offset to be subtracted from RSP.
+Index: lib/Target/X86/X86FrameLowering.cpp
+===================================================================
+--- lib/Target/X86/X86FrameLowering.cpp 2013-10-24 01:37:01.000000000 +0200
++++ lib/Target/X86/X86FrameLowering.cpp (working copy)
+@@ -635,25 +635,49 @@
+ .addReg(X86::EAX, RegState::Kill)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
++
++ MachineInstrBuilder MIB;
+
+ if (Is64Bit) {
++
+ // Handle the 64-bit Windows ABI case where we need to call __chkstk.
+ // Function prologue is responsible for adjusting the stack pointer.
+ BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::RAX)
+ .addImm(NumBytes)
+ .setMIFlag(MachineInstr::FrameSetup);
++
++ if (TM.getCodeModel() == CodeModel::Large) {
++ // For large code model we need to do indirect call to __chkstk.
++
++
++ // R11 will be used to contain the address of __chkstk.
++ // R11 is a volotiale register and assumed to be destoyed by the callee,
++ // so there is no need to save and restore it.
++ BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::R11)
++ .addExternalSymbol(StackProbeSymbol);
++ // Create a call to __chkstk function which address contained in R11.
++ MIB = BuildMI(MBB, MBBI, DL, TII.get(X86::CALL64r))
++ .addReg(X86::R11, RegState::Kill);
++ } else {
++
++ // For non-large code model we can do direct call to __chkstk.
++
++ MIB = BuildMI(MBB, MBBI, DL, TII.get(X86::W64ALLOCA))
++ .addExternalSymbol(StackProbeSymbol);
++ }
+ } else {
+ // Allocate NumBytes-4 bytes on stack in case of isEAXAlive.
+ // We'll also use 4 already allocated bytes for EAX.
+ BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
+ .addImm(isEAXAlive ? NumBytes - 4 : NumBytes)
+ .setMIFlag(MachineInstr::FrameSetup);
++
++ MIB = BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32))
++ .addExternalSymbol(StackProbeSymbol);
+ }
+
+- BuildMI(MBB, MBBI, DL,
+- TII.get(Is64Bit ? X86::W64ALLOCA : X86::CALLpcrel32))
+- .addExternalSymbol(StackProbeSymbol)
+- .addReg(StackPtr, RegState::Define | RegState::Implicit)
++
++ MIB.addReg(StackPtr, RegState::Define | RegState::Implicit)
+ .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit)
+ .setMIFlag(MachineInstr::FrameSetup);
+
diff --git a/build_files/build_environment/patches/ming32sh.cmd b/build_files/build_environment/patches/ming32sh.cmd
new file mode 100644
index 00000000000..3259d9d3714
--- /dev/null
+++ b/build_files/build_environment/patches/ming32sh.cmd
@@ -0,0 +1,7 @@
+@title MinGW-w64 32-bit GCC build environment
+
+@echo Setting up environment for MinGW-w64 GCC 32-bit...
+
+@set PATH=%CD%\bin;%CD%\msys\1.0\bin;%cd%\..\..\perl32\site\bin;%cd%\..\..\perl32\bin;%cd%\..\..\c\bin;%PATH%
+
+
diff --git a/build_files/build_environment/patches/ming64sh.cmd b/build_files/build_environment/patches/ming64sh.cmd
new file mode 100644
index 00000000000..18fea3829f3
--- /dev/null
+++ b/build_files/build_environment/patches/ming64sh.cmd
@@ -0,0 +1,7 @@
+@title MinGW-w64 64-bit GCC build environment
+
+@echo Setting up environment for MinGW-w64 GCC 64-bit...
+
+@set PATH=%CD%\bin;%CD%\msys\1.0\bin;%cd%\..\..\perl\site\bin;%cd%\..\..\perl\bin;%cd%\..\..\c\bin;%PATH%
+
+
diff --git a/build_files/build_environment/patches/numpy.diff b/build_files/build_environment/patches/numpy.diff
new file mode 100644
index 00000000000..c4c57222838
--- /dev/null
+++ b/build_files/build_environment/patches/numpy.diff
@@ -0,0 +1,23 @@
+diff -Naur numpy-1.11.1/numpy/distutils/ccompiler.py numpy-1.11.1/numpy/distutils/ccompiler.py
+--- numpy-1.11.1/numpy/distutils/ccompiler.py 2016-06-25 08:38:34 -0600
++++ numpy-1.11.1/numpy/distutils/ccompiler.py 2016-08-04 12:33:43 -0600
+@@ -29,6 +29,7 @@
+
+ # Using customized CCompiler.spawn.
+ def CCompiler_spawn(self, cmd, display=None):
++ cmd = quote_args(cmd)
+ """
+ Execute a command in a sub-process.
+
+diff -Naur numpy-1.11.1/numpy/distutils/misc_util.py numpy-1.11.1/numpy/distutils/misc_util.py
+--- numpy-1.11.1/numpy/distutils/misc_util.py 2016-06-25 08:38:34 -0600
++++ numpy-1.11.1/numpy/distutils/misc_util.py 2016-08-04 12:34:56 -0600
+@@ -116,7 +116,7 @@
+ args = list(args)
+ for i in range(len(args)):
+ a = args[i]
+- if ' ' in a and a[0] not in '"\'':
++ if ' ' in a and a[0] not in '"\'' and a[len(a)-1] not in '"\'':
+ args[i] = '"%s"' % (a)
+ return args
+
diff --git a/build_files/build_environment/patches/opencollada.diff b/build_files/build_environment/patches/opencollada.diff
new file mode 100644
index 00000000000..0c91b4151fe
--- /dev/null
+++ b/build_files/build_environment/patches/opencollada.diff
@@ -0,0 +1,32 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 3fc9be5..5112ce6 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -254,11 +254,11 @@
+ endif()
+
+ #adding PCRE
+-find_package(PCRE)
++#find_package(PCRE)
+ if (PCRE_FOUND)
+ message(STATUS "SUCCESSFUL: PCRE found")
+ else () # if pcre not found building its local copy from ./Externals
+- if (WIN32 OR APPLE)
++ if (1)
+ message("WARNING: Native PCRE not found, taking PCRE from ./Externals")
+ add_definitions(-DPCRE_STATIC)
+ add_subdirectory(${EXTERNAL_LIBRARIES}/pcre)
+diff --git a/DAEValidator/library/include/no_warning_begin.orig b/DAEValidator/library/include/no_warning_begin
+index 3fc9be5..5112ce6 100644
+--- a/DAEValidator/library/include/no_warning_begin.orig 2017-05-31 16:56:39 -0600
++++ b/DAEValidator/library/include/no_warning_begin 2017-06-07 10:18:45 -0600
+@@ -2,6 +2,9 @@
+ #if defined(_WIN32)
+ # pragma warning(push)
+ # pragma warning(disable:4668)
++# if _MSC_VER >=1900
++# pragma warning(disable:5031)
++# endif
+ # if defined(_MSC_VER) && defined(_DEBUG)
+ # pragma warning(disable:4548)
+ # endif
diff --git a/build_files/build_environment/patches/opencolorio.diff b/build_files/build_environment/patches/opencolorio.diff
new file mode 100644
index 00000000000..4e947d89097
--- /dev/null
+++ b/build_files/build_environment/patches/opencolorio.diff
@@ -0,0 +1,21 @@
+diff -ru ./CMakeLists.txt ./CMakeLists.txt
+--- ./CMakeLists.txt 2014-09-11 21:08:18.000000000 +0200
++++ ./CMakeLists.txt 2016-05-15 17:17:01.000000000 +0200
+@@ -186,7 +186,7 @@
+ PATCH_COMMAND patch -f -p1 < ${CMAKE_SOURCE_DIR}/ext/tinyxml_${TINYXML_VERSION}.patch
+ BINARY_DIR ext/build/tinyxml
+ INSTALL_DIR ext/dist
+- CMAKE_ARGS ${TINYXML_CMAKE_ARGS}
++ CMAKE_ARGS ${TINYXML_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT} -DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG} -DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE} -DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
+ )
+ if(WIN32)
+ set(TINYXML_STATIC_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/tinyxml.lib)
+@@ -254,7 +254,7 @@
+ BINARY_DIR ext/build/yaml-cpp
+ PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/ext/yaml-cpp-${YAML_CPP_VERSION}.patch
+ INSTALL_DIR ext/dist
+- CMAKE_ARGS ${YAML_CPP_CMAKE_ARGS}
++ CMAKE_ARGS ${YAML_CPP_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT} -DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG} -DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE} -DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
+ )
+ set(YAML_CPP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ext/dist/include)
+ set(YAML_CPP_LIBRARY_DIRS ${PROJECT_BINARY_DIR}/ext/dist/lib)
diff --git a/build_files/build_environment/patches/openexr.diff b/build_files/build_environment/patches/openexr.diff
new file mode 100644
index 00000000000..ec18751fe74
--- /dev/null
+++ b/build_files/build_environment/patches/openexr.diff
@@ -0,0 +1,33 @@
+--- IlmImf/CMakeLists.txt 2014-08-10 06:23:56.000000000 +0200
++++ IlmImf/CMakeLists.txt 2017-01-08 04:06:04.931723800 +0100
+@@ -8,8 +8,8 @@
+
+ TARGET_LINK_LIBRARIES ( b44ExpLogTable
+ Half
+- Iex${ILMBASE_LIBSUFFIX}
+ IlmThread${ILMBASE_LIBSUFFIX}
++ Iex${ILMBASE_LIBSUFFIX}
+ ${PTHREAD_LIB}
+ )
+
+@@ -25,8 +25,8 @@
+
+ TARGET_LINK_LIBRARIES ( dwaLookups
+ Half
+- Iex${ILMBASE_LIBSUFFIX}
+ IlmThread${ILMBASE_LIBSUFFIX}
++ Iex${ILMBASE_LIBSUFFIX}
+ ${PTHREAD_LIB}
+ )
+
+@@ -138,9 +138,9 @@
+
+ TARGET_LINK_LIBRARIES ( IlmImf
+ Half
+- Iex${ILMBASE_LIBSUFFIX}
+ Imath${ILMBASE_LIBSUFFIX}
+ IlmThread${ILMBASE_LIBSUFFIX}
++ Iex${ILMBASE_LIBSUFFIX}
+ ${PTHREAD_LIB} ${ZLIB_LIBRARIES}
+ )
+
diff --git a/build_files/build_environment/patches/openimageio_gdi.diff b/build_files/build_environment/patches/openimageio_gdi.diff
new file mode 100644
index 00000000000..af0c90638de
--- /dev/null
+++ b/build_files/build_environment/patches/openimageio_gdi.diff
@@ -0,0 +1,26 @@
+Index: OpenImageIO/osdep.h
+===================================================================
+--- OpenImageIO/osdep.h (revision 61595)
++++ OpenImageIO/osdep.h (working copy)
+@@ -34,6 +34,7 @@
+ # define WIN32_LEAN_AND_MEAN
+ # define VC_EXTRALEAN
+ # define NOMINMAX
++# define NOGDI
+ # include <windows.h>
+ #endif
+
+Index: OpenImageIO/platform.h
+===================================================================
+--- OpenImageIO/platform.h (revision 61595)
++++ OpenImageIO/platform.h (working copy)
+@@ -77,6 +77,9 @@
+ # ifndef NOMINMAX
+ # define NOMINMAX
+ # endif
++# ifndef NOGDI
++# define NOGDI
++# endif
+ # include <windows.h>
+ #endif
+
diff --git a/build_files/build_environment/patches/openimageio_idiff.diff b/build_files/build_environment/patches/openimageio_idiff.diff
new file mode 100644
index 00000000000..ae1884f76b5
--- /dev/null
+++ b/build_files/build_environment/patches/openimageio_idiff.diff
@@ -0,0 +1,13 @@
+--- idiff.cpp 2016-11-18 11:42:01 -0700
++++ idiff.cpp 2016-11-18 11:41:25 -0700
+@@ -308,8 +308,10 @@
+ // printed with three digit exponent. We change this behaviour to fit
+ // Linux way
+ #ifdef _MSC_VER
++#if _MSC_VER < 1900
+ _set_output_format(_TWO_DIGIT_EXPONENT);
+ #endif
++#endif
+ std::streamsize precis = std::cout.precision();
+ std::cout << " " << cr.nwarn << " pixels ("
+ << std::setprecision(3) << (100.0*cr.nwarn / npels)
diff --git a/build_files/build_environment/patches/openimageio_staticexr.diff b/build_files/build_environment/patches/openimageio_staticexr.diff
new file mode 100644
index 00000000000..7e4eee04548
--- /dev/null
+++ b/build_files/build_environment/patches/openimageio_staticexr.diff
@@ -0,0 +1,10 @@
+--- CMakeLists.txt 2016-11-01 01:03:44 -0600
++++ CMakeLists.txt 2016-12-01 09:20:12 -0700
+@@ -454,7 +454,6 @@
+ add_definitions (-D_CRT_NONSTDC_NO_WARNINGS)
+ add_definitions (-D_SCL_SECURE_NO_WARNINGS)
+ add_definitions (-DJAS_WIN_MSVC_BUILD)
+- add_definitions (-DOPENEXR_DLL)
+ if (LINKSTATIC)
+ add_definitions (-DBoost_USE_STATIC_LIBS=1)
+ else ()
diff --git a/build_files/build_environment/patches/opensubdiv.diff b/build_files/build_environment/patches/opensubdiv.diff
new file mode 100644
index 00000000000..9e9cf7ad554
--- /dev/null
+++ b/build_files/build_environment/patches/opensubdiv.diff
@@ -0,0 +1,16 @@
+ opensubdiv/osd/d3d11VertexBuffer.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/opensubdiv/osd/d3d11VertexBuffer.cpp b/opensubdiv/osd/d3d11VertexBuffer.cpp
+index 603cbf4..07e7e0a 100644
+--- a/opensubdiv/osd/d3d11VertexBuffer.cpp
++++ b/opensubdiv/osd/d3d11VertexBuffer.cpp
+@@ -81,7 +81,7 @@ D3D11VertexBuffer::UpdateData(const float *src, int startVertex, int numVertices
+
+ deviceContext->Unmap(_uploadBuffer, 0);
+
+- D3D11_BOX srcBox = { 0, 0, 0, size, 1, 1 };
++ D3D11_BOX srcBox = { 0, 0, 0, (UINT) size, 1, 1 };
+ deviceContext->CopySubresourceRegion(_buffer, 0, 0, 0, 0,
+ _uploadBuffer, 0, &srcBox);
+ }
diff --git a/build_files/build_environment/patches/openvdb.diff b/build_files/build_environment/patches/openvdb.diff
new file mode 100644
index 00000000000..f3afa13ea17
--- /dev/null
+++ b/build_files/build_environment/patches/openvdb.diff
@@ -0,0 +1,11 @@
+diff -Naur k:\BlenderDev\lib\win64_vc12_Harvest\openVDB\/include/openvdb/math/Coord.h .\openVDB/include/openvdb/math/Coord.h
+--- k:\BlenderDev\lib\win64_vc12_Harvest\openVDB\/include/openvdb/math/Coord.h 2016-03-30 15:09:49 -0600
++++ .\openVDB/include/openvdb/math/Coord.h 2016-04-01 06:53:47 -0600
+@@ -34,6 +34,7 @@
+ #include <openvdb/Platform.h>
+ #include "Math.h"
+ #include "Vec3.h"
++#define NOMINMAX
+
+ namespace tbb { class split; } // forward declaration
+
diff --git a/build_files/build_environment/patches/openvdb_vc2013.diff b/build_files/build_environment/patches/openvdb_vc2013.diff
new file mode 100644
index 00000000000..7dc3e476297
--- /dev/null
+++ b/build_files/build_environment/patches/openvdb_vc2013.diff
@@ -0,0 +1,35 @@
+--- openvdb/tree/LeafNode.h 2015-10-01 15:55:33 -0600
++++ openvdb/tree/LeafNode.h 2016-03-26 13:12:22 -0600
+@@ -70,13 +70,14 @@
+ typedef boost::shared_ptr<LeafNode> Ptr;
+ typedef util::NodeMask<Log2Dim> NodeMaskType;
+
+- static const Index
+- LOG2DIM = Log2Dim, // needed by parent nodes
+- TOTAL = Log2Dim, // needed by parent nodes
+- DIM = 1 << TOTAL, // dimension along one coordinate direction
+- NUM_VALUES = 1 << 3 * Log2Dim,
+- NUM_VOXELS = NUM_VALUES, // total number of voxels represented by this node
+- SIZE = NUM_VALUES,
++ static const Index
++ LOG2DIM = Log2Dim, // needed by parent nodes
++ TOTAL = Log2Dim, // needed by parent nodes
++ DIM = 1 << TOTAL, // dimension along one coordinate direction
++ NUM_VALUES = 1 << 3 * Log2Dim,
++ NUM_VOXELS = NUM_VALUES; // total number of voxels represented by this node
++ static const Index
++ SIZE = NUM_VALUES,
+ LEVEL = 0; // level 0 = leaf
+
+ /// @brief ValueConverter<T>::Type is the type of a LeafNode having the same
+--- openvdb/PlatformConfig.h 2016-03-30 15:09:49 -0600
++++ openvdb/PlatformConfig.h 2016-04-01 07:00:38 -0600
+@@ -47,7 +47,7 @@
+ #if !defined(OPENVDB_OPENEXR_STATICLIB) && !defined(OPENEXR_DLL)
+ #define OPENEXR_DLL
+ #endif
+-
++ #define NOMINMAX
+ #endif // _WIN32
+
+ #endif // OPENVDB_PLATFORMCONFIG_HAS_BEEN_INCLUDED
diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff
new file mode 100644
index 00000000000..fcb5ec4165f
--- /dev/null
+++ b/build_files/build_environment/patches/osl.diff
@@ -0,0 +1,12 @@
+diff -Naur osl/src/external_osl/src/cmake/flexbison.cmake osl_bak/src/external_osl/src/cmake/flexbison.cmake
+--- osl/src/external_osl//src/cmake/flexbison.cmake 2016-01-29 11:15:22 -0700
++++ osl_bak/src/external_osl/src/cmake/flexbison.cmake 2016-02-29 21:26:26 -0700
+@@ -77,7 +77,7 @@
+ DEPENDS ${${compiler_headers}}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
+ ADD_CUSTOM_COMMAND ( OUTPUT ${flexoutputcxx}
+- COMMAND ${FLEX_EXECUTABLE} -o ${flexoutputcxx} "${CMAKE_CURRENT_SOURCE_DIR}/${flexsrc}"
++ COMMAND ${FLEX_EXECUTABLE} ${FLEX_EXTRA_OPTIONS} -o ${flexoutputcxx} "${CMAKE_CURRENT_SOURCE_DIR}/${flexsrc}"
+ MAIN_DEPENDENCY ${flexsrc}
+ DEPENDS ${${compiler_headers}}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
diff --git a/build_files/build_environment/patches/osl_simd_oiio.diff b/build_files/build_environment/patches/osl_simd_oiio.diff
new file mode 100644
index 00000000000..5062a597167
--- /dev/null
+++ b/build_files/build_environment/patches/osl_simd_oiio.diff
@@ -0,0 +1,14 @@
+--- CMakeLists.txt 2016-10-31 16:48:19 -0600
++++ CMakeLists.txt 2017-04-10 10:38:48 -0600
+@@ -269,6 +269,11 @@
+ add_definitions ("-DOIIO_STATIC_BUILD=1")
+ endif ()
+
++set (OIIO_NOSIMD OFF CACHE BOOL "Disable simd support in oiio")
++if (OIIO_NOSIMD)
++ add_definitions ("-DOIIO_NO_SSE=1")
++endif ()
++
+ if (OSL_NO_DEFAULT_TEXTURESYSTEM)
+ add_definitions ("-DOSL_NO_DEFAULT_TEXTURESYSTEM=1")
+ endif ()
diff --git a/build_files/build_environment/patches/pthreads.diff b/build_files/build_environment/patches/pthreads.diff
new file mode 100644
index 00000000000..bbabfdc8925
--- /dev/null
+++ b/build_files/build_environment/patches/pthreads.diff
@@ -0,0 +1,13 @@
+--- pthread.h.orig 2012-05-26 22:16:45 -0600
++++ pthread.h 2016-04-01 09:20:36 -0600
+@@ -109,6 +109,10 @@
+ /* Include everything */
+ #endif
+
++#if _MSC_VER >= 1900
++# define HAVE_STRUCT_TIMESPEC 1
++#endif
++
+ #if defined(_UWIN)
+ # define HAVE_STRUCT_TIMESPEC 1
+ # define HAVE_SIGNAL_H 1
diff --git a/build_files/build_environment/patches/pyshell.diff b/build_files/build_environment/patches/pyshell.diff
new file mode 100644
index 00000000000..7ccffe4c040
--- /dev/null
+++ b/build_files/build_environment/patches/pyshell.diff
@@ -0,0 +1,12 @@
+--- pyshellext.cpp.orig 2017-01-17 00:57:53 -0700
++++ pyshellext.cpp 2017-05-20 15:21:51 -0600
+@@ -13,6 +13,9 @@
+ #include <strsafe.h>
+
+ #include "pyshellext_h.h"
++#if _MSC_VER < 1900
++#include "pyshellext_i.c"
++#endif
+
+ #define DDWM_UPDATEWINDOW (WM_USER+3)
+
diff --git a/build_files/build_environment/patches/python.diff b/build_files/build_environment/patches/python.diff
new file mode 100644
index 00000000000..749a51d6972
--- /dev/null
+++ b/build_files/build_environment/patches/python.diff
@@ -0,0 +1,40 @@
+--- pcbuild/build.bat 2016-05-21 09:53:55 -0600
++++ pcbuild/build.bat 2016-05-21 09:56:16 -0600
+@@ -59,6 +59,7 @@
+ if "%~1"=="-h" goto Usage
+ if "%~1"=="-c" (set conf=%2) & shift & shift & goto CheckOpts
+ if "%~1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts
++if "%~1"=="-k" (set vs_toolset=%2) & shift & shift & goto CheckOpts
+ if "%~1"=="-r" (set target=Rebuild) & shift & goto CheckOpts
+ if "%~1"=="-t" (set target=%2) & shift & shift & goto CheckOpts
+ if "%~1"=="-d" (set conf=Debug) & shift & goto CheckOpts
+@@ -126,7 +126,7 @@
+
+ :Kill
+ echo on
+-msbuild "%dir%\pythoncore.vcxproj" /t:KillPython %verbose%^
++msbuild "%dir%\pythoncore.vcxproj" /t:KillPython %verbose% /p:PlatformToolset=%vs_toolset%^
+ /p:Configuration=%conf% /p:Platform=%platf%^
+ /p:KillPython=true
+
+@@ -95,7 +96,7 @@
+ rem batch is, shall we say, "lackluster"
+ echo on
+ msbuild "%dir%pcbuild.proj" /t:%target% %parallel% %verbose%^
+- /p:Configuration=%conf% /p:Platform=%platf%^
++ /p:Configuration=%conf% /p:Platform=%platf% /p:PlatformToolset=%vs_toolset%^
+ /p:IncludeExternals=%IncludeExternals%^
+ /p:IncludeSSL=%IncludeSSL% /p:IncludeTkinter=%IncludeTkinter%^
+ /p:UseTestMarker=%UseTestMarker%^
+
+--- pcbuild/sqlite3.vcxproj 2015-12-06 18:39:10 -0700
++++ pcbuild/sqlite3.vcxproj 2016-11-02 09:25:56 -0600
+@@ -43,7 +43,7 @@
+ <Import Project="python.props" />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration">
+- <ConfigurationType>DynamicLibrary</ConfigurationType>
++ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>NotSet</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
diff --git a/build_files/build_environment/patches/python_apple.diff b/build_files/build_environment/patches/python_apple.diff
new file mode 100644
index 00000000000..0ca7a8d8f04
--- /dev/null
+++ b/build_files/build_environment/patches/python_apple.diff
@@ -0,0 +1,48 @@
+--- Modules/expat/expat_external.h 2016-12-17 06:51:30 -0500
++++ Modules/expat/expat_external.h 2016-12-17 06:55:29 -0500
+@@ -7,9 +7,17 @@
+
+ /* External API definitions */
+
+-/* Namespace external symbols to allow multiple libexpat version to
+- co-exist. */
+-#include "pyexpatns.h"
++/*
++
++ HACK: Fix build breakage on MacOS:
++ *** WARNING: renaming "pyexpat" since importing it failed: dlopen(build/lib.macosx-10.6-i386-3.3/pyexpat.so, 2): Symbol not found: _XML_ErrorString
++ This reverts c242a8f30806 from the python hg repo:
++ restore namespacing of pyexpat symbols (closes #19186)
++ See http://bugs.python.org/issue19186#msg214069
++ The recommendation to include Modules/inc at first broke the Linux build...
++ So do it this way, as it was before. Needs some realignment later.
++
++*/
+
+ #if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
+ #define XML_USE_MSC_EXTENSIONS 1
+--- pyconfig.h.in 2017-04-05 02:47:52.000000000 +0200
++++ pyconfig.h.in 2017-04-05 02:51:33.000000000 +0200
+@@ -119,12 +119,6 @@
+ /* Define to 1 if you have the `clock' function. */
+ #undef HAVE_CLOCK
+
+-/* Define to 1 if you have the `clock_getres' function. */
+-#undef HAVE_CLOCK_GETRES
+-
+-/* Define to 1 if you have the `clock_gettime' function. */
+-#undef HAVE_CLOCK_GETTIME
+-
+ /* Define if the C compiler supports computed gotos. */
+ #undef HAVE_COMPUTED_GOTOS
+
+@@ -338,9 +332,6 @@
+ /* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */
+ #undef HAVE_GETC_UNLOCKED
+
+-/* Define to 1 if you have the `getentropy' function. */
+-#undef HAVE_GETENTROPY
+-
+ /* Define to 1 if you have the `getgrouplist' function. */
+ #undef HAVE_GETGROUPLIST
+
diff --git a/build_files/build_environment/patches/python_runtime_vc2013.diff b/build_files/build_environment/patches/python_runtime_vc2013.diff
new file mode 100644
index 00000000000..186d2b36c07
--- /dev/null
+++ b/build_files/build_environment/patches/python_runtime_vc2013.diff
@@ -0,0 +1,29 @@
+--- _msvccompiler.py.orig 2017-05-20 19:31:45 -0600
++++ _msvccompiler.py 2017-06-10 10:05:38 -0600
+@@ -222,9 +222,9 @@
+ # use /MT[d] to build statically, then switch from libucrt[d].lib to ucrt[d].lib
+ # later to dynamically link to ucrtbase but not vcruntime.
+ self.compile_options = [
+- '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG'
++ '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG' , '/MD'
+ ]
+- self.compile_options.append('/MD' if self._vcruntime_redist else '/MT')
++ #self.compile_options.append('/MD' if self._vcruntime_redist else '/MT')
+
+ self.compile_options_debug = [
+ '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG'
+@@ -233,11 +233,11 @@
+ ldflags = [
+ '/nologo', '/INCREMENTAL:NO', '/LTCG'
+ ]
+- if not self._vcruntime_redist:
+- ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib'))
++ #if not self._vcruntime_redist:
++ # ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib'))
+
+ ldflags_debug = [
+- '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL'
++ '/nologo', '/INCREMENTAL:NO', '/LTCG'
+ ]
+
+ self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1']
diff --git a/build_files/build_environment/patches/schroedinger.diff b/build_files/build_environment/patches/schroedinger.diff
new file mode 100644
index 00000000000..6acb35f2a7b
--- /dev/null
+++ b/build_files/build_environment/patches/schroedinger.diff
@@ -0,0 +1,54 @@
+--- configure.orig 2012-01-22 19:06:43 -0700
++++ configure 2016-04-06 20:00:50 -0600
+@@ -16492,10 +16492,10 @@
+ HAVE_ORC=yes
+ fi
+ if test "x${HAVE_ORC}" != xyes ; then
+- as_fn_error $? "orc-0.4 >= $ORC_VER is required" "$LINENO" 5
++ $as_echo "orc-0.4 >= $ORC_VER is required"
+ fi
+ SCHRO_PKG_DEPS="$SCHRO_PKG_DEPS orc-0.4 >= $ORC_VER"
+-ORCC=`$PKG_CONFIG --variable=orcc orc-0.4`
++#ORCC=`$PKG_CONFIG --variable=orcc orc-0.4`
+
+ if test "x$cross_compiling" != xyes; then
+ HAVE_ORCC_TRUE=
+--- Makefile.in 2012-01-22 18:06:42 -0700
++++ Makefile.in 2016-04-06 20:30:09 -0600
+@@ -291,7 +291,7 @@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+ AUTOMAKE_OPTIONS = foreign
+-SUBDIRS = schroedinger doc tools testsuite
++SUBDIRS = schroedinger doc tools
+ DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
+ DIST_SUBDIRS = schroedinger doc tools testsuite
+ EXTRA_DIST = COPYING COPYING.GPL COPYING.LGPL COPYING.MIT COPYING.MPL \
+
+--- schroedinger.pc.in 2011-03-21 17:08:39 -0600
++++ schroedinger.pc.in 2016-04-08 13:30:42 -0600
+@@ -7,9 +7,9 @@
+
+ Name: schroedinger-@SCHRO_MAJORMINOR@
+ Description: Dirac codec library
+-Requires.private: @SCHRO_PKG_DEPS@
++Requires: @SCHRO_PKG_DEPS@
+ Version: @VERSION@
+-Libs: -L${libdir} -lschroedinger-@SCHRO_MAJORMINOR@
++Libs: -L${libdir} -lschroedinger-@SCHRO_MAJORMINOR@ -lorc-0.4
+ Libs.private: @PTHREAD_LIBS@ @LIBM@
+ Cflags: -I${includedir}
+
+--- ./schroedinger/schrodecoder.c 2012-01-23 00:38:57.000000000 +0100
++++ ./schroedinger/schrodecoder.c 2016-05-15 06:07:24.000000000 +0200
+@@ -70,8 +70,8 @@
+ };
+
+
+-int _schro_decode_prediction_only;
+-int _schro_telemetry;
++int _schro_decode_prediction_only = 0;
++int _schro_telemetry = 0;
+
+ static void schro_decoder_x_decode_motion (SchroAsyncStage * stage);
+ static void schro_decoder_x_render_motion (SchroAsyncStage * stage);
diff --git a/build_files/build_environment/patches/sdl.diff b/build_files/build_environment/patches/sdl.diff
new file mode 100644
index 00000000000..b309d0230f3
--- /dev/null
+++ b/build_files/build_environment/patches/sdl.diff
@@ -0,0 +1,50 @@
+diff -ru /Users/brecht/dev/lib/deps/Downloads/SDL2-2.0.4/src/video/SDL_video.c ./src/video/SDL_video.c
+--- /Users/brecht/dev/lib/deps/Downloads/SDL2-2.0.4/src/video/SDL_video.c 2016-01-02 20:56:31.000000000 +0100
++++ ./src/video/SDL_video.c 2016-05-15 02:58:27.000000000 +0200
+@@ -137,7 +137,7 @@
+
+ #define FULLSCREEN_MASK (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN)
+
+-#ifdef __MACOSX__
++#if SDL_VIDEO_DRIVER_COCOA
+ /* Support for Mac OS X fullscreen spaces */
+ extern SDL_bool Cocoa_IsWindowInFullscreenSpace(SDL_Window * window);
+ extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state);
+@@ -1141,7 +1141,7 @@
+ if ( window->is_hiding && fullscreen )
+ return 0;
+
+-#ifdef __MACOSX__
++#if SDL_VIDEO_DRIVER_COCOA
+ /* if the window is going away and no resolution change is necessary,
+ do nothing, or else we may trigger an ugly double-transition
+ */
+@@ -2365,7 +2365,7 @@
+ return SDL_FALSE;
+ }
+
+-#ifdef __MACOSX__
++#if SDL_VIDEO_DRIVER_COCOA
+ if (Cocoa_IsWindowInFullscreenSpace(window)) {
+ return SDL_FALSE;
+ }
+--- CMakeLists.txt.old 2016-01-02 12:56:31 -0700
++++ CMakeLists.txt 2016-10-03 11:24:24 -0600
+@@ -609,7 +609,7 @@
+ list(APPEND EXTRA_LIBS m)
+ endif()
+
+- check_library_exists(iconv iconv_open "" HAVE_LIBICONV)
++ #check_library_exists(iconv iconv_open "" HAVE_LIBICONV)
+ if(HAVE_LIBICONV)
+ list(APPEND EXTRA_LIBS iconv)
+ set(HAVE_ICONV 1)
+@@ -1455,7 +1455,7 @@
+ set(_INSTALL_LIBS "SDL2main")
+
+ if(SDL_SHARED)
+- add_library(SDL2 SHARED ${SOURCE_FILES})
++ add_library(SDL2 SHARED ${SOURCE_FILES} ${VERSION_SOURCES})
+ if(UNIX)
+ set_target_properties(SDL2 PROPERTIES
+ VERSION ${LT_VERSION}
diff --git a/build_files/build_environment/patches/semi.txt b/build_files/build_environment/patches/semi.txt
new file mode 100644
index 00000000000..092bc2b0412
--- /dev/null
+++ b/build_files/build_environment/patches/semi.txt
@@ -0,0 +1 @@
+;
diff --git a/build_files/build_environment/windows/build_deps.cmd b/build_files/build_environment/windows/build_deps.cmd
new file mode 100644
index 00000000000..a18eb085e4f
--- /dev/null
+++ b/build_files/build_environment/windows/build_deps.cmd
@@ -0,0 +1,122 @@
+@echo off
+if NOT "%1" == "" (
+ if "%1" == "2013" (
+ echo "Building for VS2013"
+ set VSVER=12.0
+ set VSVER_SHORT=12
+ set BuildDir=VS12
+ goto par2
+ )
+ if "%1" == "2015" (
+ echo "Building for VS2015"
+ set VSVER=14.0
+ set VSVER_SHORT=14
+ set BuildDir=VS14
+ goto par2
+ )
+)
+:usage
+
+Echo Usage build_deps 2013/2015 x64/x86
+goto exit
+:par2
+if NOT "%2" == "" (
+ if "%2" == "x86" (
+ echo "Building for x86"
+ set HARVESTROOT=Windows_vc
+ set ARCH=86
+ if "%1" == "2013" (
+ set CMAKE_BUILDER=Visual Studio 12 2013
+ )
+ if "%1" == "2015" (
+ set CMAKE_BUILDER=Visual Studio 14 2015
+ )
+ goto start
+ )
+ if "%2" == "x64" (
+ echo "Building for x64"
+ set HARVESTROOT=Win64_vc
+ set ARCH=64
+ if "%1" == "2013" (
+ set CMAKE_BUILDER=Visual Studio 12 2013 Win64
+ )
+ if "%1" == "2015" (
+ set CMAKE_BUILDER=Visual Studio 14 2015 Win64
+ )
+ goto start
+ )
+)
+goto usage
+
+:start
+setlocal ENABLEEXTENSIONS
+set CMAKE_DEBUG_OPTIONS=-DWITH_OPTIMIZED_DEBUG=On
+if "%3" == "debug" set CMAKE_DEBUG_OPTIONS=-DWITH_OPTIMIZED_DEBUG=Off
+
+set SOURCE_DIR=%~dp0\..
+set BUILD_DIR=%cd%\build
+set HARVEST_DIR=%BUILD_DIR%\output
+set STAGING=%BUILD_DIR%\S
+
+rem for python module build
+set MSSdk=1
+set DISTUTILS_USE_SDK=1
+rem for python externals source to be shared between the various archs and compilers
+mkdir %BUILD_DIR%\downloads\externals
+
+REM Detect MSVC Installation
+if DEFINED VisualStudioVersion goto msvc_detect_finally
+set VALUE_NAME=ProductDir
+REM Check 64 bits
+set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%VSVER%\Setup\VC"
+for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
+if DEFINED MSVC_VC_DIR goto msvc_detect_finally
+REM Check 32 bits
+set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%VSVER%\Setup\VC"
+for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
+if DEFINED MSVC_VC_DIR goto msvc_detect_finally
+:msvc_detect_finally
+if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat"
+echo on
+
+REM Sanity Checks
+where /Q msbuild
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: "MSBuild" command not in the PATH.
+ echo You must have MSVC installed and run this from the "Developer Command Prompt"
+ echo ^(available from Visual Studio's Start menu entry^), aborting!
+ goto EOF
+)
+where /Q cmake
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: "CMake" command not in the PATH.
+ echo You must have CMake installed and added to your PATH, aborting!
+ goto EOF
+)
+
+set StatusFile=%BUILD_DIR%\%1_%2.log
+set path=%BUILD_DIR%\downloads\mingw\mingw64\msys\1.0\bin\;%BUILD_DIR%\downloads\nasm-2.12.01\;%path%
+mkdir %STAGING%\%BuildDir%%ARCH%R
+cd %Staging%\%BuildDir%%ARCH%R
+echo %DATE% %TIME% : Start > %StatusFile%
+cmake -G "%CMAKE_BUILDER%" %SOURCE_DIR% -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DBUILD_MODE=Release -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/
+echo %DATE% %TIME% : Release Configuration done >> %StatusFile%
+msbuild /m "ll.vcxproj" /p:Configuration=Release /fl /flp:logfile=BlenderDeps_llvm.log
+msbuild /m "BlenderDependencies.sln" /p:Configuration=Release /fl /flp:logfile=BlenderDeps.log
+echo %DATE% %TIME% : Release Build done >> %StatusFile%
+cmake --build . --target Harvest_Release_Results > Harvest_Release.txt
+echo %DATE% %TIME% : Release Harvest done >> %StatusFile%
+cd %BUILD_DIR%
+mkdir %STAGING%\%BuildDir%%ARCH%D
+cd %Staging%\%BuildDir%%ARCH%D
+cmake -G "%CMAKE_BUILDER%" %SOURCE_DIR% -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DCMAKE_BUILD_TYPE=Debug -DBUILD_MODE=Debug -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ %CMAKE_DEBUG_OPTIONS%
+echo %DATE% %TIME% : Debug Configuration done >> %StatusFile%
+msbuild /m "ll.vcxproj" /p:Configuration=Debug /fl /flp:logfile=BlenderDeps_llvm.log
+msbuild /m "BlenderDependencies.sln" /p:Configuration=Debug /fl /flp:logfile=BlenderDeps.log
+echo %DATE% %TIME% : Debug Build done >> %StatusFile%
+cmake --build . --target Harvest_Debug_Results> Harvest_Debug.txt
+echo %DATE% %TIME% : Debug Harvest done >> %StatusFile%
+cd %BUILD_DIR%
+
+:exit
+Echo .
diff --git a/build_files/build_environment/windows/buildall.cmd b/build_files/build_environment/windows/buildall.cmd
new file mode 100644
index 00000000000..480be8cde44
--- /dev/null
+++ b/build_files/build_environment/windows/buildall.cmd
@@ -0,0 +1,10 @@
+title building 1_4 - x86_2013
+call build_deps 2013 x86
+title building 2_4 - x86_2015
+call build_deps 2015 x86
+title building 3_4 - x64_2013
+call build_deps 2013 x64
+title building 4_4 - x64_2015
+call build_deps 2015 x64
+title done!
+echo done! \ No newline at end of file
diff --git a/build_files/build_environment/windows/nuke.cmd b/build_files/build_environment/windows/nuke.cmd
new file mode 100644
index 00000000000..68dbc8d1487
--- /dev/null
+++ b/build_files/build_environment/windows/nuke.cmd
@@ -0,0 +1,52 @@
+@echo off
+if "%1"=="" goto EOF:
+set ROOT=%~dp0\..\..\..\..\build_windows\deps
+
+set CurPath=%ROOT%\s\vs1264D\debug\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1264D\build\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1264R\release\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1264R\build\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\output\win64_vc12\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+
+set CurPath=%ROOT%\s\vs1464D\debug\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1464D\build\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1464R\release\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1464R\build\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\output\win64_vc14\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+
+set CurPath=%ROOT%\s\vs1286D\debug\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1286D\build\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1286R\release\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1286R\build\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\output\windows_vc12\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+
+set CurPath=%ROOT%\s\vs1486D\debug\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1486D\build\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1486R\release\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\s\vs1486R\build\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+set CurPath=%ROOT%\output\windows_vc14\%1\
+if EXIST %CurPath%\nul ( echo removing "%CurPath%" && rd /s /q "%CurPath%" )
+
+
+:EOF
+
+
diff --git a/build_files/buildbot/config/blender_linux.cmake b/build_files/buildbot/config/blender_linux.cmake
index 56f18967300..95265754d74 100644
--- a/build_files/buildbot/config/blender_linux.cmake
+++ b/build_files/buildbot/config/blender_linux.cmake
@@ -70,7 +70,7 @@ set(FFMPEG_LIBRARIES
)
# SndFile libraries
-set(SNDFILE_LIBRARY "/usr/lib/libsndfile.a;/usr/lib/libFLAC.a" CACHE STRING "" FORCE)
+set(SNDFILE_LIBRARY "/usr/lib${MULTILIB}/libsndfile.a;/usr/lib${MULTILIB}/libFLAC.a" CACHE STRING "" FORCE)
# OpenAL libraries
set(OPENAL_ROOT_DIR "/opt/lib/openal" CACHE STRING "" FORCE)
diff --git a/build_files/buildbot/config/blender_linux_player.cmake b/build_files/buildbot/config/blender_linux_player.cmake
index 2fb31192002..69ab984e386 100644
--- a/build_files/buildbot/config/blender_linux_player.cmake
+++ b/build_files/buildbot/config/blender_linux_player.cmake
@@ -1,4 +1,4 @@
-# This is applied as an ovveride on top of blender_linux.config
+# This is applied as an override on top of blender_linux.config
# Disables all the areas which are not needed for the player.
set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg
index c650cb8c302..dad7f1e01d2 100644
--- a/build_files/buildbot/master.cfg
+++ b/build_files/buildbot/master.cfg
@@ -312,15 +312,13 @@ def generic_builder(id, libdir='', branch='', rsync=False):
# Builders
-add_builder(c, 'mac_x86_64_10_6_cmake', 'darwin-9.x.universal', generic_builder, hour=5)
-# add_builder(c, 'linux_glibc211_i686_cmake', '', generic_builder, hour=1)
-# add_builder(c, 'linux_glibc211_x86_64_cmake', '', generic_builder, hour=2)
-add_builder(c, 'linux_glibc219_i686_cmake', '', generic_builder, hour=3)
-add_builder(c, 'linux_glibc219_x86_64_cmake', '', generic_builder, hour=4)
-add_builder(c, 'win32_cmake_vc2013', 'windows_vc12', generic_builder, hour=3)
-add_builder(c, 'win64_cmake_vc2013', 'win64_vc12', generic_builder, hour=4)
-add_builder(c, 'win32_cmake_vc2015', 'windows_vc14', generic_builder, hour=5)
-add_builder(c, 'win64_cmake_vc2015', 'win64_vc14', generic_builder, hour=6)
+add_builder(c, 'mac_x86_64_10_6_cmake', 'darwin-9.x.universal', generic_builder, hour=1)
+add_builder(c, 'linux_glibc219_i686_cmake', '', generic_builder, hour=2)
+add_builder(c, 'linux_glibc219_x86_64_cmake', '', generic_builder, hour=1)
+add_builder(c, 'win32_cmake_vc2013', 'windows_vc12', generic_builder, hour=1)
+add_builder(c, 'win64_cmake_vc2013', 'win64_vc12', generic_builder, hour=2)
+add_builder(c, 'win32_cmake_vc2015', 'windows_vc14', generic_builder, hour=3)
+add_builder(c, 'win64_cmake_vc2015', 'win64_vc14', generic_builder, hour=4)
# STATUS TARGETS
#
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index 0e264a752d5..d99e66f7871 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -112,8 +112,8 @@ if 'cmake' in builder:
chroot_name = 'buildbot_' + deb_name + '_i686'
cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64'
targets = ['player', 'blender', 'cuda']
- cmake_extra_options.extend(["-DCMAKE_C_COMPILER=/usr/bin/gcc-6",
- "-DCMAKE_CXX_COMPILER=/usr/bin/g++-6"])
+ cmake_extra_options.extend(["-DCMAKE_C_COMPILER=/usr/bin/gcc-7",
+ "-DCMAKE_CXX_COMPILER=/usr/bin/g++-7"])
cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file))
diff --git a/build_files/cmake/Modules/FindOpenCOLLADA.cmake b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
index 1c10d5a71de..63bc520ea15 100644
--- a/build_files/cmake/Modules/FindOpenCOLLADA.cmake
+++ b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
@@ -83,6 +83,7 @@ FOREACH(COMPONENT ${_opencollada_FIND_INCLUDES})
# but this is less trouble, just looks strange.
include/opencollada/${COMPONENT}
include/${COMPONENT}/include
+ include/${COMPONENT}
HINTS
${_opencollada_SEARCH_DIRS}
)
diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py
index 3d06790758a..443657532de 100755
--- a/build_files/cmake/cmake_consistency_check.py
+++ b/build_files/cmake/cmake_consistency_check.py
@@ -61,10 +61,8 @@ def replace_line(f, i, text, keep_indent=True):
def source_list(path, filename_check=None):
for dirpath, dirnames, filenames in os.walk(path):
-
# skip '.git'
- if dirpath.startswith("."):
- continue
+ dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
if filename_check is None or filename_check(filename):
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 6105f2e04de..00c5772e11c 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -93,7 +93,11 @@ if(WITH_PYTHON)
# 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)
+ if(WITH_CXX11)
+ set(PYTHON_LIBRARY ${LIBDIR}/python/lib/libpython${PYTHON_VERSION}m.a)
+ else()
+ set(PYTHON_LIBRARY python${PYTHON_VERSION}m)
+ endif()
set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
# set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled
else()
@@ -113,6 +117,9 @@ if(WITH_PYTHON)
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
+ # needed for Audaspace, numpy is installed into python site-packages
+ set(NUMPY_INCLUDE_DIRS "${PYTHON_LIBPATH}/site-packages/numpy/core/include")
+
if(NOT EXISTS "${PYTHON_EXECUTABLE}")
message(FATAL_ERROR "Python executable missing: ${PYTHON_EXECUTABLE}")
endif()
diff --git a/build_files/cmake/platform/platform_win32_msvc.cmake b/build_files/cmake/platform/platform_win32_msvc.cmake
index 2055b164f6d..1b596e3d932 100644
--- a/build_files/cmake/platform/platform_win32_msvc.cmake
+++ b/build_files/cmake/platform/platform_win32_msvc.cmake
@@ -134,7 +134,10 @@ if(NOT DEFINED LIBDIR)
message(STATUS "32 bit compiler detected.")
set(LIBDIR_BASE "windows")
endif()
- if(MSVC_VERSION EQUAL 1910)
+ if(MSVC_VERSION EQUAL 1911)
+ message(STATUS "Visual Studio 2017 detected.")
+ set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14)
+ elseif(MSVC_VERSION EQUAL 1910)
message(STATUS "Visual Studio 2017 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14)
elseif(MSVC_VERSION EQUAL 1900)
@@ -452,20 +455,21 @@ if(WITH_MOD_CLOTH_ELTOPO)
endif()
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
- set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include)
- set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
- set(OPENSUBDIV_LIBRARIES optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
- optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
- debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
- debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
- )
- set(OPENSUBDIV_HAS_OPENMP TRUE)
+ set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include)
+ set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
+ set(OPENSUBDIV_LIBRARIES
+ optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
+ optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
+ debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
+ debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
+ )
+ set(OPENSUBDIV_HAS_OPENMP TRUE)
set(OPENSUBDIV_HAS_TBB FALSE)
set(OPENSUBDIV_HAS_OPENCL TRUE)
set(OPENSUBDIV_HAS_CUDA FALSE)
set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
- windows_find_package(OpenSubdiv)
+ windows_find_package(OpenSubdiv)
endif()
if(WITH_SDL)
@@ -488,14 +492,14 @@ 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 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/"
+ 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/build_files/cmake/project_info.py b/build_files/cmake/project_info.py
index 3ac4c4c9480..9b0905da030 100755
--- a/build_files/cmake/project_info.py
+++ b/build_files/cmake/project_info.py
@@ -84,10 +84,8 @@ def init(cmake_path):
def source_list(path, filename_check=None):
for dirpath, dirnames, filenames in os.walk(path):
-
- # skip '.svn'
- if dirpath.startswith("."):
- continue
+ # skip '.git'
+ dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
filepath = join(dirpath, filename)
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index 8b3a97816ba..a3ccf9227d3 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.8x"
+PROJECT_NUMBER = "V2.79"
# 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/examples/bpy.app.translations.py b/doc/python_api/examples/bpy.app.translations.py
index e41623d2885..4256147ef31 100644
--- a/doc/python_api/examples/bpy.app.translations.py
+++ b/doc/python_api/examples/bpy.app.translations.py
@@ -32,3 +32,62 @@ Module References
-----------------
"""
+
+import bpy
+
+# This block can be automatically generated by UI translations addon, which also handles conversion with PO format.
+# See also https://wiki.blender.org/index.php/Dev:Doc/Process/Translate_Blender#Translating_non-official_addons
+# It can (should) also be put in a different, specific py file.
+
+# ##### BEGIN AUTOGENERATED I18N SECTION #####
+# NOTE: You can safely move around this auto-generated block (with the begin/end markers!),
+# and edit the translations by hand.
+# Just carefully respect the format of the tuple!
+
+# Tuple of tuples ((msgctxt, msgid), (sources, gen_comments), (lang, translation, (is_fuzzy, comments)), ...)
+translations_tuple = (
+ (("*", ""),
+ ((), ()),
+ ("fr_FR", "Project-Id-Version: Copy Settings 0.1.5 (r0)\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-04-18 15:27:45.563524\nPO-Revision-Date: 2013-04-18 15:38+0100\nLast-Translator: Bastien Montagne <montagne29@wanadoo.fr>\nLanguage-Team: LANGUAGE <LL@li.org>\nLanguage: __POT__\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\n",
+ (False,
+ ("Blender's translation file (po format).",
+ "Copyright (C) 2013 The Blender Foundation.",
+ "This file is distributed under the same license as the Blender package.",
+ "FIRST AUTHOR <EMAIL@ADDRESS>, YEAR."))),
+ ),
+ (("Operator", "Render: Copy Settings"),
+ (("bpy.types.SCENE_OT_render_copy_settings",),
+ ()),
+ ("fr_FR", "Rendu : copier réglages",
+ (False, ())),
+ ),
+ (("*", "Copy render settings from current scene to others"),
+ (("bpy.types.SCENE_OT_render_copy_settings",),
+ ()),
+ ("fr_FR", "Copier les réglages de rendu depuis la scène courante vers d’autres",
+ (False, ())),
+ ),
+ # ... etc, all messages from your addon.
+)
+
+translations_dict = {}
+for msg in translations_tuple:
+ key = msg[0]
+ for lang, trans, (is_fuzzy, comments) in msg[2:]:
+ if trans and not is_fuzzy:
+ translations_dict.setdefault(lang, {})[key] = trans
+
+# ##### END AUTOGENERATED I18N SECTION #####
+
+# Define remaining addon (operators, UI...) here.
+
+def register():
+ # Usual operator/UI/etc. registration...
+
+ bpy.app.translations.register(__name__, translations_dict)
+
+
+def unregister():
+ bpy.app.translations.unregister(__name__)
+
+ # Usual operator/UI/etc. unregistration...
diff --git a/doc/python_api/examples/bpy.types.Operator.5.py b/doc/python_api/examples/bpy.types.Operator.5.py
index 310eeceadf3..c1a49a756a0 100644
--- a/doc/python_api/examples/bpy.types.Operator.5.py
+++ b/doc/python_api/examples/bpy.types.Operator.5.py
@@ -2,13 +2,14 @@
Modal Execution
+++++++++++++++
-This operator defines a :class:`Operator.modal` function which running,
-handling events until it returns ``{'FINISHED'}`` or ``{'CANCELLED'}``.
-
-Grab, Rotate, Scale and Fly-Mode are examples of modal operators.
-They are especially useful for interactive tools,
-your operator can have its own state where keys toggle options as the operator
-runs.
+This operator defines a :class:`Operator.modal` function that will keep being
+run to handle events until it returns ``{'FINISHED'}`` or ``{'CANCELLED'}``.
+
+Modal operators run every time a new event is detected, such as a mouse click
+or key press. Conversely, when no new events are detected, the modal operator
+will not run. Modal operators are especially useful for interactive tools, an
+operator can have its own state where keys toggle options as the operator runs.
+Grab, Rotate, Scale, and Fly-Mode are examples of modal operators.
:class:`Operator.invoke` is used to initialize the operator as being by
returning ``{'RUNNING_MODAL'}``, initializing the modal loop.
diff --git a/doc/python_api/rst/bge.app.rst b/doc/python_api/rst/bge.app.rst
index 34b9263db0c..e8b91ffbcaf 100644
--- a/doc/python_api/rst/bge.app.rst
+++ b/doc/python_api/rst/bge.app.rst
@@ -47,4 +47,3 @@ Module to access application values that remain unchanged during runtime.
True if the BGE has been built with physics support.
:type: bool
-
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst b/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst
index d08a761ed95..4bb3d273cb9 100644
--- a/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst
+++ b/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst
@@ -59,7 +59,7 @@ base class --- :class:`SCA_IActuator`
.. attribute:: mode
- The operation mode of the actuator. Can be one of :ref:`these constants<shape-action-actuator>`.
+ The operation mode of the actuator. Can be one of :ref:`these constants<action-actuator>`.
:type: integer
@@ -68,5 +68,3 @@ base class --- :class:`SCA_IActuator`
The name of the property that is set to the current frame number.
:type: string
-
-
diff --git a/doc/python_api/rst/gpu.rst b/doc/python_api/rst/gpu.rst
index 6c38122a573..cf639357a31 100644
--- a/doc/python_api/rst/gpu.rst
+++ b/doc/python_api/rst/gpu.rst
@@ -6,6 +6,13 @@ GPU functions (gpu)
This module provides access to materials GLSL shaders.
+Submodules:
+
+.. toctree::
+ :maxdepth: 1
+
+ gpu.offscreen.rst
+
Intro
=====
@@ -24,7 +31,6 @@ and in the game engine.
Constants
=========
-
GLSL Data Type
--------------
diff --git a/doc/python_api/rst/include__bmesh.rst b/doc/python_api/rst/include__bmesh.rst
index 83e3e73cea4..bed374bf7b6 100644
--- a/doc/python_api/rst/include__bmesh.rst
+++ b/doc/python_api/rst/include__bmesh.rst
@@ -7,14 +7,17 @@
Submodules:
-* :mod:`bmesh.ops`
-* :mod:`bmesh.types`
-* :mod:`bmesh.utils`
-* :mod:`bmesh.geometry`
+.. toctree::
+ :maxdepth: 1
+ bmesh.ops.rst
+ bmesh.types.rst
+ bmesh.utils.rst
+ bmesh.geometry.rst
-Intro
------
+
+Introduction
+------------
This API gives access the blenders internal mesh editing api, featuring geometry connectivity data and
access to editing operations such as split, separate, collapse and dissolve.
diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst
index ba2e6949b81..721374cd472 100644
--- a/doc/python_api/rst/info_overview.rst
+++ b/doc/python_api/rst/info_overview.rst
@@ -5,23 +5,25 @@
Python API Overview
*******************
-This document is to give an understanding of how Python and Blender fit together,
-covering some of the functionality that isn't obvious from reading the API reference and example scripts.
+The purpose of this document is to explain how Python and Blender fit together,
+covering some of the functionality that may not be obvious from reading the API
+references and example scripts.
Python in Blender
=================
-Blender embeds a Python interpreter which is started with Blender and stays active.
-This interpreter runs scripts to draw the user interface and is used for some of Blender's internal tools too.
+Blender has an embedded Python interpreter which is loaded when Blender is started and stays
+active while Blender is running. This interpreter runs scripts to draw the user interface
+and is used for some of Blender’s internal tools as well.
-This is a typical Python environment so tutorials on how to write Python scripts
-will work running the scripts in Blender too.
-Blender provides the :mod:`bpy` module to the Python interpreter.
-This module can be imported in a script and gives access to Blender data, classes, and functions.
-Scripts that deal with Blender data will need to import this module.
+Blender's embedded interpreter provides a typical Python environment, so code from tutorials
+on how to write Python scripts can also be run with Blender’s interpreter. Blender provides its
+Python modules, such as :mod:`bpy` and :mod:`mathutils`, to the embedded interpreter so they can
+be imported into a script and give access to Blender's data, classes, and functions. Scripts that
+deal with Blender data will need to import the modules to work.
-Here is a simple example of moving a vertex of the object named **Cube**:
+Here is a simple example which moves a vertex attached to an object named **Cube**:
.. code-block:: python
@@ -49,15 +51,17 @@ See the :ref:`directory layout docs <blender_manual:getting-started_installing-c
Script Loading
==============
-This may seem obvious but it's important to note the difference
-between executing a script directly or importing it as a module.
+This may seem obvious, but it is important to note the difference between
+executing a script directly and importing a script as a module.
-Scripts that extend Blender - define classes that exist beyond the scripts execution,
-this makes future access to these classes (to unregister for example)
-more difficult than importing as a module where class instance is kept
-in the module and can be accessed by importing that module later on.
+Extending Blender by executing a script directly means the classes that the script
+defines remain available inside Blender after the script finishes execution.
+Using scripts this way makes future access to their classes
+(to unregister them for example) more difficult compared to importing the scripts as modules.
+When a script is imported as a module, its class instances will remain
+inside the module and can be accessed later on by importing that module again.
-For this reason it's preferable to only use directly execute scripts that don't extend Blender by registering classes.
+For this reason it is preferable to avoid directly executing scripts that extend Blender by registering classes.
Here are some ways to run scripts directly in Blender.
@@ -396,8 +400,8 @@ This works just as well for PropertyGroup subclasses you define yourself.
Dynamic Defined-Classes (Advanced)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-In some cases the specifier for data may not be in Blender,
-renderman shader definitions for example and it may be useful to define types and remove them on the fly.
+In some cases the specifier for data may not be in Blender, renderman shader definitions
+for example, and it may be useful to define them as types and remove them on the fly.
.. code-block:: python
@@ -420,7 +424,7 @@ renderman shader definitions for example and it may be useful to define types an
This is an alternative syntax for class creation in Python, better suited to constructing classes dynamically.
-Calling these operators:
+To call the operators from the previous example:
>>> bpy.ops.object.operator_1()
Hello World OBJECT_OT_operator_1
diff --git a/doc/python_api/rst/info_tutorial_addon.rst b/doc/python_api/rst/info_tutorial_addon.rst
deleted file mode 100644
index 92fbf9b8787..00000000000
--- a/doc/python_api/rst/info_tutorial_addon.rst
+++ /dev/null
@@ -1,635 +0,0 @@
-
-Add-on Tutorial
-###############
-
-************
-Introduction
-************
-
-
-Intended Audience
-=================
-
-This tutorial is designed to help technical artists or developers learn to extend Blender.
-An understanding of the basics of Python is expected for those working through this tutorial.
-
-
-Prerequisites
--------------
-
-Before going through the tutorial you should...
-
-- Familiarity with the basics of working in Blender.
-- Know how to run a script in Blender's text editor (as documented in the quick-start)
-- Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set).
-- Be familiar with the concept of Python modules.
-- Basic understanding of classes (object orientation) in Python.
-
-
-Suggested reading before starting this tutorial.
-
-- `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ sections (1, 2, 3, 4, and 7).
-- :ref:`Blender API Quickstart <info_quickstart>`
- to help become familiar with Blender/Python basics.
-
-
-To best troubleshoot any error message Python prints while writing scripts you run blender with from a terminal,
-see :ref:`Use The Terminal <use_the_terminal>`.
-
-
-Documentation Links
-===================
-
-While going through the tutorial you may want to look into our reference documentation.
-
-- :ref:`Blender API Overview <info_overview>`. -
- *This document is rather detailed but helpful if you want to know more on a topic.*
-- :mod:`bpy.context` api reference. -
- *Handy to have a list of available items your script may operate on.*
-- :class:`bpy.types.Operator`. -
- *The following add-ons define operators, these docs give details and more examples of operators.*
-
-
-*******
-Add-ons
-*******
-
-What is an Add-on?
-==================
-
-An add-on is simply a Python module with some additional requirements so Blender can display it in a list with useful
-information.
-
-To give an example, here is the simplest possible add-on.
-
-.. code-block:: python
-
- bl_info = {"name": "My Test Add-on", "category": "Object"}
- def register():
- print("Hello World")
- def unregister():
- print("Goodbye World")
-
-
-- ``bl_info`` is a dictionary containing add-on metadata such as the title,
- version and author to be displayed in the user preferences add-on list.
-- ``register`` is a function which only runs when enabling the add-on,
- this means the module can be loaded without activating the add-on.
-- ``unregister`` is a function to unload anything setup by ``register``, this is called when the add-on is disabled.
-
-
-Notice this add-on does not do anything related to Blender, (the :mod:`bpy` module is not imported for example).
-
-This is a contrived example of an add-on that serves to illustrate the point
-that the base requirements of an add-on are simple.
-
-An add-on will typically register operators, panels, menu items etc, but its worth noting that _any_ script can do this,
-when executed from the text editor or even the interactive console - there is nothing inherently different about an
-add-on that allows it to integrate with Blender, such functionality is just provided by the :mod:`bpy` module for any
-script to access.
-
-So an add-on is just a way to encapsulate a Python module in a way a user can easily utilize.
-
-.. note::
-
- Running this script within the text editor won't print anything,
- to see the output it must be installed through the user preferences.
- Messages will be printed when enabling and disabling.
-
-
-Your First Add-on
-=================
-
-The simplest possible add-on above is useful as an example but not much else.
-This next add-on is simple but shows how to integrate a script into Blender using an ``Operator``
-which is the typical way to define a tool accessed from menus, buttons and keyboard shortcuts.
-
-For the first example we will make a script that simply moves all objects in a scene.
-
-
-Write The Script
-----------------
-
-Add the following script to the text editor in Blender.
-
-.. code-block:: python
-
- import bpy
-
- scene = bpy.context.scene
- for obj in scene.objects:
- obj.location.x += 1.0
-
-
-Click the :ref:`Run Script button <blender_manual:editors-text-run-script>`,
-all objects in the active scene are moved by 1.0 Blender unit.
-
-
-Write the Add-on (Simple)
--------------------------
-
-This add-on takes the body of the script above, and adds them to an operator's ``execute()`` function.
-
-
-.. code-block:: python
-
- bl_info = {
- "name": "Move X Axis",
- "category": "Object",
- }
-
- import bpy
-
-
- class ObjectMoveX(bpy.types.Operator):
- """My Object Moving Script""" # blender will use this as a tooltip for menu items and buttons.
- bl_idname = "object.move_x" # unique identifier for buttons and menu items to reference.
- bl_label = "Move X by One" # display name in the interface.
- bl_options = {'REGISTER', 'UNDO'} # enable undo for the operator.
-
- def execute(self, context): # execute() is called by blender when running the operator.
-
- # The original script
- scene = context.scene
- for obj in scene.objects:
- obj.location.x += 1.0
-
- return {'FINISHED'} # this lets blender know the operator finished successfully.
-
- def register():
- bpy.utils.register_class(ObjectMoveX)
-
-
- def unregister():
- bpy.utils.unregister_class(ObjectMoveX)
-
-
- # This allows you to run the script directly from blenders text editor
- # to test the add-on without having to install it.
- if __name__ == "__main__":
- register()
-
-
-.. note::
-
- ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items.
-
-.. note::
-
- Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``.
- In most cases these will be the same however in some cases operators will be passed a custom context
- so script authors should prefer the ``context`` argument passed to operators.
-
-To test the script you can copy and paste this into Blender text editor and run it, this will execute the script
-directly and call register immediately.
-
-However running the script wont move any objects, for this you need to execute the newly registered operator.
-
-.. image:: spacebar.png
- :width: 924px
- :align: center
- :height: 574px
- :alt: Spacebar
-
-Do this by pressing :kbd:`Spacebar` to bring up the operator search dialog and type in
-"Move X by One" (the ``bl_label``), then :kbd:`Enter`.
-
-
-
-The objects should move as before.
-
-*Keep this add-on open in Blender for the next step - Installing.*
-
-
-Install The Add-on
-------------------
-
-Once you have your add-on within in Blender's text editor,
-you will want to be able to install it so it can be enabled in the user preferences to load on startup.
-
-Even though the add-on above is a test, lets go through the steps anyway so you know how to do it for later.
-
-To install the Blender text as an add-on you will first have to save it to disk, take care to obey the naming
-restrictions that apply to Python modules and end with a ``.py`` extension.
-
-Once the file is on disk, you can install it as you would for an add-on downloaded online.
-
-Open the user :menuselection:`File --> User Preferences`,
-Select the *Add-on* section, press *Install Add-on...* and select the file.
-
-Now the add-on will be listed and you can enable it by pressing the check-box,
-if you want it to be enabled on restart, press *Save as Default*.
-
-.. note::
-
- The destination of the add-on depends on your Blender configuration.
- When installing an add-on the source and destination path are printed in the console.
- You can also find add-on path locations by running this in the Python console.
-
- .. code-block:: python
-
- import addon_utils
- print(addon_utils.paths())
-
- More is written on this topic here:
- :ref:`Directory Layout <blender_manual:getting-started_installing-config-directories>`.
-
-
-Your Second Add-on
-==================
-
-For our second add-on, we will focus on object instancing - this is - to make linked copies of an object in a
-similar way to what you may have seen with the array modifier.
-
-
-Write The Script
-----------------
-
-As before, first we will start with a script, develop it, then convert into an add-on.
-
-.. code-block:: python
-
- import bpy
- from bpy import context
-
- # Get the current scene
- scene = context.scene
-
- # Get the 3D cursor
- cursor = scene.cursor_location
-
- # Get the active object (assume we have one)
- obj = scene.objects.active
-
- # Now make a copy of the object
- obj_new = obj.copy()
-
- # The object won't automatically get into a new scene
- scene.objects.link(obj_new)
-
- # Now we can place the object
- obj_new.location = cursor
-
-
-Now try copy this script into Blender and run it on the default cube.
-Make sure you click to move the 3D cursor before running as the duplicate will appear at the cursor's location.
-
-
-... go off and test ...
-
-
-After running, notice that when you go into edit-mode to change the cube - all of the copies change,
-in Blender this is known as *Linked-Duplicates*.
-
-
-Next, we're going to do this in a loop, to make an array of objects between the active object and the cursor.
-
-
-.. code-block:: python
-
- import bpy
- from bpy import context
-
- scene = context.scene
- cursor = scene.cursor_location
- obj = scene.objects.active
-
- # Use a fixed value for now, eventually make this user adjustable
- total = 10
-
- # Add 'total' objects into the scene
- for i in range(total):
- obj_new = obj.copy()
- scene.objects.link(obj_new)
-
- # Now place the object in between the cursor
- # and the active object based on 'i'
- factor = i / total
- obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
-
-
-Try run this script with with the active object and the cursor spaced apart to see the result.
-
-With this script you'll notice we're doing some math with the object location and cursor, this works because both are
-3D :class:`mathutils.Vector` instances, a convenient class provided by the :mod:`mathutils` module and
-allows vectors to be multiplied by numbers and matrices.
-
-If you are interested in this area, read into :class:`mathutils.Vector` - there are many handy utility functions
-such as getting the angle between vectors, cross product, dot products
-as well as more advanced functions in :mod:`mathutils.geometry` such as Bézier Spline interpolation and
-ray-triangle intersection.
-
-For now we will focus on making this script an add-on, but its good to know that this 3D math module is available and
-can help you with more advanced functionality later on.
-
-
-Write the Add-on
-----------------
-
-The first step is to convert the script as-is into an add-on.
-
-
-.. code-block:: python
-
- bl_info = {
- "name": "Cursor Array",
- "category": "Object",
- }
-
- import bpy
-
-
- class ObjectCursorArray(bpy.types.Operator):
- """Object Cursor Array"""
- bl_idname = "object.cursor_array"
- bl_label = "Cursor Array"
- bl_options = {'REGISTER', 'UNDO'}
-
- def execute(self, context):
- scene = context.scene
- cursor = scene.cursor_location
- obj = scene.objects.active
-
- total = 10
-
- for i in range(total):
- obj_new = obj.copy()
- scene.objects.link(obj_new)
-
- factor = i / total
- obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
-
- return {'FINISHED'}
-
- def register():
- bpy.utils.register_class(ObjectCursorArray)
-
-
- def unregister():
- bpy.utils.unregister_class(ObjectCursorArray)
-
-
- if __name__ == "__main__":
- register()
-
-
-Everything here has been covered in the previous steps, you may want to try run the add-on still
-and consider what could be done to make it more useful.
-
-
-... go off and test ...
-
-
-The two of the most obvious missing things are - having the total fixed at 10, and having to access the operator from
-space-bar is not very convenient.
-
-Both these additions are explained next, with the final script afterwards.
-
-
-Operator Property
-^^^^^^^^^^^^^^^^^
-
-There are a variety of property types that are used for tool settings, common property types include:
-int, float, vector, color, boolean and string.
-
-These properties are handled differently to typical Python class attributes
-because Blender needs to be display them in the interface,
-store their settings in key-maps and keep settings for re-use.
-
-While this is handled in a fairly Pythonic way, be mindful that you are in fact defining tool settings that
-are loaded into Blender and accessed by other parts of Blender, outside of Python.
-
-
-To get rid of the literal 10 for `total`, we'll us an operator property.
-Operator properties are defined via bpy.props module, this is added to the class body.
-
-.. code-block:: python
-
- # moved assignment from execute() to the body of the class...
- total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
-
- # and this is accessed on the class
- # instance within the execute() function as...
- self.total
-
-
-These properties from :mod:`bpy.props` are handled specially by Blender when the class is registered
-so they display as buttons in the user interface.
-There are many arguments you can pass to properties to set limits, change the default and display a tooltip.
-
-.. seealso:: :mod:`bpy.props.IntProperty`
-
-This document doesn't go into details about using other property types,
-however the link above includes examples of more advanced property usage.
-
-
-Menu Item
-^^^^^^^^^
-
-Add-ons can add to the user interface of existing panels, headers and menus defined in Python.
-
-For this example we'll add to an existing menu.
-
-.. image:: menu_id.png
- :width: 334px
- :align: center
- :height: 128px
- :alt: Menu Identifier
-
-To find the identifier of a menu you can hover your mouse over the menu item and the identifier is displayed.
-
-The method used for adding a menu item is to append a draw function into an existing class.
-
-
-.. code-block:: python
-
- def menu_func(self, context):
- self.layout.operator(ObjectCursorArray.bl_idname)
-
- def register():
- bpy.types.VIEW3D_MT_object.append(menu_func)
-
-
-For docs on extending menus see: :doc:`bpy.types.Menu`.
-
-
-Keymap
-^^^^^^
-
-In Blender, add-ons have their own keymaps so as not to interfere with Blenders built in key-maps.
-
-In the example below, a new object-mode :class:`bpy.types.KeyMap` is added,
-then a :class:`bpy.types.KeyMapItem` is added to the key-map which references our newly added operator,
-using :kbd:`Ctrl-Shift-Space` as the key shortcut to activate it.
-
-
-.. code-block:: python
-
- # store keymaps here to access after registration
- addon_keymaps = []
-
- def register():
-
- # handle the keymap
- wm = bpy.context.window_manager
- km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
-
- kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
- kmi.properties.total = 4
-
- addon_keymaps.append((km, kmi))
-
-
- def unregister():
-
- # handle the keymap
- for km, kmi in addon_keymaps:
- km.keymap_items.remove(kmi)
- addon_keymaps.clear()
-
-
-Notice how the key-map item can have a different ``total`` setting then the default set by the operator,
-this allows you to have multiple keys accessing the same operator with different settings.
-
-
-.. note::
-
- While :kbd:`Ctrl-Shift-Space` isn't a default Blender key shortcut, its hard to make sure add-ons won't
- overwrite each others keymaps, At least take care when assigning keys that they don't
- conflict with important functionality within Blender.
-
-For API documentation on the functions listed above, see:
-:class:`bpy.types.KeyMaps.new`,
-:class:`bpy.types.KeyMap`,
-:class:`bpy.types.KeyMapItems.new`,
-:class:`bpy.types.KeyMapItem`.
-
-
-Bringing it all together
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. code-block:: python
-
- bl_info = {
- "name": "Cursor Array",
- "category": "Object",
- }
-
- import bpy
-
-
- class ObjectCursorArray(bpy.types.Operator):
- """Object Cursor Array"""
- bl_idname = "object.cursor_array"
- bl_label = "Cursor Array"
- bl_options = {'REGISTER', 'UNDO'}
-
- total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
-
- def execute(self, context):
- scene = context.scene
- cursor = scene.cursor_location
- obj = scene.objects.active
-
- for i in range(self.total):
- obj_new = obj.copy()
- scene.objects.link(obj_new)
-
- factor = i / self.total
- obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
-
- return {'FINISHED'}
-
-
- def menu_func(self, context):
- self.layout.operator(ObjectCursorArray.bl_idname)
-
- # store keymaps here to access after registration
- addon_keymaps = []
-
-
- def register():
- bpy.utils.register_class(ObjectCursorArray)
- bpy.types.VIEW3D_MT_object.append(menu_func)
-
- # handle the keymap
- wm = bpy.context.window_manager
- # Note that in background mode (no GUI available), keyconfigs are not available either, so we have to check this
- # to avoid nasty errors in background case.
- kc = wm.keyconfigs.addon
- if kc:
- km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
- kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
- kmi.properties.total = 4
- addon_keymaps.append((km, kmi))
-
- def unregister():
- # Note: when unregistering, it's usually good practice to do it in reverse order you registered.
- # Can avoid strange issues like keymap still referring to operators already unregistered...
- # handle the keymap
- for km, kmi in addon_keymaps:
- km.keymap_items.remove(kmi)
- addon_keymaps.clear()
-
- bpy.utils.unregister_class(ObjectCursorArray)
- bpy.types.VIEW3D_MT_object.remove(menu_func)
-
-
- if __name__ == "__main__":
- register()
-
-.. image:: in_menu.png
- :width: 591px
- :align: center
- :height: 649px
- :alt: In the menu
-
-Run the script (or save it and add it through the Preferences like before) and it will appear in the menu.
-
-.. image:: op_prop.png
- :width: 669px
- :align: center
- :height: 644px
- :alt: Operator Property
-
-After selecting it from the menu, you can choose how many instance of the cube you want created.
-
-
-.. note::
-
- Directly executing the script multiple times will add the menu each time too.
- While not useful behavior, theres nothing to worry about since add-ons won't register them selves multiple
- times when enabled through the user preferences.
-
-
-Conclusions
-===========
-
-Add-ons can encapsulate certain functionality neatly for writing tools to improve your work-flow or for writing utilities
-for others to use.
-
-While there are limits to what Python can do within Blender, there is certainly a lot that can be achieved without
-having to dive into Blender's C/C++ code.
-
-The example given in the tutorial is limited, but shows the Blender API used for common tasks that you can expand on
-to write your own tools.
-
-
-Further Reading
----------------
-
-Blender comes commented templates which are accessible from the text editor header, if you have specific areas
-you want to see example code for, this is a good place to start.
-
-
-Here are some sites you might like to check on after completing this tutorial.
-
-- :ref:`Blender/Python API Overview <info_overview>` -
- *For more background details on Blender/Python integration.*
-- `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
- *Great info for those who are still learning Python.*
-- `Blender Development (Wiki) <https://wiki.blender.org/index.php/Dev:Contents>`_ -
- *Blender Development, general information and helpful links.*
-- `Blender Artists (Coding Section) <https://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
- *forum where people ask Python development questions*
-
diff --git a/doc/python_api/rst_from_bmesh_opdefines.py b/doc/python_api/rst_from_bmesh_opdefines.py
index cdbed88cc88..d3e4b2a0cfd 100644
--- a/doc/python_api/rst_from_bmesh_opdefines.py
+++ b/doc/python_api/rst_from_bmesh_opdefines.py
@@ -22,7 +22,7 @@
# 'bmesh_opdefines.c' in order to avoid having to add a lot of introspection
# data access into the api.
#
-# The script is stupid becase it makes assumptions about formatting...
+# The script is stupid because it makes assumptions about formatting...
# that each arg has its own line, that comments above or directly after will be __doc__ etc...
#
# We may want to replace this script with something else one day but for now its good enough.
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 47bb323e574..08c3e729ed9 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -341,6 +341,8 @@ EXTRA_SOURCE_FILES = (
"../examples/bge.texture.py",
"../examples/bmesh.ops.1.py",
"../examples/bpy.app.translations.py",
+ "../static/favicon.ico",
+ "../static/blender_logo.svg",
)
@@ -362,8 +364,6 @@ INFO_DOCS = (
"Blender/Python Quickstart: new to Blender/scripting and want to get your feet wet?"),
("info_overview.rst",
"Blender/Python API Overview: a more complete explanation of Python integration"),
- ("info_tutorial_addon.rst",
- "Blender/Python Add-on Tutorial: a step by step guide on how to write an add-on from scratch"),
("info_api_reference.rst",
"Blender/Python API Reference Usage: examples of how to use the API reference docs"),
("info_best_practice.rst",
@@ -1010,9 +1010,9 @@ def pymodule2sphinx(basepath, module_name, module, title):
context_type_map = {
"active_base": ("ObjectBase", False),
"active_bone": ("EditBone", False),
+ "active_gpencil_brush": ("GPencilSculptBrush", 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),
@@ -1063,6 +1063,7 @@ context_type_map = {
"selected_bones": ("EditBone", True),
"selected_editable_bases": ("ObjectBase", True),
"selected_editable_bones": ("EditBone", True),
+ "selected_editable_fcurves": ("FCurce", True),
"selected_editable_objects": ("Object", True),
"selected_editable_sequences": ("Sequence", True),
"selected_nodes": ("Node", True),
@@ -1613,10 +1614,8 @@ def pyrna2sphinx(basepath):
else:
url_base = API_BASEURL
- fw(" :file: `%s <%s/%s>`_:%d\n\n" % (location[0],
- url_base,
- location[0],
- location[1]))
+ fw(" :file: `%s\\:%d <%s/%s$%d>`_\n\n" %
+ (location[0], location[1], url_base, location[0], location[1]))
file.close()
@@ -1641,19 +1640,24 @@ def write_sphinx_conf_py(basepath):
fw("version = '%s - API'\n" % BLENDER_VERSION_DOTS)
fw("release = '%s - API'\n" % BLENDER_VERSION_DOTS)
+ # Quiet file not in table-of-contents warnings.
+ fw("exclude_patterns = [\n")
+ fw(" 'include__bmesh.rst',\n")
+ fw("]\n\n")
+
if ARGS.sphinx_theme != 'default':
fw("html_theme = '%s'\n" % ARGS.sphinx_theme)
if ARGS.sphinx_theme == "blender-org":
fw("html_theme_path = ['../']\n")
- # copied with the theme, exclude else we get an error [T28873]
- fw("html_favicon = 'favicon.ico'\n") # in <theme>/static/
# not helpful since the source is generated, adds to upload size.
fw("html_copy_source = False\n")
fw("html_show_sphinx = False\n")
fw("html_split_index = True\n")
- fw("\n")
+ fw("html_extra_path = ['__/static/favicon.ico', '__/static/blender_logo.svg']\n")
+ fw("html_favicon = '__/static/favicon.ico'\n")
+ fw("html_logo = '__/static/blender_logo.svg'\n\n")
# needed for latex, pdf gen
fw("latex_elements = {\n")
@@ -1661,6 +1665,24 @@ def write_sphinx_conf_py(basepath):
fw("}\n\n")
fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
+
+ # Workaround for useless links leading to compile errors
+ # See https://github.com/sphinx-doc/sphinx/issues/3866
+ fw(r"""
+from sphinx.domains.python import PythonDomain
+
+class PatchedPythonDomain(PythonDomain):
+ def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ if 'refspecific' in node:
+ del node['refspecific']
+ return super(PatchedPythonDomain, self).resolve_xref(
+ env, fromdocname, builder, typ, target, node, contnode)
+
+def setup(sphinx):
+ sphinx.override_domain(PatchedPythonDomain)
+""")
+ # end workaround
+
file.close()
@@ -1715,8 +1737,6 @@ def write_rst_contents(basepath):
"bpy.utils.previews",
"bpy.path",
"bpy.app",
- "bpy.app.handlers",
- "bpy.app.translations",
# C modules
"bpy.props",
@@ -1731,19 +1751,9 @@ def write_rst_contents(basepath):
fw(" :maxdepth: 1\n\n")
standalone_modules = (
- # mathutils
- "mathutils",
- "mathutils.geometry",
- "mathutils.bvhtree", "mathutils.kdtree",
- "mathutils.interpolate",
- "mathutils.noise",
- # misc
- "freestyle", "bgl", "blf",
- "gpu", "gpu.offscreen",
- "aud", "bpy_extras",
- "idprop.types",
- # bmesh, submodules are in own page
- "bmesh",
+ # submodules are added in parent page
+ "mathutils", "freestyle", "bgl", "blf", "gpu",
+ "aud", "bpy_extras", "idprop.types", "bmesh",
)
for mod in standalone_modules:
diff --git a/doc/python_api/static/blender_logo.svg b/doc/python_api/static/blender_logo.svg
new file mode 100644
index 00000000000..bbf446c9bec
--- /dev/null
+++ b/doc/python_api/static/blender_logo.svg
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ id="svg8"
+ version="1.1"
+ viewBox="0 0 55.032989 15.935012"
+ height="60.226818"
+ width="207.9987">
+ <defs
+ id="defs2">
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3020">
+ <path
+ style="stroke-width:1.06666672"
+ d="M 0,0 H 211.2 V 61.866667 H 0 Z"
+ id="path3022" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3020-8">
+ <path
+ style="stroke-width:1.06666672"
+ d="M 0,0 H 211.2 V 61.866667 H 0 Z"
+ id="path3022-1" />
+ </clipPath>
+ </defs>
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Blender Logo</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>https://www.blender.org/about/logo/</dc:source>
+ <cc:license
+ rdf:resource="(c) Blender Foundation" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(42.023693,-77.734934)"
+ id="layer1">
+ <g
+ transform="matrix(0.26259939,0,0,-0.26259939,-42.237694,93.888967)"
+ id="g3012"
+ style="stroke-width:7.2904439">
+ <g
+ id="g3014"
+ style="stroke-width:7.2904439" />
+ <g
+ id="g3016"
+ style="stroke-width:7.2904439">
+ <g
+ clip-path="url(#clipPath3020-8)"
+ id="g3018"
+ style="stroke-width:7.2904439">
+ <path
+ id="path3024"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 192.54827,44.510933 c 0,0 -125.158403,0 -128.688003,0 -0.07893,0.06187 -0.1504,0.1344 -0.2272,0.193067 -0.01813,0.0192 -18.9312,14.548267 -19.5008,14.986667 -0.032,0.0256 -0.06507,0.04907 -0.06507,0.04907 -3.029333,2.321067 -7.531733,2.369067 -10.721067,0.133334 -1.9968,-1.396267 -3.194666,-3.508267 -3.285333,-5.792 -0.0021,-0.09173 -0.0064,-0.1824 -0.0064,-0.2752 0,-1.185067 0.314667,-2.3296 0.8832,-3.357867 -5.857067,-0.0053 -11.746133,-0.0128 -11.746133,-0.0128 -4.3936,-0.0021 -8.3648,-2.965333 -9.2725337,-6.8928 C 9.7898667,42.9792 9.7248,42.411733 9.7248,41.8496 c 0,-1.643733 0.546133,-3.236267 1.5808,-4.542933 1.162667,-1.463467 2.842667,-2.448 4.7584,-2.832 C 10.530133,30.2272 5.0016,25.984 4.9973333,25.979733 4.9578667,25.949867 4.9248,25.924267 4.8970667,25.905067 c -2.2176,-1.703467 -3.68,-4.1728 -4.0106667,-6.770134 -0.0490667,-0.381866 -0.0714667,-0.7584 -0.0714667,-1.133866 0,-1.870934 0.5962667,-3.650134 1.7301334,-5.102934 1.3781333,-1.764266 3.4144,-2.884266 5.7322666,-3.147733 2.6549337,-0.3072 5.4495997,0.542933 7.6607997,2.330667 0.01493,0.01173 2.753067,2.256 5.639467,4.6176 1.060267,-2.555734 2.545067,-4.926934 4.465067,-7.0453337 2.4704,-2.7306666 5.473066,-4.8864 8.919466,-6.4128 C 38.5856,1.6352 42.466133,0.82453333 46.501333,0.83413333 50.5376,0.8416 54.417067,1.6629333 58.0352,3.2768 c 3.453867,1.5466667 6.449067,3.7109333 8.910933,6.4352 0.360534,0.4032 0.693334,0.8288 1.0272,1.2544 4.885334,0 124.574937,0 124.574937,0 9.84,0 17.8368,7.5232 17.8368,16.7712 0,9.248 -7.9968,16.773333 -17.8368,16.773333" />
+ <path
+ id="path3026"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 38.538667,28.497067 c 0.113066,2.016 1.101866,3.793066 2.590933,5.0528 1.4624,1.237333 3.428267,1.9936 5.575467,1.9936 2.144,0 4.110933,-0.756267 5.572266,-1.9936 1.490134,-1.259734 2.4768,-3.0368 2.590934,-5.050667 0.113066,-2.0736 -0.718934,-3.997867 -2.181334,-5.425067 C 51.1968,21.6224 49.0784,20.7104 46.705067,20.7104 c -2.3744,0 -4.497067,0.912 -5.9872,2.363733 -1.461334,1.4272 -2.292267,3.351467 -2.1792,5.422934" />
+ <path
+ id="path3028"
+ style="fill:#f5792a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 25.536,24.421333 c 0.01387,-0.7904 0.2656,-2.3232 0.6432,-3.521066 C 26.9728,18.3648 28.318933,16.0192 30.193067,13.950933 32.1152,11.8272 34.482133,10.119467 37.216,8.9088 c 2.872533,-1.2736 5.986133,-1.9210667 9.220267,-1.9157333 3.229866,0.00427 6.3424,0.6656 9.216,1.9477333 2.733866,1.2224 5.098666,2.9376 7.018666,5.063467 1.870934,2.074666 3.216,4.424533 4.010667,6.96 0.401067,1.282133 0.6528,2.581333 0.754133,3.886933 0.100267,1.285333 0.0576,2.571733 -0.1248,3.858133 -0.356266,2.507734 -1.223466,4.858667 -2.557866,7.002667 -1.2224,1.970133 -2.7968,3.696 -4.6688,5.147733 l 0.0053,0.0021 -18.8928,14.506666 c -0.016,0.0128 -0.02987,0.02667 -0.048,0.03733 -1.240533,0.952533 -3.3248,0.948266 -4.686933,-0.0053 -1.3792,-0.9632 -1.536,-2.557866 -0.3104,-3.5648 l -0.0043,-0.0043 7.8784,-6.407467 -24.016,-0.02667 c -0.01173,0 -0.0224,0 -0.032,0 -1.985067,-0.0011 -3.893333,-1.303466 -4.269867,-2.9504 -0.389333,-1.6768 0.958934,-3.067733 3.022934,-3.074133 l -0.0021,-0.0075 L 30.900267,39.3888 9.1786667,22.715733 c -0.026667,-0.02133 -0.0576,-0.0416 -0.0832,-0.06293 -2.0490667,-1.568 -2.7104,-4.178133 -1.4197334,-5.828267 1.3088,-1.68 4.0949337,-1.6832 6.1653337,-0.0096 L 25.696,26.516267 c 0,0 -0.173867,-1.3088 -0.16,-2.094934 z M 56,20.034133 c -2.443733,-2.488533 -5.8624,-3.899733 -9.563733,-3.9072 -3.7056,-0.0064 -7.124267,1.393067 -9.568,3.877334 -1.1936,1.210666 -2.0704,2.602666 -2.6112,4.087466 -0.529067,1.457067 -0.736,3.0048 -0.599467,4.5664 0.130133,1.527467 0.583467,2.9824 1.309867,4.3008 0.712533,1.293867 1.6928,2.465067 2.9056,3.454934 2.373333,1.934933 5.396266,2.981333 8.558933,2.9856 3.1648,0.0053 6.1856,-1.0336 8.561067,-2.961067 1.2096,-0.9856 2.190933,-2.151467 2.903466,-3.445333 0.728534,-1.316267 1.179734,-2.765867 1.314134,-4.2976 C 59.344,27.136 59.138133,25.5904 58.609067,24.1312 58.0672,22.6432 57.1936,21.2512 56,20.034133" />
+ <path
+ id="path3030"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 167.96587,28.529067 c 0.1824,2.0352 1.75466,3.325866 4.15786,3.325866 2.4064,0 3.97974,-1.290666 4.16214,-3.325866 z M 176.0384,23.504 c -0.61547,-1.508267 -2.06507,-2.401067 -4.03627,-2.401067 -2.46613,0 -4.12693,1.540267 -4.1952,3.9744 h 14.18347 c 0,0.251734 0,0.462934 0,0.715734 0,6.094933 -3.57653,9.518933 -9.98827,9.518933 -6.22506,0 -9.98826,-3.457067 -9.98826,-8.878933 0,-5.454934 3.82293,-8.9056 9.98826,-8.9056 3.70134,0 6.5696,1.2672 8.33814,3.4976 L 176.0384,23.504" />
+ <path
+ id="path3032"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 105.0336,28.519467 c 0.18667,2.036266 1.76,3.326933 4.16533,3.326933 2.40214,0 3.97547,-1.290667 4.15894,-3.326933 z m 8.07787,-5.025067 c -0.61547,-1.512533 -2.06614,-2.404267 -4.03947,-2.404267 -2.464,0 -4.12907,1.544534 -4.19413,3.9776 h 14.18026 c 0,0.2496 0,0.4608 0,0.712534 0,6.098133 -3.57546,9.524266 -9.98613,9.524266 -6.22933,0 -9.986133,-3.458133 -9.986133,-8.88 0,-5.456 3.821863,-8.906666 9.986133,-8.906666 3.6992,0 6.5696,1.262933 8.34133,3.495466 l -4.30186,2.481067" />
+ <path
+ id="path3034"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 92.701867,38.997333 h 5.114666 v -20.9248 h -5.114666 z" />
+ <path
+ id="path3036"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 120.33067,33.438933 h 5.14453 v -1.245866 c 1.8208,1.9424 4.00747,2.9248 6.47253,2.9248 2.84054,0 4.992,-0.9824 6.1024,-2.653867 0.92587,-1.381333 0.98774,-3.0496 0.98774,-5.239467 v -9.152 h -5.15094 v 8.040534 c 0,3.336533 -0.67093,4.877866 -3.6,4.877866 -2.96106,0 -4.81173,-1.764266 -4.81173,-4.724266 v -8.194134 h -5.14453 v 15.3664" />
+ <path
+ id="path3038"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 155.60107,26.173867 c 0,-2.864 -1.9136,-4.741334 -4.8736,-4.741334 -2.96427,0 -4.87787,1.813334 -4.87787,4.709334 0,2.9376 1.88907,4.750933 4.87787,4.750933 2.96,0 4.8736,-1.8464 4.8736,-4.718933 z m 0,6.568533 c -1.30027,1.393067 -3.1808,2.157867 -5.79734,2.157867 -5.64266,0 -9.49546,-3.479467 -9.49546,-8.6944 0,-5.112534 3.82613,-8.688 9.40266,-8.688 2.5568,0 4.4352,0.645333 5.89014,2.096 v -1.541334 h 5.14666 v 22.2528 l -5.14666,-1.328 V 32.7424" />
+ <path
+ id="path3040"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 81.010133,30.8928 c 2.990934,0 4.871467,-1.813333 4.871467,-4.750933 0,-2.896 -1.9104,-4.709334 -4.871467,-4.709334 -2.958933,0 -4.869333,1.877334 -4.869333,4.741334 0,2.872533 1.9104,4.718933 4.869333,4.718933 z m -4.869333,8.104533 -5.1488,1.328 v -22.2528 h 5.1488 v 1.541334 c 1.448533,-1.450667 3.329067,-2.096 5.886933,-2.096 5.579734,0 9.4016,3.575466 9.4016,8.688 0,5.214933 -3.853866,8.6944 -9.493333,8.6944 -2.621867,0 -4.5024,-0.7648 -5.7952,-2.157867 v 6.254933" />
+ <path
+ id="path3042"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 183.2608,18.072533 v 15.3664 h 5.14667 v -0.9504 c 1.54026,1.857067 3.1712,2.7808 5.0272,2.7808 0.368,0 0.82986,-0.05973 1.44533,-0.1216 V 30.768 c -0.496,0.064 -1.04747,0.064 -1.6352,0.064 -2.992,0 -4.83733,-1.972267 -4.83733,-5.329067 v -7.4304 h -5.14667" />
+ <path
+ id="path3044"
+ style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
+ d="m 201.55307,35.252267 h -0.39467 l 0.0139,1.409066 0.0203,0.466134 -0.1056,-0.384 -0.46826,-1.4912 h -0.36054 l -0.45866,1.4912 -0.1152,0.376533 0.0277,-0.458667 0.0139,-1.409066 h -0.38614 v 2.282666 h 0.54187 l 0.57067,-1.8016 0.5568,1.8016 h 0.544 z m -3.12747,0 h -0.39787 V 37.1968 h -0.7328 v 0.338133 h 1.85067 V 37.1968 h -0.72 v -1.944533" />
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/python_api/blender-org/static/favicon.ico b/doc/python_api/static/favicon.ico
index f125d24dcb6..f125d24dcb6 100644
--- a/doc/python_api/blender-org/static/favicon.ico
+++ b/doc/python_api/static/favicon.ico
Binary files differ
diff --git a/extern/cuew/README.blender b/extern/cuew/README.blender
index 7b77935d750..a53a927c25f 100644
--- a/extern/cuew/README.blender
+++ b/extern/cuew/README.blender
@@ -1,5 +1,5 @@
Project: Cuda Wrangler
URL: https://github.com/CudaWrangler/cuew
License: Apache 2.0
-Upstream version: 63d2a0f
+Upstream version: cbf465b
Local modifications: None
diff --git a/extern/cuew/include/cuew.h b/extern/cuew/include/cuew.h
index 4cce29d38ab..0eace96bc3f 100644
--- a/extern/cuew/include/cuew.h
+++ b/extern/cuew/include/cuew.h
@@ -27,7 +27,7 @@ extern "C" {
#define CUEW_VERSION_MAJOR 1
#define CUEW_VERSION_MINOR 2
-#define CUDA_VERSION 7050
+#define CUDA_VERSION 8000
#define CU_IPC_HANDLE_SIZE 64
#define CU_STREAM_LEGACY ((CUstream)0x1)
#define CU_STREAM_PER_THREAD ((CUstream)0x2)
@@ -51,6 +51,8 @@ extern "C" {
#define CU_LAUNCH_PARAM_BUFFER_POINTER ((void*)0x01)
#define CU_LAUNCH_PARAM_BUFFER_SIZE ((void*)0x02)
#define CU_PARAM_TR_DEFAULT -1
+#define CU_DEVICE_CPU ((CUdevice)-1)
+#define CU_DEVICE_INVALID ((CUdevice)-2)
/* Functions which changed 3.1 -> 3.2 for 64 bit stuff,
* the cuda library has both the old ones for compatibility and new
@@ -114,12 +116,30 @@ extern "C" {
#define cuGLGetDevices cuGLGetDevices_v2
/* Types. */
+#ifdef _MSC_VER
+typedef unsigned __int32 cuuint32_t;
+typedef unsigned __int64 cuuint64_t;
+#else
+#include <stdint.h>
+typedef uint32_t cuuint32_t;
+typedef uint64_t cuuint64_t;
+#endif
+
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__)
typedef unsigned long long CUdeviceptr;
#else
typedef unsigned int CUdeviceptr;
#endif
+
+#ifdef _WIN32
+# define CUDAAPI __stdcall
+# define CUDA_CB __stdcall
+#else
+# define CUDAAPI
+# define CUDA_CB
+#endif
+
typedef int CUdevice;
typedef struct CUctx_st* CUcontext;
typedef struct CUmod_st* CUmodule;
@@ -180,6 +200,53 @@ typedef enum CUevent_flags_enum {
CU_EVENT_INTERPROCESS = 0x4,
} CUevent_flags;
+typedef enum CUstreamWaitValue_flags_enum {
+ CU_STREAM_WAIT_VALUE_GEQ = 0x0,
+ CU_STREAM_WAIT_VALUE_EQ = 0x1,
+ CU_STREAM_WAIT_VALUE_AND = 0x2,
+ CU_STREAM_WAIT_VALUE_FLUSH = (1 << 30),
+} CUstreamWaitValue_flags;
+
+typedef enum CUstreamWriteValue_flags_enum {
+ CU_STREAM_WRITE_VALUE_DEFAULT = 0x0,
+ CU_STREAM_WRITE_VALUE_NO_MEMORY_BARRIER = 0x1,
+} CUstreamWriteValue_flags;
+
+typedef enum CUstreamBatchMemOpType_enum {
+ CU_STREAM_MEM_OP_WAIT_VALUE_32 = 1,
+ CU_STREAM_MEM_OP_WRITE_VALUE_32 = 2,
+ CU_STREAM_MEM_OP_FLUSH_REMOTE_WRITES = 3,
+} CUstreamBatchMemOpType;
+
+typedef union CUstreamBatchMemOpParams_union {
+ CUstreamBatchMemOpType operation;
+ struct CUstreamMemOpWaitValueParams_st {
+ CUstreamBatchMemOpType operation;
+ CUdeviceptr address;
+ union {
+ cuuint32_t value;
+ cuuint64_t pad;
+ };
+ unsigned int flags;
+ CUdeviceptr alias;
+ } waitValue;
+ struct CUstreamMemOpWriteValueParams_st {
+ CUstreamBatchMemOpType operation;
+ CUdeviceptr address;
+ union {
+ cuuint32_t value;
+ cuuint64_t pad;
+ };
+ unsigned int flags;
+ CUdeviceptr alias;
+ } writeValue;
+ struct CUstreamMemOpFlushRemoteWritesParams_st {
+ CUstreamBatchMemOpType operation;
+ unsigned int flags;
+ } flushRemoteWrites;
+ cuuint64_t pad[6];
+} CUstreamBatchMemOpParams;
+
typedef enum CUoccupancy_flags_enum {
CU_OCCUPANCY_DEFAULT = 0x0,
CU_OCCUPANCY_DISABLE_CACHING_OVERRIDE = 0x1,
@@ -299,6 +366,12 @@ typedef enum CUdevice_attribute_enum {
CU_DEVICE_ATTRIBUTE_MANAGED_MEMORY = 83,
CU_DEVICE_ATTRIBUTE_MULTI_GPU_BOARD = 84,
CU_DEVICE_ATTRIBUTE_MULTI_GPU_BOARD_GROUP_ID = 85,
+ CU_DEVICE_ATTRIBUTE_HOST_NATIVE_ATOMIC_SUPPORTED = 86,
+ CU_DEVICE_ATTRIBUTE_SINGLE_TO_DOUBLE_PRECISION_PERF_RATIO = 87,
+ CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS = 88,
+ CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS = 89,
+ CU_DEVICE_ATTRIBUTE_COMPUTE_PREEMPTION_SUPPORTED = 90,
+ CU_DEVICE_ATTRIBUTE_CAN_USE_HOST_POINTER_FOR_REGISTERED_MEM = 91,
CU_DEVICE_ATTRIBUTE_MAX,
} CUdevice_attribute;
@@ -360,11 +433,26 @@ typedef enum CUmemorytype_enum {
typedef enum CUcomputemode_enum {
CU_COMPUTEMODE_DEFAULT = 0,
- CU_COMPUTEMODE_EXCLUSIVE = 1,
CU_COMPUTEMODE_PROHIBITED = 2,
CU_COMPUTEMODE_EXCLUSIVE_PROCESS = 3,
} CUcomputemode;
+typedef enum CUmem_advise_enum {
+ CU_MEM_ADVISE_SET_READ_MOSTLY = 1,
+ CU_MEM_ADVISE_UNSET_READ_MOSTLY = 2,
+ CU_MEM_ADVISE_SET_PREFERRED_LOCATION = 3,
+ CU_MEM_ADVISE_UNSET_PREFERRED_LOCATION = 4,
+ CU_MEM_ADVISE_SET_ACCESSED_BY = 5,
+ CU_MEM_ADVISE_UNSET_ACCESSED_BY = 6,
+} CUmem_advise;
+
+typedef enum CUmem_range_attribute_enum {
+ CU_MEM_RANGE_ATTRIBUTE_READ_MOSTLY = 1,
+ CU_MEM_RANGE_ATTRIBUTE_PREFERRED_LOCATION = 2,
+ CU_MEM_RANGE_ATTRIBUTE_ACCESSED_BY = 3,
+ CU_MEM_RANGE_ATTRIBUTE_LAST_PREFETCH_LOCATION = 4,
+} CUmem_range_attribute;
+
typedef enum CUjit_option_enum {
CU_JIT_MAX_REGISTERS = 0,
CU_JIT_THREADS_PER_BLOCK,
@@ -381,6 +469,8 @@ typedef enum CUjit_option_enum {
CU_JIT_LOG_VERBOSE,
CU_JIT_GENERATE_LINE_INFO,
CU_JIT_CACHE_MODE,
+ CU_JIT_NEW_SM3X_OPT,
+ CU_JIT_FAST_COMPILE,
CU_JIT_NUM_OPTIONS,
} CUjit_option;
@@ -397,6 +487,10 @@ typedef enum CUjit_target_enum {
CU_TARGET_COMPUTE_37 = 37,
CU_TARGET_COMPUTE_50 = 50,
CU_TARGET_COMPUTE_52 = 52,
+ CU_TARGET_COMPUTE_53 = 53,
+ CU_TARGET_COMPUTE_60 = 60,
+ CU_TARGET_COMPUTE_61 = 61,
+ CU_TARGET_COMPUTE_62 = 62,
} CUjit_target;
typedef enum CUjit_fallback_enum {
@@ -490,6 +584,7 @@ typedef enum cudaError_enum {
CUDA_ERROR_PEER_ACCESS_UNSUPPORTED = 217,
CUDA_ERROR_INVALID_PTX = 218,
CUDA_ERROR_INVALID_GRAPHICS_CONTEXT = 219,
+ CUDA_ERROR_NVLINK_UNCORRECTABLE = 220,
CUDA_ERROR_INVALID_SOURCE = 300,
CUDA_ERROR_FILE_NOT_FOUND = 301,
CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND = 302,
@@ -521,8 +616,14 @@ typedef enum cudaError_enum {
CUDA_ERROR_UNKNOWN = 999,
} CUresult;
-typedef void* CUstreamCallback;
-typedef size_t* CUoccupancyB2DSize;
+typedef enum CUdevice_P2PAttribute_enum {
+ CU_DEVICE_P2P_ATTRIBUTE_PERFORMANCE_RANK = 0x01,
+ CU_DEVICE_P2P_ATTRIBUTE_ACCESS_SUPPORTED = 0x02,
+ CU_DEVICE_P2P_ATTRIBUTE_NATIVE_ATOMIC_SUPPORTED = 0x03,
+} CUdevice_P2PAttribute;
+
+typedef void (CUDA_CB *CUstreamCallback)(CUstream hStream, CUresult status, void* userData);
+typedef size_t (CUDA_CB *CUoccupancyB2DSize)(int blockSize);
typedef struct CUDA_MEMCPY2D_st {
size_t srcXInBytes;
@@ -654,7 +755,8 @@ typedef struct CUDA_TEXTURE_DESC_st {
float mipmapLevelBias;
float minMipmapLevelClamp;
float maxMipmapLevelClamp;
- int reserved[16];
+ float borderColor[4];
+ int reserved[12];
} CUDA_TEXTURE_DESC;
typedef enum CUresourceViewFormat_enum {
@@ -736,21 +838,16 @@ typedef enum {
NVRTC_ERROR_INVALID_OPTION = 5,
NVRTC_ERROR_COMPILATION = 6,
NVRTC_ERROR_BUILTIN_OPERATION_FAILURE = 7,
+ NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION = 8,
+ NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION = 9,
+ NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID = 10,
+ NVRTC_ERROR_INTERNAL_ERROR = 11,
} nvrtcResult;
typedef struct _nvrtcProgram* nvrtcProgram;
-
-#ifdef _WIN32
-# define CUDAAPI __stdcall
-# define CUDA_CB __stdcall
-#else
-# define CUDAAPI
-# define CUDA_CB
-#endif
-
/* Function types. */
-typedef CUresult CUDAAPI tcuGetErrorString(CUresult error, const char* pStr);
-typedef CUresult CUDAAPI tcuGetErrorName(CUresult error, const char* pStr);
+typedef CUresult CUDAAPI tcuGetErrorString(CUresult error, const char** pStr);
+typedef CUresult CUDAAPI tcuGetErrorName(CUresult error, const char** pStr);
typedef CUresult CUDAAPI tcuInit(unsigned int Flags);
typedef CUresult CUDAAPI tcuDriverGetVersion(int* driverVersion);
typedef CUresult CUDAAPI tcuDeviceGet(CUdevice* device, int ordinal);
@@ -786,26 +883,26 @@ typedef CUresult CUDAAPI tcuCtxAttach(CUcontext* pctx, unsigned int flags);
typedef CUresult CUDAAPI tcuCtxDetach(CUcontext ctx);
typedef CUresult CUDAAPI tcuModuleLoad(CUmodule* module, const char* fname);
typedef CUresult CUDAAPI tcuModuleLoadData(CUmodule* module, const void* image);
-typedef CUresult CUDAAPI tcuModuleLoadDataEx(CUmodule* module, const void* image, unsigned int numOptions, CUjit_option* options, void* optionValues);
+typedef CUresult CUDAAPI tcuModuleLoadDataEx(CUmodule* module, const void* image, unsigned int numOptions, CUjit_option* options, void** optionValues);
typedef CUresult CUDAAPI tcuModuleLoadFatBinary(CUmodule* module, const void* fatCubin);
typedef CUresult CUDAAPI tcuModuleUnload(CUmodule hmod);
typedef CUresult CUDAAPI tcuModuleGetFunction(CUfunction* hfunc, CUmodule hmod, const char* name);
typedef CUresult CUDAAPI tcuModuleGetGlobal_v2(CUdeviceptr* dptr, size_t* bytes, CUmodule hmod, const char* name);
typedef CUresult CUDAAPI tcuModuleGetTexRef(CUtexref* pTexRef, CUmodule hmod, const char* name);
typedef CUresult CUDAAPI tcuModuleGetSurfRef(CUsurfref* pSurfRef, CUmodule hmod, const char* name);
-typedef CUresult CUDAAPI tcuLinkCreate_v2(unsigned int numOptions, CUjit_option* options, void* optionValues, CUlinkState* stateOut);
-typedef CUresult CUDAAPI tcuLinkAddData_v2(CUlinkState state, CUjitInputType type, void* data, size_t size, const char* name, unsigned int numOptions, CUjit_option* options, void* optionValues);
-typedef CUresult CUDAAPI tcuLinkAddFile_v2(CUlinkState state, CUjitInputType type, const char* path, unsigned int numOptions, CUjit_option* options, void* optionValues);
-typedef CUresult CUDAAPI tcuLinkComplete(CUlinkState state, void* cubinOut, size_t* sizeOut);
+typedef CUresult CUDAAPI tcuLinkCreate_v2(unsigned int numOptions, CUjit_option* options, void** optionValues, CUlinkState* stateOut);
+typedef CUresult CUDAAPI tcuLinkAddData_v2(CUlinkState state, CUjitInputType type, void* data, size_t size, const char* name, unsigned int numOptions, CUjit_option* options, void** optionValues);
+typedef CUresult CUDAAPI tcuLinkAddFile_v2(CUlinkState state, CUjitInputType type, const char* path, unsigned int numOptions, CUjit_option* options, void** optionValues);
+typedef CUresult CUDAAPI tcuLinkComplete(CUlinkState state, void** cubinOut, size_t* sizeOut);
typedef CUresult CUDAAPI tcuLinkDestroy(CUlinkState state);
typedef CUresult CUDAAPI tcuMemGetInfo_v2(size_t* free, size_t* total);
typedef CUresult CUDAAPI tcuMemAlloc_v2(CUdeviceptr* dptr, size_t bytesize);
typedef CUresult CUDAAPI tcuMemAllocPitch_v2(CUdeviceptr* dptr, size_t* pPitch, size_t WidthInBytes, size_t Height, unsigned int ElementSizeBytes);
typedef CUresult CUDAAPI tcuMemFree_v2(CUdeviceptr dptr);
typedef CUresult CUDAAPI tcuMemGetAddressRange_v2(CUdeviceptr* pbase, size_t* psize, CUdeviceptr dptr);
-typedef CUresult CUDAAPI tcuMemAllocHost_v2(void* pp, size_t bytesize);
+typedef CUresult CUDAAPI tcuMemAllocHost_v2(void** pp, size_t bytesize);
typedef CUresult CUDAAPI tcuMemFreeHost(void* p);
-typedef CUresult CUDAAPI tcuMemHostAlloc(void* pp, size_t bytesize, unsigned int Flags);
+typedef CUresult CUDAAPI tcuMemHostAlloc(void** pp, size_t bytesize, unsigned int Flags);
typedef CUresult CUDAAPI tcuMemHostGetDevicePointer_v2(CUdeviceptr* pdptr, void* p, unsigned int Flags);
typedef CUresult CUDAAPI tcuMemHostGetFlags(unsigned int* pFlags, void* p);
typedef CUresult CUDAAPI tcuMemAllocManaged(CUdeviceptr* dptr, size_t bytesize, unsigned int flags);
@@ -863,8 +960,12 @@ typedef CUresult CUDAAPI tcuMipmappedArrayCreate(CUmipmappedArray* pHandle, cons
typedef CUresult CUDAAPI tcuMipmappedArrayGetLevel(CUarray* pLevelArray, CUmipmappedArray hMipmappedArray, unsigned int level);
typedef CUresult CUDAAPI tcuMipmappedArrayDestroy(CUmipmappedArray hMipmappedArray);
typedef CUresult CUDAAPI tcuPointerGetAttribute(void* data, CUpointer_attribute attribute, CUdeviceptr ptr);
+typedef CUresult CUDAAPI tcuMemPrefetchAsync(CUdeviceptr devPtr, size_t count, CUdevice dstDevice, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemAdvise(CUdeviceptr devPtr, size_t count, CUmem_advise advice, CUdevice device);
+typedef CUresult CUDAAPI tcuMemRangeGetAttribute(void* data, size_t dataSize, CUmem_range_attribute attribute, CUdeviceptr devPtr, size_t count);
+typedef CUresult CUDAAPI tcuMemRangeGetAttributes(void** data, size_t* dataSizes, CUmem_range_attribute* attributes, size_t numAttributes, CUdeviceptr devPtr, size_t count);
typedef CUresult CUDAAPI tcuPointerSetAttribute(const void* value, CUpointer_attribute attribute, CUdeviceptr ptr);
-typedef CUresult CUDAAPI tcuPointerGetAttributes(unsigned int numAttributes, CUpointer_attribute* attributes, void* data, CUdeviceptr ptr);
+typedef CUresult CUDAAPI tcuPointerGetAttributes(unsigned int numAttributes, CUpointer_attribute* attributes, void** data, CUdeviceptr ptr);
typedef CUresult CUDAAPI tcuStreamCreate(CUstream* phStream, unsigned int Flags);
typedef CUresult CUDAAPI tcuStreamCreateWithPriority(CUstream* phStream, unsigned int flags, int priority);
typedef CUresult CUDAAPI tcuStreamGetPriority(CUstream hStream, int* priority);
@@ -881,10 +982,13 @@ typedef CUresult CUDAAPI tcuEventQuery(CUevent hEvent);
typedef CUresult CUDAAPI tcuEventSynchronize(CUevent hEvent);
typedef CUresult CUDAAPI tcuEventDestroy_v2(CUevent hEvent);
typedef CUresult CUDAAPI tcuEventElapsedTime(float* pMilliseconds, CUevent hStart, CUevent hEnd);
+typedef CUresult CUDAAPI tcuStreamWaitValue32(CUstream stream, CUdeviceptr addr, cuuint32_t value, unsigned int flags);
+typedef CUresult CUDAAPI tcuStreamWriteValue32(CUstream stream, CUdeviceptr addr, cuuint32_t value, unsigned int flags);
+typedef CUresult CUDAAPI tcuStreamBatchMemOp(CUstream stream, unsigned int count, CUstreamBatchMemOpParams* paramArray, unsigned int flags);
typedef CUresult CUDAAPI tcuFuncGetAttribute(int* pi, CUfunction_attribute attrib, CUfunction hfunc);
typedef CUresult CUDAAPI tcuFuncSetCacheConfig(CUfunction hfunc, CUfunc_cache config);
typedef CUresult CUDAAPI tcuFuncSetSharedMemConfig(CUfunction hfunc, CUsharedconfig config);
-typedef CUresult CUDAAPI tcuLaunchKernel(CUfunction f, unsigned int gridDimX, unsigned int gridDimY, unsigned int gridDimZ, unsigned int blockDimX, unsigned int blockDimY, unsigned int blockDimZ, unsigned int sharedMemBytes, CUstream hStream, void* kernelParams, void* extra);
+typedef CUresult CUDAAPI tcuLaunchKernel(CUfunction f, unsigned int gridDimX, unsigned int gridDimY, unsigned int gridDimZ, unsigned int blockDimX, unsigned int blockDimY, unsigned int blockDimZ, unsigned int sharedMemBytes, CUstream hStream, void** kernelParams, void** extra);
typedef CUresult CUDAAPI tcuFuncSetBlockShape(CUfunction hfunc, int x, int y, int z);
typedef CUresult CUDAAPI tcuFuncSetSharedSize(CUfunction hfunc, unsigned int bytes);
typedef CUresult CUDAAPI tcuParamSetSize(CUfunction hfunc, unsigned int numbytes);
@@ -910,6 +1014,7 @@ typedef CUresult CUDAAPI tcuTexRefSetMipmapFilterMode(CUtexref hTexRef, CUfilter
typedef CUresult CUDAAPI tcuTexRefSetMipmapLevelBias(CUtexref hTexRef, float bias);
typedef CUresult CUDAAPI tcuTexRefSetMipmapLevelClamp(CUtexref hTexRef, float minMipmapLevelClamp, float maxMipmapLevelClamp);
typedef CUresult CUDAAPI tcuTexRefSetMaxAnisotropy(CUtexref hTexRef, unsigned int maxAniso);
+typedef CUresult CUDAAPI tcuTexRefSetBorderColor(CUtexref hTexRef, float* pBorderColor);
typedef CUresult CUDAAPI tcuTexRefSetFlags(CUtexref hTexRef, unsigned int Flags);
typedef CUresult CUDAAPI tcuTexRefGetAddress_v2(CUdeviceptr* pdptr, CUtexref hTexRef);
typedef CUresult CUDAAPI tcuTexRefGetArray(CUarray* phArray, CUtexref hTexRef);
@@ -921,6 +1026,7 @@ typedef CUresult CUDAAPI tcuTexRefGetMipmapFilterMode(CUfilter_mode* pfm, CUtexr
typedef CUresult CUDAAPI tcuTexRefGetMipmapLevelBias(float* pbias, CUtexref hTexRef);
typedef CUresult CUDAAPI tcuTexRefGetMipmapLevelClamp(float* pminMipmapLevelClamp, float* pmaxMipmapLevelClamp, CUtexref hTexRef);
typedef CUresult CUDAAPI tcuTexRefGetMaxAnisotropy(int* pmaxAniso, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuTexRefGetBorderColor(float* pBorderColor, CUtexref hTexRef);
typedef CUresult CUDAAPI tcuTexRefGetFlags(unsigned int* pFlags, CUtexref hTexRef);
typedef CUresult CUDAAPI tcuTexRefCreate(CUtexref* pTexRef);
typedef CUresult CUDAAPI tcuTexRefDestroy(CUtexref hTexRef);
@@ -935,6 +1041,7 @@ typedef CUresult CUDAAPI tcuSurfObjectCreate(CUsurfObject* pSurfObject, const CU
typedef CUresult CUDAAPI tcuSurfObjectDestroy(CUsurfObject surfObject);
typedef CUresult CUDAAPI tcuSurfObjectGetResourceDesc(CUDA_RESOURCE_DESC* pResDesc, CUsurfObject surfObject);
typedef CUresult CUDAAPI tcuDeviceCanAccessPeer(int* canAccessPeer, CUdevice dev, CUdevice peerDev);
+typedef CUresult CUDAAPI tcuDeviceGetP2PAttribute(int* value, CUdevice_P2PAttribute attrib, CUdevice srcDevice, CUdevice dstDevice);
typedef CUresult CUDAAPI tcuCtxEnablePeerAccess(CUcontext peerContext, unsigned int Flags);
typedef CUresult CUDAAPI tcuCtxDisablePeerAccess(CUcontext peerContext);
typedef CUresult CUDAAPI tcuGraphicsUnregisterResource(CUgraphicsResource resource);
@@ -944,7 +1051,7 @@ typedef CUresult CUDAAPI tcuGraphicsResourceGetMappedPointer_v2(CUdeviceptr* pDe
typedef CUresult CUDAAPI tcuGraphicsResourceSetMapFlags_v2(CUgraphicsResource resource, unsigned int flags);
typedef CUresult CUDAAPI tcuGraphicsMapResources(unsigned int count, CUgraphicsResource* resources, CUstream hStream);
typedef CUresult CUDAAPI tcuGraphicsUnmapResources(unsigned int count, CUgraphicsResource* resources, CUstream hStream);
-typedef CUresult CUDAAPI tcuGetExportTable(const void* ppExportTable, const CUuuid* pExportTableId);
+typedef CUresult CUDAAPI tcuGetExportTable(const void** ppExportTable, const CUuuid* pExportTableId);
typedef CUresult CUDAAPI tcuGraphicsGLRegisterBuffer(CUgraphicsResource* pCudaResource, GLuint buffer, unsigned int Flags);
typedef CUresult CUDAAPI tcuGraphicsGLRegisterImage(CUgraphicsResource* pCudaResource, GLuint image, GLenum target, unsigned int Flags);
@@ -961,13 +1068,15 @@ typedef CUresult CUDAAPI tcuGLUnmapBufferObjectAsync(GLuint buffer, CUstream hSt
typedef const char* CUDAAPI tnvrtcGetErrorString(nvrtcResult result);
typedef nvrtcResult CUDAAPI tnvrtcVersion(int* major, int* minor);
-typedef nvrtcResult CUDAAPI tnvrtcCreateProgram(nvrtcProgram* prog, const char* src, const char* name, int numHeaders, const char* headers, const char* includeNames);
+typedef nvrtcResult CUDAAPI tnvrtcCreateProgram(nvrtcProgram* prog, const char* src, const char* name, int numHeaders, const char** headers, const char** includeNames);
typedef nvrtcResult CUDAAPI tnvrtcDestroyProgram(nvrtcProgram* prog);
-typedef nvrtcResult CUDAAPI tnvrtcCompileProgram(nvrtcProgram prog, int numOptions, const char* options);
+typedef nvrtcResult CUDAAPI tnvrtcCompileProgram(nvrtcProgram prog, int numOptions, const char** options);
typedef nvrtcResult CUDAAPI tnvrtcGetPTXSize(nvrtcProgram prog, size_t* ptxSizeRet);
typedef nvrtcResult CUDAAPI tnvrtcGetPTX(nvrtcProgram prog, char* ptx);
typedef nvrtcResult CUDAAPI tnvrtcGetProgramLogSize(nvrtcProgram prog, size_t* logSizeRet);
typedef nvrtcResult CUDAAPI tnvrtcGetProgramLog(nvrtcProgram prog, char* log);
+typedef nvrtcResult CUDAAPI tnvrtcAddNameExpression(nvrtcProgram prog, const char* name_expression);
+typedef nvrtcResult CUDAAPI tnvrtcGetLoweredName(nvrtcProgram prog, const char* name_expression, const char** lowered_name);
/* Function declarations. */
@@ -1085,6 +1194,10 @@ extern tcuMipmappedArrayCreate *cuMipmappedArrayCreate;
extern tcuMipmappedArrayGetLevel *cuMipmappedArrayGetLevel;
extern tcuMipmappedArrayDestroy *cuMipmappedArrayDestroy;
extern tcuPointerGetAttribute *cuPointerGetAttribute;
+extern tcuMemPrefetchAsync *cuMemPrefetchAsync;
+extern tcuMemAdvise *cuMemAdvise;
+extern tcuMemRangeGetAttribute *cuMemRangeGetAttribute;
+extern tcuMemRangeGetAttributes *cuMemRangeGetAttributes;
extern tcuPointerSetAttribute *cuPointerSetAttribute;
extern tcuPointerGetAttributes *cuPointerGetAttributes;
extern tcuStreamCreate *cuStreamCreate;
@@ -1103,6 +1216,9 @@ extern tcuEventQuery *cuEventQuery;
extern tcuEventSynchronize *cuEventSynchronize;
extern tcuEventDestroy_v2 *cuEventDestroy_v2;
extern tcuEventElapsedTime *cuEventElapsedTime;
+extern tcuStreamWaitValue32 *cuStreamWaitValue32;
+extern tcuStreamWriteValue32 *cuStreamWriteValue32;
+extern tcuStreamBatchMemOp *cuStreamBatchMemOp;
extern tcuFuncGetAttribute *cuFuncGetAttribute;
extern tcuFuncSetCacheConfig *cuFuncSetCacheConfig;
extern tcuFuncSetSharedMemConfig *cuFuncSetSharedMemConfig;
@@ -1132,6 +1248,7 @@ extern tcuTexRefSetMipmapFilterMode *cuTexRefSetMipmapFilterMode;
extern tcuTexRefSetMipmapLevelBias *cuTexRefSetMipmapLevelBias;
extern tcuTexRefSetMipmapLevelClamp *cuTexRefSetMipmapLevelClamp;
extern tcuTexRefSetMaxAnisotropy *cuTexRefSetMaxAnisotropy;
+extern tcuTexRefSetBorderColor *cuTexRefSetBorderColor;
extern tcuTexRefSetFlags *cuTexRefSetFlags;
extern tcuTexRefGetAddress_v2 *cuTexRefGetAddress_v2;
extern tcuTexRefGetArray *cuTexRefGetArray;
@@ -1143,6 +1260,7 @@ extern tcuTexRefGetMipmapFilterMode *cuTexRefGetMipmapFilterMode;
extern tcuTexRefGetMipmapLevelBias *cuTexRefGetMipmapLevelBias;
extern tcuTexRefGetMipmapLevelClamp *cuTexRefGetMipmapLevelClamp;
extern tcuTexRefGetMaxAnisotropy *cuTexRefGetMaxAnisotropy;
+extern tcuTexRefGetBorderColor *cuTexRefGetBorderColor;
extern tcuTexRefGetFlags *cuTexRefGetFlags;
extern tcuTexRefCreate *cuTexRefCreate;
extern tcuTexRefDestroy *cuTexRefDestroy;
@@ -1157,6 +1275,7 @@ extern tcuSurfObjectCreate *cuSurfObjectCreate;
extern tcuSurfObjectDestroy *cuSurfObjectDestroy;
extern tcuSurfObjectGetResourceDesc *cuSurfObjectGetResourceDesc;
extern tcuDeviceCanAccessPeer *cuDeviceCanAccessPeer;
+extern tcuDeviceGetP2PAttribute *cuDeviceGetP2PAttribute;
extern tcuCtxEnablePeerAccess *cuCtxEnablePeerAccess;
extern tcuCtxDisablePeerAccess *cuCtxDisablePeerAccess;
extern tcuGraphicsUnregisterResource *cuGraphicsUnregisterResource;
@@ -1190,6 +1309,8 @@ extern tnvrtcGetPTXSize *nvrtcGetPTXSize;
extern tnvrtcGetPTX *nvrtcGetPTX;
extern tnvrtcGetProgramLogSize *nvrtcGetProgramLogSize;
extern tnvrtcGetProgramLog *nvrtcGetProgramLog;
+extern tnvrtcAddNameExpression *nvrtcAddNameExpression;
+extern tnvrtcGetLoweredName *nvrtcGetLoweredName;
enum {
diff --git a/extern/cuew/src/cuew.c b/extern/cuew/src/cuew.c
index c96ea2c1959..962059bfcce 100644
--- a/extern/cuew/src/cuew.c
+++ b/extern/cuew/src/cuew.c
@@ -184,6 +184,10 @@ tcuMipmappedArrayCreate *cuMipmappedArrayCreate;
tcuMipmappedArrayGetLevel *cuMipmappedArrayGetLevel;
tcuMipmappedArrayDestroy *cuMipmappedArrayDestroy;
tcuPointerGetAttribute *cuPointerGetAttribute;
+tcuMemPrefetchAsync *cuMemPrefetchAsync;
+tcuMemAdvise *cuMemAdvise;
+tcuMemRangeGetAttribute *cuMemRangeGetAttribute;
+tcuMemRangeGetAttributes *cuMemRangeGetAttributes;
tcuPointerSetAttribute *cuPointerSetAttribute;
tcuPointerGetAttributes *cuPointerGetAttributes;
tcuStreamCreate *cuStreamCreate;
@@ -202,6 +206,9 @@ tcuEventQuery *cuEventQuery;
tcuEventSynchronize *cuEventSynchronize;
tcuEventDestroy_v2 *cuEventDestroy_v2;
tcuEventElapsedTime *cuEventElapsedTime;
+tcuStreamWaitValue32 *cuStreamWaitValue32;
+tcuStreamWriteValue32 *cuStreamWriteValue32;
+tcuStreamBatchMemOp *cuStreamBatchMemOp;
tcuFuncGetAttribute *cuFuncGetAttribute;
tcuFuncSetCacheConfig *cuFuncSetCacheConfig;
tcuFuncSetSharedMemConfig *cuFuncSetSharedMemConfig;
@@ -231,6 +238,7 @@ tcuTexRefSetMipmapFilterMode *cuTexRefSetMipmapFilterMode;
tcuTexRefSetMipmapLevelBias *cuTexRefSetMipmapLevelBias;
tcuTexRefSetMipmapLevelClamp *cuTexRefSetMipmapLevelClamp;
tcuTexRefSetMaxAnisotropy *cuTexRefSetMaxAnisotropy;
+tcuTexRefSetBorderColor *cuTexRefSetBorderColor;
tcuTexRefSetFlags *cuTexRefSetFlags;
tcuTexRefGetAddress_v2 *cuTexRefGetAddress_v2;
tcuTexRefGetArray *cuTexRefGetArray;
@@ -242,6 +250,7 @@ tcuTexRefGetMipmapFilterMode *cuTexRefGetMipmapFilterMode;
tcuTexRefGetMipmapLevelBias *cuTexRefGetMipmapLevelBias;
tcuTexRefGetMipmapLevelClamp *cuTexRefGetMipmapLevelClamp;
tcuTexRefGetMaxAnisotropy *cuTexRefGetMaxAnisotropy;
+tcuTexRefGetBorderColor *cuTexRefGetBorderColor;
tcuTexRefGetFlags *cuTexRefGetFlags;
tcuTexRefCreate *cuTexRefCreate;
tcuTexRefDestroy *cuTexRefDestroy;
@@ -256,6 +265,7 @@ tcuSurfObjectCreate *cuSurfObjectCreate;
tcuSurfObjectDestroy *cuSurfObjectDestroy;
tcuSurfObjectGetResourceDesc *cuSurfObjectGetResourceDesc;
tcuDeviceCanAccessPeer *cuDeviceCanAccessPeer;
+tcuDeviceGetP2PAttribute *cuDeviceGetP2PAttribute;
tcuCtxEnablePeerAccess *cuCtxEnablePeerAccess;
tcuCtxDisablePeerAccess *cuCtxDisablePeerAccess;
tcuGraphicsUnregisterResource *cuGraphicsUnregisterResource;
@@ -289,6 +299,8 @@ tnvrtcGetPTXSize *nvrtcGetPTXSize;
tnvrtcGetPTX *nvrtcGetPTX;
tnvrtcGetProgramLogSize *nvrtcGetProgramLogSize;
tnvrtcGetProgramLog *nvrtcGetProgramLog;
+tnvrtcAddNameExpression *nvrtcAddNameExpression;
+tnvrtcGetLoweredName *nvrtcGetLoweredName;
static DynamicLibrary dynamic_library_open_find(const char **paths) {
@@ -486,6 +498,10 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuMipmappedArrayGetLevel);
CUDA_LIBRARY_FIND(cuMipmappedArrayDestroy);
CUDA_LIBRARY_FIND(cuPointerGetAttribute);
+ CUDA_LIBRARY_FIND(cuMemPrefetchAsync);
+ CUDA_LIBRARY_FIND(cuMemAdvise);
+ CUDA_LIBRARY_FIND(cuMemRangeGetAttribute);
+ CUDA_LIBRARY_FIND(cuMemRangeGetAttributes);
CUDA_LIBRARY_FIND(cuPointerSetAttribute);
CUDA_LIBRARY_FIND(cuPointerGetAttributes);
CUDA_LIBRARY_FIND(cuStreamCreate);
@@ -504,6 +520,9 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuEventSynchronize);
CUDA_LIBRARY_FIND(cuEventDestroy_v2);
CUDA_LIBRARY_FIND(cuEventElapsedTime);
+ CUDA_LIBRARY_FIND(cuStreamWaitValue32);
+ CUDA_LIBRARY_FIND(cuStreamWriteValue32);
+ CUDA_LIBRARY_FIND(cuStreamBatchMemOp);
CUDA_LIBRARY_FIND(cuFuncGetAttribute);
CUDA_LIBRARY_FIND(cuFuncSetCacheConfig);
CUDA_LIBRARY_FIND(cuFuncSetSharedMemConfig);
@@ -533,6 +552,7 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuTexRefSetMipmapLevelBias);
CUDA_LIBRARY_FIND(cuTexRefSetMipmapLevelClamp);
CUDA_LIBRARY_FIND(cuTexRefSetMaxAnisotropy);
+ CUDA_LIBRARY_FIND(cuTexRefSetBorderColor);
CUDA_LIBRARY_FIND(cuTexRefSetFlags);
CUDA_LIBRARY_FIND(cuTexRefGetAddress_v2);
CUDA_LIBRARY_FIND(cuTexRefGetArray);
@@ -544,6 +564,7 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuTexRefGetMipmapLevelBias);
CUDA_LIBRARY_FIND(cuTexRefGetMipmapLevelClamp);
CUDA_LIBRARY_FIND(cuTexRefGetMaxAnisotropy);
+ CUDA_LIBRARY_FIND(cuTexRefGetBorderColor);
CUDA_LIBRARY_FIND(cuTexRefGetFlags);
CUDA_LIBRARY_FIND(cuTexRefCreate);
CUDA_LIBRARY_FIND(cuTexRefDestroy);
@@ -558,6 +579,7 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuSurfObjectDestroy);
CUDA_LIBRARY_FIND(cuSurfObjectGetResourceDesc);
CUDA_LIBRARY_FIND(cuDeviceCanAccessPeer);
+ CUDA_LIBRARY_FIND(cuDeviceGetP2PAttribute);
CUDA_LIBRARY_FIND(cuCtxEnablePeerAccess);
CUDA_LIBRARY_FIND(cuCtxDisablePeerAccess);
CUDA_LIBRARY_FIND(cuGraphicsUnregisterResource);
@@ -593,6 +615,8 @@ int cuewInit(void) {
NVRTC_LIBRARY_FIND(nvrtcGetPTX);
NVRTC_LIBRARY_FIND(nvrtcGetProgramLogSize);
NVRTC_LIBRARY_FIND(nvrtcGetProgramLog);
+ NVRTC_LIBRARY_FIND(nvrtcAddNameExpression);
+ NVRTC_LIBRARY_FIND(nvrtcGetLoweredName);
}
result = CUEW_SUCCESS;
@@ -630,6 +654,7 @@ const char *cuewErrorString(CUresult result) {
case CUDA_ERROR_PEER_ACCESS_UNSUPPORTED: return "Peer access unsupported";
case CUDA_ERROR_INVALID_PTX: return "Invalid ptx";
case CUDA_ERROR_INVALID_GRAPHICS_CONTEXT: return "Invalid graphics context";
+ case CUDA_ERROR_NVLINK_UNCORRECTABLE: return "Nvlink uncorrectable";
case CUDA_ERROR_INVALID_SOURCE: return "Invalid source";
case CUDA_ERROR_FILE_NOT_FOUND: return "File not found";
case CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND: return "Link to a shared object failed to resolve";
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 96ec9a33270..b5340efdcb2 100644
--- a/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c
+++ b/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c
@@ -137,7 +137,7 @@ struct Knot {
/* Initially point to contiguous memory, however we may re-assign */
double *tan[2];
-} Knot;
+};
struct KnotRemoveState {
@@ -1102,7 +1102,7 @@ int curve_fit_cubic_to_points_refit_db(
uint **r_corner_index_array, uint *r_corner_index_len)
{
const uint knots_len = points_len;
- struct Knot *knots = malloc(sizeof(Knot) * knots_len);
+ struct Knot *knots = malloc(sizeof(struct Knot) * knots_len);
#ifndef USE_CORNER_DETECT
(void)r_corner_index_array;
diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h
index 1e9528f9ed9..72813c39ac2 100644
--- a/intern/atomic/atomic_ops.h
+++ b/intern/atomic/atomic_ops.h
@@ -100,6 +100,7 @@ ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x);
ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x);
ATOMIC_INLINE size_t atomic_fetch_and_sub_z(size_t *p, size_t x);
ATOMIC_INLINE size_t atomic_cas_z(size_t *v, size_t old, size_t _new);
+ATOMIC_INLINE size_t atomic_fetch_and_update_max_z(size_t *p, size_t x); /* Uses CAS loop, see warning below. */
ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x);
ATOMIC_INLINE unsigned int atomic_sub_and_fetch_u(unsigned int *p, unsigned int x);
diff --git a/intern/atomic/intern/atomic_ops_ext.h b/intern/atomic/intern/atomic_ops_ext.h
index b72c94563fc..8d5f2e5dad7 100644
--- a/intern/atomic/intern/atomic_ops_ext.h
+++ b/intern/atomic/intern/atomic_ops_ext.h
@@ -111,6 +111,17 @@ ATOMIC_INLINE size_t atomic_cas_z(size_t *v, size_t old, size_t _new)
#endif
}
+ATOMIC_INLINE size_t atomic_fetch_and_update_max_z(size_t *p, size_t x)
+{
+ size_t prev_value;
+ while((prev_value = *p) < x) {
+ if(atomic_cas_z(p, prev_value, x) == prev_value) {
+ break;
+ }
+ }
+ return prev_value;
+}
+
/******************************************************************************/
/* unsigned operations. */
ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x)
diff --git a/intern/atomic/intern/atomic_ops_utils.h b/intern/atomic/intern/atomic_ops_utils.h
index bfec9918c16..c190b655e0a 100644
--- a/intern/atomic/intern/atomic_ops_utils.h
+++ b/intern/atomic/intern/atomic_ops_utils.h
@@ -52,8 +52,8 @@
#ifndef __ATOMIC_OPS_UTILS_H__
#define __ATOMIC_OPS_UTILS_H__
-/* needed for int types */
-#include "../../../source/blender/blenlib/BLI_sys_types.h"
+#include <stdint.h>
+#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
@@ -63,12 +63,7 @@
#if defined(_MSC_VER)
# define ATOMIC_INLINE static __forceinline
#else
-# if (defined(__APPLE__) && defined(__ppc__))
-/* static inline __attribute__ here breaks osx ppc gcc42 build */
-# define ATOMIC_INLINE static __attribute__((always_inline))
-# else
-# define ATOMIC_INLINE static inline __attribute__((always_inline))
-# endif
+# define ATOMIC_INLINE static inline __attribute__((always_inline))
#endif
#ifndef LIKELY
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index f9d65aa2363..10e42a82b76 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -89,7 +89,7 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause(bool keep)
}
AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_PitchReader> pitch, boost::shared_ptr<AUD_ResampleReader> resampler, boost::shared_ptr<AUD_ChannelMapperReader> mapper, bool keep) :
- m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_old_volume(1.0f), m_loopcount(0),
+ m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(0.0f), m_old_volume(0.0f), m_loopcount(0),
m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0),
m_flags(AUD_RENDER_CONE), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device)
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index c53a9f91cc0..5844c2480d6 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -41,61 +41,65 @@ elseif(WIN32 AND MSVC)
set(CYCLES_AVX2_ARCH_FLAGS "/arch:SSE2")
endif()
+ # Unlike GCC/clang we still use fast math, because there is no fine
+ # grained control and the speedup we get here is too big to ignore.
+ set(CYCLES_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
+
# there is no /arch:SSE3, but intrinsics are available anyway
if(CMAKE_CL_64)
- set(CYCLES_SSE2_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
- set(CYCLES_SSE3_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
- set(CYCLES_SSE41_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
- set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_AVX_ARCH_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
- set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
+ set(CYCLES_SSE2_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_SSE3_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_SSE41_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_AVX_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
else()
- set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
- set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
- set(CYCLES_SSE41_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
- set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_AVX_ARCH_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
- set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
+ set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_SSE41_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_AVX_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
endif()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox")
-
- set(CYCLES_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
-elseif(CMAKE_COMPILER_IS_GNUCC)
+elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
- set(CYCLES_KERNEL_FLAGS "-ffast-math")
- if(CXX_HAS_SSE)
- set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2 -mfpmath=sse")
- set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse")
- set(CYCLES_SSE41_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mfpmath=sse")
- endif()
- if(CXX_HAS_AVX)
- set(CYCLES_AVX_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mfpmath=sse")
- endif()
- if(CXX_HAS_AVX2)
- set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c -mfpmath=sse")
+
+ # Assume no signal trapping for better code generation.
+ set(CYCLES_KERNEL_FLAGS "-fno-trapping-math")
+ # Avoid overhead of setting errno for NaNs.
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-math-errno")
+ # Let compiler optimize 0.0 - x without worrying about signed zeros.
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signed-zeros")
+
+ if(CMAKE_COMPILER_IS_GNUCC)
+ # Assume no signal trapping for better code generation.
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signaling-nans")
+ # Assume a fixed rounding mode for better constant folding.
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-rounding-math")
endif()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math -fno-finite-math-only")
-elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- check_cxx_compiler_flag(-msse CXX_HAS_SSE)
- check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
- check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
- set(CYCLES_KERNEL_FLAGS "-ffast-math")
+
if(CXX_HAS_SSE)
- set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2")
- set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3")
- set(CYCLES_SSE41_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1")
- endif()
- if(CXX_HAS_AVX)
- set(CYCLES_AVX_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx")
- endif()
- if(CXX_HAS_AVX2)
- set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c")
+ if(CMAKE_COMPILER_IS_GNUCC)
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -mfpmath=sse")
+ endif()
+
+ set(CYCLES_SSE2_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -msse -msse2")
+ set(CYCLES_SSE3_KERNEL_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS} -msse3 -mssse3")
+ set(CYCLES_SSE41_KERNEL_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS} -msse4.1")
+ if(CXX_HAS_AVX)
+ set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS} -mavx")
+ endif()
+ if(CXX_HAS_AVX2)
+ set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS} -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c")
+ endif()
endif()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math -fno-finite-math-only")
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}")
endif()
if(CXX_HAS_SSE)
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index b5149b5082e..3018fd5b316 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -239,7 +239,8 @@ def register_passes(engine, scene, srl):
if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE')
if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE')
- if crl.use_denoising and crl.denoising_store_passes:
+ cscene = scene.cycles
+ if crl.use_denoising and crl.denoising_store_passes and not cscene.use_progressive_refine:
engine.register_pass(scene, srl, "Denoising Normal", 3, "XYZ", 'VECTOR')
engine.register_pass(scene, srl, "Denoising Normal Variance", 3, "XYZ", 'VECTOR')
engine.register_pass(scene, srl, "Denoising Albedo", 3, "RGB", 'COLOR')
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index 82c4ffc6e50..17efb00abdb 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -32,14 +32,11 @@ class AddPresetIntegrator(AddPresetBase, Operator):
preset_values = [
"cycles.max_bounces",
- "cycles.min_bounces",
"cycles.diffuse_bounces",
"cycles.glossy_bounces",
"cycles.transmission_bounces",
"cycles.volume_bounces",
- "cycles.transparent_min_bounces",
"cycles.transparent_max_bounces",
- "cycles.use_transparent_shadows",
"cycles.caustics_reflective",
"cycles.caustics_refractive",
"cycles.blur_glossy"
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 8bb25aba13c..7b16ef1d543 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -205,13 +205,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
name="AA Samples",
description="Number of antialiasing samples to render for each pixel",
min=1, max=2097151,
- default=4,
+ default=128,
)
cls.preview_aa_samples = IntProperty(
name="AA Samples",
description="Number of antialiasing samples to render in the viewport, unlimited if 0",
min=0, max=2097151,
- default=4,
+ default=32,
)
cls.diffuse_samples = IntProperty(
name="Diffuse Samples",
@@ -308,17 +308,9 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="Adaptively blur glossy shaders after blurry bounces, "
"to reduce noise at the cost of accuracy",
min=0.0, max=10.0,
- default=0.0,
+ default=1.0,
)
- cls.min_bounces = IntProperty(
- name="Min Bounces",
- description="Minimum number of bounces, setting this lower "
- "than the maximum enables probabilistic path "
- "termination (faster but noisier)",
- min=0, max=1024,
- default=3,
- )
cls.max_bounces = IntProperty(
name="Max Bounces",
description="Total maximum number of bounces",
@@ -351,26 +343,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=0,
)
- cls.transparent_min_bounces = IntProperty(
- name="Transparent Min Bounces",
- description="Minimum number of transparent bounces, setting "
- "this lower than the maximum enables "
- "probabilistic path termination (faster but "
- "noisier)",
- min=0, max=1024,
- default=8,
- )
cls.transparent_max_bounces = IntProperty(
name="Transparent Max Bounces",
description="Maximum number of transparent bounces",
min=0, max=1024,
default=8,
)
- cls.use_transparent_shadows = BoolProperty(
- name="Transparent Shadows",
- description="Use transparency of surfaces for rendering shadows",
- default=True,
- )
cls.volume_step_size = FloatProperty(
name="Step Size",
@@ -475,7 +453,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
"higher values will be scaled down to avoid too "
"much noise and slow convergence at the cost of accuracy",
min=0.0, max=1e8,
- default=0.0,
+ default=10.0,
)
cls.debug_tile_size = IntProperty(
@@ -695,10 +673,17 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
update=devices_update_callback
)
- cls.debug_opencl_kernel_single_program = BoolProperty(name="Single Program", default=True, update=devices_update_callback);
+ cls.debug_opencl_kernel_single_program = BoolProperty(
+ name="Single Program",
+ default=True,
+ update=devices_update_callback,
+ )
cls.debug_use_opencl_debug = BoolProperty(name="Debug OpenCL", default=False)
+ cls.debug_opencl_mem_limit = IntProperty(name="Memory limit", default=0,
+ description="Artificial limit on OpenCL memory usage in MB (0 to disable limit)")
+
@classmethod
def unregister(cls):
del bpy.types.Scene.cycles
@@ -1209,6 +1194,7 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
name="Use Denoising",
description="Denoise the rendered image",
default=False,
+ update=update_render_passes,
)
cls.denoising_diffuse_direct = BoolProperty(
name="Diffuse Direct",
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 4ed3ccd9a2c..7ab47455c49 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -139,7 +139,7 @@ def draw_samples_info(layout, context):
(ao * aa, ml * aa, sss * aa, vol * aa))
-class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
bl_label = "Sampling"
bl_options = {'DEFAULT_CLOSED'}
@@ -214,7 +214,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
draw_samples_info(layout, context)
-class CyclesRender_PT_geometry(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_geometry(CyclesButtonsPanel, Panel):
bl_label = "Geometry"
bl_options = {'DEFAULT_CLOSED'}
@@ -270,7 +270,7 @@ class CyclesRender_PT_geometry(CyclesButtonsPanel, Panel):
row.prop(ccscene, "maximum_width", text="Max Extension")
-class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_light_paths(CyclesButtonsPanel, Panel):
bl_label = "Light Paths"
bl_options = {'DEFAULT_CLOSED'}
@@ -292,8 +292,6 @@ class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
sub = col.column(align=True)
sub.label("Transparency:")
sub.prop(cscene, "transparent_max_bounces", text="Max")
- sub.prop(cscene, "transparent_min_bounces", text="Min")
- sub.prop(cscene, "use_transparent_shadows", text="Shadows")
col.separator()
@@ -306,7 +304,6 @@ class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
sub = col.column(align=True)
sub.label(text="Bounces:")
sub.prop(cscene, "max_bounces", text="Max")
- sub.prop(cscene, "min_bounces", text="Min")
sub = col.column(align=True)
sub.prop(cscene, "diffuse_bounces", text="Diffuse")
@@ -315,7 +312,7 @@ class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
sub.prop(cscene, "volume_bounces", text="Volume")
-class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
bl_label = "Motion Blur"
bl_options = {'DEFAULT_CLOSED'}
@@ -356,7 +353,7 @@ class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
row.prop(cscene, "rolling_shutter_duration")
-class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_film(CyclesButtonsPanel, Panel):
bl_label = "Film"
def draw(self, context):
@@ -378,7 +375,7 @@ class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
sub.prop(cscene, "filter_width", text="Width")
-class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel):
bl_label = "Performance"
bl_options = {'DEFAULT_CLOSED'}
@@ -399,6 +396,8 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.enabled = rd.threads_mode == 'FIXED'
sub.prop(rd, "threads")
+ col.separator()
+
sub = col.column(align=True)
sub.label(text="Tiles:")
sub.prop(cscene, "tile_order", text="")
@@ -408,19 +407,10 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.prop(cscene, "use_progressive_refine")
- subsub = sub.column(align=True)
- subsub.prop(rd, "use_save_buffers")
-
- col = split.column(align=True)
-
- col.label(text="Viewport:")
- col.prop(cscene, "debug_bvh_type", text="")
- col.separator()
- col.prop(cscene, "preview_start_resolution")
-
- col.separator()
+ col = split.column()
col.label(text="Final Render:")
+ col.prop(rd, "use_save_buffers")
col.prop(rd, "use_persistent_data", text="Persistent Images")
col.separator()
@@ -433,8 +423,14 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
row.active = not cscene.debug_use_spatial_splits
row.prop(cscene, "debug_bvh_time_steps")
+ col = layout.column()
+ col.label(text="Viewport Resolution:")
+ split = col.split()
+ split.prop(rd, "preview_pixel_size", text="")
+ split.prop(cscene, "preview_start_resolution")
-class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
+
+class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel):
bl_label = "Layer"
bl_context = "render_layer"
@@ -470,7 +466,7 @@ class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
col.prop(rl, "use_strand", "Use Hair")
-class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel):
bl_label = "Passes"
bl_context = "render_layer"
bl_options = {'DEFAULT_CLOSED'}
@@ -531,20 +527,20 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_environment")
if context.scene.cycles.feature_set == 'EXPERIMENTAL':
- col.separator()
- sub = col.column()
- sub.active = crl.use_denoising
- sub.prop(crl, "denoising_store_passes", text="Denoising")
+ col.separator()
+ sub = col.column()
+ sub.active = crl.use_denoising
+ sub.prop(crl, "denoising_store_passes", text="Denoising")
if _cycles.with_cycles_debug:
- col = layout.column()
- col.prop(crl, "pass_debug_bvh_traversed_nodes")
- col.prop(crl, "pass_debug_bvh_traversed_instances")
- col.prop(crl, "pass_debug_bvh_intersections")
- col.prop(crl, "pass_debug_ray_bounces")
+ col = layout.column()
+ col.prop(crl, "pass_debug_bvh_traversed_nodes")
+ col.prop(crl, "pass_debug_bvh_traversed_instances")
+ col.prop(crl, "pass_debug_bvh_intersections")
+ col.prop(crl, "pass_debug_ray_bounces")
-class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_views(CyclesButtonsPanel, Panel):
bl_label = "Views"
bl_context = "render_layer"
bl_options = {'DEFAULT_CLOSED'}
@@ -587,7 +583,7 @@ class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
row.prop(rv, "camera_suffix", text="")
-class CyclesRender_PT_denoising(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
bl_label = "Denoising"
bl_context = "render_layer"
bl_options = {'DEFAULT_CLOSED'}
@@ -652,7 +648,7 @@ class CyclesRender_PT_denoising(CyclesButtonsPanel, Panel):
sub.prop(crl, "denoising_subsurface_indirect", text="Indirect", toggle=True)
-class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
+class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
@@ -671,7 +667,7 @@ class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
col.prop(rd, "dither_intensity", text="Dither", slider=True)
-class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
+class CYCLES_CAMERA_PT_dof(CyclesButtonsPanel, Panel):
bl_label = "Depth of Field"
bl_context = "data"
@@ -722,7 +718,7 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
sub.prop(ccam, "aperture_ratio", text="Ratio")
-class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
+class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
bl_label = ""
bl_context = "material"
bl_options = {'HIDE_HEADER'}
@@ -782,7 +778,7 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
split.separator()
-class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
+class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
bl_label = "Motion Blur"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
@@ -830,7 +826,7 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
sub.prop(cob, "motion_steps", text="Steps")
-class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
+class CYCLES_OBJECT_PT_cycles_settings(CyclesButtonsPanel, Panel):
bl_label = "Cycles Settings"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
@@ -939,7 +935,7 @@ def panel_node_draw(layout, id_data, output_type, input_name):
return True
-class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
+class CYCLES_LAMP_PT_preview(CyclesButtonsPanel, Panel):
bl_label = "Preview"
bl_context = "data"
bl_options = {'DEFAULT_CLOSED'}
@@ -955,7 +951,7 @@ class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
self.layout.template_preview(context.lamp)
-class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
+class CYCLES_LAMP_PT_lamp(CyclesButtonsPanel, Panel):
bl_label = "Lamp"
bl_context = "data"
@@ -1009,7 +1005,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
layout.label(text="Not supported, interpreted as sun lamp")
-class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
+class CYCLES_LAMP_PT_nodes(CyclesButtonsPanel, Panel):
bl_label = "Nodes"
bl_context = "data"
@@ -1027,7 +1023,7 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
layout.prop(lamp, "color")
-class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
+class CYCLES_LAMP_PT_spot(CyclesButtonsPanel, Panel):
bl_label = "Spot Shape"
bl_context = "data"
@@ -1052,7 +1048,7 @@ class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
col.prop(lamp, "show_cone")
-class CyclesWorld_PT_preview(CyclesButtonsPanel, Panel):
+class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
bl_label = "Preview"
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@@ -1065,7 +1061,7 @@ class CyclesWorld_PT_preview(CyclesButtonsPanel, Panel):
self.layout.template_preview(context.world)
-class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
+class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface"
bl_context = "world"
@@ -1082,7 +1078,7 @@ class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
layout.prop(world, "horizon_color", text="Color")
-class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
+class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@@ -1099,7 +1095,7 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
-class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
+class CYCLES_WORLD_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
bl_label = "Ambient Occlusion"
bl_context = "world"
@@ -1124,7 +1120,7 @@ class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
row.prop(light, "distance", text="Distance")
-class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel):
+class CYCLES_WORLD_PT_mist(CyclesButtonsPanel, Panel):
bl_label = "Mist Pass"
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@@ -1151,7 +1147,7 @@ class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel):
layout.prop(world.mist_settings, "falloff")
-class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel):
+class CYCLES_WORLD_PT_ray_visibility(CyclesButtonsPanel, Panel):
bl_label = "Ray Visibility"
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@@ -1175,7 +1171,7 @@ class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel):
flow.prop(visibility, "scatter")
-class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
+class CYCLES_WORLD_PT_settings(CyclesButtonsPanel, Panel):
bl_label = "Settings"
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@@ -1216,7 +1212,7 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
col.prop(cworld, "homogeneous_volume", text="Homogeneous")
-class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
+class CYCLES_MATERIAL_PT_preview(CyclesButtonsPanel, Panel):
bl_label = "Preview"
bl_context = "material"
bl_options = {'DEFAULT_CLOSED'}
@@ -1229,7 +1225,7 @@ class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
self.layout.template_preview(context.material)
-class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
+class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface"
bl_context = "material"
@@ -1245,7 +1241,7 @@ class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
layout.prop(mat, "diffuse_color")
-class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
+class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
bl_context = "material"
bl_options = {'DEFAULT_CLOSED'}
@@ -1264,7 +1260,7 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
-class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
+class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
bl_label = "Displacement"
bl_context = "material"
@@ -1280,7 +1276,7 @@ class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
-class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
+class CYCLES_MATERIAL_PT_settings(CyclesButtonsPanel, Panel):
bl_label = "Settings"
bl_context = "material"
bl_options = {'DEFAULT_CLOSED'}
@@ -1335,7 +1331,7 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
col.prop(mat, "pass_index")
-class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
+class CYCLES_TEXTURE_PT_context(CyclesButtonsPanel, Panel):
bl_label = ""
bl_context = "texture"
bl_options = {'HIDE_HEADER'}
@@ -1376,7 +1372,7 @@ class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
split.prop(tex, "type", text="")
-class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
+class CYCLES_TEXTURE_PT_node(CyclesButtonsPanel, Panel):
bl_label = "Node"
bl_context = "texture"
@@ -1393,7 +1389,7 @@ class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
layout.template_node_view(ntree, node, None)
-class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
+class CYCLES_TEXTURE_PT_mapping(CyclesButtonsPanel, Panel):
bl_label = "Mapping"
bl_context = "texture"
@@ -1426,7 +1422,7 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
row.prop(mapping, "mapping_z", text="")
-class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
+class CYCLES_TEXTURE_PT_colors(CyclesButtonsPanel, Panel):
bl_label = "Color"
bl_context = "texture"
bl_options = {'DEFAULT_CLOSED'}
@@ -1465,7 +1461,7 @@ class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
layout.template_color_ramp(mapping, "color_ramp", expand=True)
-class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
+class CYCLES_PARTICLE_PT_textures(CyclesButtonsPanel, Panel):
bl_label = "Textures"
bl_context = "particle"
bl_options = {'DEFAULT_CLOSED'}
@@ -1496,7 +1492,7 @@ class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
layout.template_ID(slot, "texture", new="texture.new")
-class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
bl_label = "Bake"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
@@ -1569,7 +1565,7 @@ class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
sub.prop(cbk, "cage_extrusion", text="Ray Distance")
-class CyclesRender_PT_debug(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
bl_label = "Debug"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
@@ -1597,20 +1593,30 @@ class CyclesRender_PT_debug(CyclesButtonsPanel, Panel):
col.prop(cscene, "debug_use_qbvh")
col.prop(cscene, "debug_use_cpu_split_kernel")
+ col.separator()
+
col = layout.column()
col.label('CUDA Flags:')
col.prop(cscene, "debug_use_cuda_adaptive_compile")
col.prop(cscene, "debug_use_cuda_split_kernel")
+ col.separator()
+
col = layout.column()
col.label('OpenCL Flags:')
col.prop(cscene, "debug_opencl_kernel_type", text="Kernel")
col.prop(cscene, "debug_opencl_device_type", text="Device")
col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
col.prop(cscene, "debug_use_opencl_debug", text="Debug")
+ col.prop(cscene, "debug_opencl_mem_limit")
+
+ col.separator()
+
+ col = layout.column()
+ col.prop(cscene, "debug_bvh_type")
-class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
+class CYCLES_PARTICLE_PT_curve_settings(CyclesButtonsPanel, Panel):
bl_label = "Cycles Hair Settings"
bl_context = "particle"
@@ -1641,7 +1647,7 @@ class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
row.prop(cpsys, "use_closetip", text="Close tip")
-class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
+class CYCLES_SCENE_PT_simplify(CyclesButtonsPanel, Panel):
bl_label = "Simplify"
bl_context = "scene"
COMPAT_ENGINES = {'CYCLES'}
@@ -1710,7 +1716,7 @@ def draw_device(self, context):
layout.prop(cscene, "feature_set")
- split = layout.split(percentage=1/3)
+ split = layout.split(percentage=1 / 3)
split.label("Device:")
row = split.row()
row.active = show_device_active(context)
@@ -1796,47 +1802,47 @@ def get_panels():
classes = (
CYCLES_MT_sampling_presets,
CYCLES_MT_integrator_presets,
- CyclesRender_PT_sampling,
- CyclesRender_PT_geometry,
- CyclesRender_PT_light_paths,
- CyclesRender_PT_motion_blur,
- CyclesRender_PT_film,
- CyclesRender_PT_performance,
- CyclesRender_PT_layer_options,
- CyclesRender_PT_layer_passes,
- CyclesRender_PT_views,
- CyclesRender_PT_denoising,
- Cycles_PT_post_processing,
- CyclesCamera_PT_dof,
- Cycles_PT_context_material,
- CyclesObject_PT_motion_blur,
- CyclesObject_PT_cycles_settings,
+ CYCLES_RENDER_PT_sampling,
+ CYCLES_RENDER_PT_geometry,
+ CYCLES_RENDER_PT_light_paths,
+ CYCLES_RENDER_PT_motion_blur,
+ CYCLES_RENDER_PT_film,
+ CYCLES_RENDER_PT_performance,
+ CYCLES_RENDER_PT_layer_options,
+ CYCLES_RENDER_PT_layer_passes,
+ CYCLES_RENDER_PT_views,
+ CYCLES_RENDER_PT_denoising,
+ CYCLES_PT_post_processing,
+ CYCLES_CAMERA_PT_dof,
+ CYCLES_PT_context_material,
+ CYCLES_OBJECT_PT_motion_blur,
+ CYCLES_OBJECT_PT_cycles_settings,
CYCLES_OT_use_shading_nodes,
- CyclesLamp_PT_preview,
- CyclesLamp_PT_lamp,
- CyclesLamp_PT_nodes,
- CyclesLamp_PT_spot,
- CyclesWorld_PT_preview,
- CyclesWorld_PT_surface,
- CyclesWorld_PT_volume,
- CyclesWorld_PT_ambient_occlusion,
- CyclesWorld_PT_mist,
- CyclesWorld_PT_ray_visibility,
- CyclesWorld_PT_settings,
- CyclesMaterial_PT_preview,
- CyclesMaterial_PT_surface,
- CyclesMaterial_PT_volume,
- CyclesMaterial_PT_displacement,
- CyclesMaterial_PT_settings,
- CyclesTexture_PT_context,
- CyclesTexture_PT_node,
- CyclesTexture_PT_mapping,
- CyclesTexture_PT_colors,
- CyclesParticle_PT_textures,
- CyclesRender_PT_bake,
- CyclesRender_PT_debug,
- CyclesParticle_PT_CurveSettings,
- CyclesScene_PT_simplify,
+ CYCLES_LAMP_PT_preview,
+ CYCLES_LAMP_PT_lamp,
+ CYCLES_LAMP_PT_nodes,
+ CYCLES_LAMP_PT_spot,
+ CYCLES_WORLD_PT_preview,
+ CYCLES_WORLD_PT_surface,
+ CYCLES_WORLD_PT_volume,
+ CYCLES_WORLD_PT_ambient_occlusion,
+ CYCLES_WORLD_PT_mist,
+ CYCLES_WORLD_PT_ray_visibility,
+ CYCLES_WORLD_PT_settings,
+ CYCLES_MATERIAL_PT_preview,
+ CYCLES_MATERIAL_PT_surface,
+ CYCLES_MATERIAL_PT_volume,
+ CYCLES_MATERIAL_PT_displacement,
+ CYCLES_MATERIAL_PT_settings,
+ CYCLES_TEXTURE_PT_context,
+ CYCLES_TEXTURE_PT_node,
+ CYCLES_TEXTURE_PT_mapping,
+ CYCLES_TEXTURE_PT_colors,
+ CYCLES_PARTICLE_PT_textures,
+ CYCLES_RENDER_PT_bake,
+ CYCLES_RENDER_PT_debug,
+ CYCLES_PARTICLE_PT_curve_settings,
+ CYCLES_SCENE_PT_simplify,
)
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
index b2a745500a1..efd794461d6 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -302,3 +302,16 @@ def do_versions(self):
cscene = scene.cycles
if not cscene.is_property_set("light_sampling_threshold"):
cscene.light_sampling_threshold = 0.0
+
+ if bpy.data.version <= (2, 79, 0):
+ for scene in bpy.data.scenes:
+ cscene = scene.cycles
+ # Default changes
+ if not cscene.is_property_set("aa_samples"):
+ cscene.aa_samples = 4
+ if not cscene.is_property_set("preview_aa_samples"):
+ cscene.preview_aa_samples = 4
+ if not cscene.is_property_set("blur_glossy"):
+ cscene.blur_glossy = 0.0
+ if not cscene.is_property_set("sample_clamp_indirect"):
+ cscene.sample_clamp_indirect = 0.0
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 40d6b25f2b7..b29711d30d3 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -544,7 +544,11 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render,
if(tfm != cam->matrix) {
VLOG(1) << "Camera " << b_ob.name() << " motion detected.";
- if(motion_time == -1.0f) {
+ if(motion_time == 0.0f) {
+ /* When motion blur is not centered in frame, cam->matrix gets reset. */
+ cam->matrix = tfm;
+ }
+ else if(motion_time == -1.0f) {
cam->motion.pre = tfm;
cam->use_motion = true;
}
@@ -573,7 +577,10 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render,
float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
if(fov != cam->fov) {
VLOG(1) << "Camera " << b_ob.name() << " FOV change detected.";
- if(motion_time == -1.0f) {
+ if(motion_time == 0.0f) {
+ cam->fov = fov;
+ }
+ else if(motion_time == -1.0f) {
cam->fov_pre = fov;
cam->use_perspective_motion = true;
}
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 3ebe2d8cf34..430e1066303 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -50,8 +50,7 @@ enum {
* Two triangles has vertex indices in the original Blender-side face.
* If face is already a quad tri_b will not be initialized.
*/
-inline void face_split_tri_indices(const int num_verts,
- const int face_flag,
+inline void face_split_tri_indices(const int face_flag,
int tri_a[3],
int tri_b[3])
{
@@ -59,36 +58,38 @@ inline void face_split_tri_indices(const int num_verts,
tri_a[0] = 0;
tri_a[1] = 1;
tri_a[2] = 3;
- if(num_verts == 4) {
- tri_b[0] = 2;
- tri_b[1] = 3;
- tri_b[2] = 1;
- }
+
+ tri_b[0] = 2;
+ tri_b[1] = 3;
+ tri_b[2] = 1;
}
else /*if(face_flag & FACE_FLAG_DIVIDE_13)*/ {
+ assert(face_flag & FACE_FLAG_DIVIDE_13);
+
tri_a[0] = 0;
tri_a[1] = 1;
tri_a[2] = 2;
- if(num_verts == 4) {
- tri_b[0] = 0;
- tri_b[1] = 2;
- tri_b[2] = 3;
- }
+
+ tri_b[0] = 0;
+ tri_b[1] = 2;
+ tri_b[2] = 3;
}
}
/* Tangent Space */
struct MikkUserData {
- MikkUserData(const BL::Mesh& mesh_,
- BL::MeshTextureFaceLayer *layer_,
- int num_faces_)
- : mesh(mesh_), layer(layer_), num_faces(num_faces_)
+ MikkUserData(const BL::Mesh& b_mesh,
+ BL::MeshTextureFaceLayer *layer,
+ int num_faces)
+ : b_mesh(b_mesh),
+ layer(layer),
+ num_faces(num_faces)
{
tangent.resize(num_faces*4);
}
- BL::Mesh mesh;
+ BL::Mesh b_mesh;
BL::MeshTextureFaceLayer *layer;
int num_faces;
vector<float4> tangent;
@@ -103,7 +104,7 @@ static int mikk_get_num_faces(const SMikkTSpaceContext *context)
static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num)
{
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
- BL::MeshTessFace f = userdata->mesh.tessfaces[face_num];
+ BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num];
int4 vi = get_int4(f.vertices_raw());
return (vi[3] == 0)? 3: 4;
@@ -112,9 +113,9 @@ static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const i
static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num)
{
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
- BL::MeshTessFace f = userdata->mesh.tessfaces[face_num];
+ BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num];
int4 vi = get_int4(f.vertices_raw());
- BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]];
+ BL::MeshVertex v = userdata->b_mesh.vertices[vi[vert_num]];
float3 vP = get_float3(v.co());
P[0] = vP.x;
@@ -148,9 +149,9 @@ static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float
uv[1] = tfuv.y;
}
else {
- int vert_idx = userdata->mesh.tessfaces[face_num].vertices()[vert_num];
+ int vert_idx = userdata->b_mesh.tessfaces[face_num].vertices()[vert_num];
float3 orco =
- get_float3(userdata->mesh.vertices[vert_idx].undeformed_co());
+ get_float3(userdata->b_mesh.vertices[vert_idx].undeformed_co());
float2 tmp = map_to_sphere(make_float3(orco[0], orco[1], orco[2]));
uv[0] = tmp.x;
uv[1] = tmp.y;
@@ -160,12 +161,12 @@ static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float
static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num)
{
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
- BL::MeshTessFace f = userdata->mesh.tessfaces[face_num];
+ BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num];
float3 vN;
if(f.use_smooth()) {
int4 vi = get_int4(f.vertices_raw());
- BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]];
+ BL::MeshVertex v = userdata->b_mesh.vertices[vi[vert_num]];
vN = get_float3(v.normal());
}
else {
@@ -250,7 +251,7 @@ static void mikk_compute_tangents(BL::Mesh& b_mesh,
for(int i = 0; i < nverts.size(); i++) {
int tri_a[3], tri_b[3];
- face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
+ face_split_tri_indices(face_flags[i], tri_a, tri_b);
tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_a[0]]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_a[1]]);
@@ -376,7 +377,7 @@ static void attr_create_vertex_color(Scene *scene,
for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
int tri_a[3], tri_b[3];
- face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
+ face_split_tri_indices(face_flags[i], tri_a, tri_b);
uchar4 colors[4];
colors[0] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color1())));
@@ -469,7 +470,7 @@ static void attr_create_uv_map(Scene *scene,
for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
int tri_a[3], tri_b[3];
- face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
+ face_split_tri_indices(face_flags[i], tri_a, tri_b);
float3 uvs[4];
uvs[0] = get_float3(t->uv1());
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 01570b1e3f9..e268c9a0d35 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -60,6 +60,8 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene)
/* Backup some settings for comparison. */
DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
DebugFlags::OpenCL::KernelType opencl_kernel_type = flags.opencl.kernel_type;
+ /* Synchronize shared flags. */
+ flags.viewport_static_bvh = get_enum(cscene, "debug_bvh_type");
/* Synchronize CPU flags. */
flags.cpu.avx2 = get_boolean(cscene, "debug_use_cpu_avx2");
flags.cpu.avx = get_boolean(cscene, "debug_use_cpu_avx");
@@ -106,6 +108,7 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene)
}
/* Synchronize other OpenCL flags. */
flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug");
+ flags.opencl.mem_limit = ((size_t)get_int(cscene, "debug_opencl_mem_limit"))*1024*1024;
flags.opencl.single_program = get_boolean(cscene, "debug_opencl_kernel_single_program");
return flags.opencl.device_type != opencl_device_type ||
flags.opencl.kernel_type != opencl_kernel_type;
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index c6a59577507..12de3da063f 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -129,9 +129,9 @@ void BlenderSession::create_session()
scene = new Scene(scene_params, session_params.device);
/* setup callbacks for builtin image support */
- scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7);
- scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4);
- scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4);
+ scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7, _8);
+ scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5);
+ scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5);
/* create session */
session = new Session(session_params);
@@ -399,14 +399,7 @@ void BlenderSession::render()
BL::RenderLayer b_rlay = *b_single_rlay;
/* add passes */
- array<Pass> passes;
- if(session_params.device.advanced_shading) {
- passes = sync->sync_render_passes(b_rlay, *b_layer_iter);
- }
- else {
- Pass::add(PASS_COMBINED, passes);
- }
-
+ array<Pass> passes = sync->sync_render_passes(b_rlay, *b_layer_iter, session_params);
buffer_params.passes = passes;
PointerRNA crl = RNA_pointer_get(&b_layer_iter->ptr, "cycles");
@@ -1020,7 +1013,8 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
int &width,
int &height,
int &depth,
- int &channels)
+ int &channels,
+ bool& free_cache)
{
/* empty image */
is_float = false;
@@ -1028,6 +1022,7 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
height = 1;
depth = 0;
channels = 0;
+ free_cache = false;
if(!builtin_data)
return;
@@ -1041,6 +1036,7 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
/* image data */
BL::Image b_image(b_id);
+ free_cache = !b_image.has_data();
is_float = b_image.is_float();
width = b_image.size()[0];
height = b_image.size()[1];
@@ -1101,7 +1097,8 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
bool BlenderSession::builtin_image_pixels(const string &builtin_name,
void *builtin_data,
unsigned char *pixels,
- const size_t pixels_size)
+ const size_t pixels_size,
+ const bool free_cache)
{
if(!builtin_data) {
return false;
@@ -1122,7 +1119,6 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
if(image_pixels && num_pixels * channels == pixels_size) {
memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
- MEM_freeN(image_pixels);
}
else {
if(channels == 1) {
@@ -1141,6 +1137,16 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
}
}
}
+
+ if(image_pixels) {
+ MEM_freeN(image_pixels);
+ }
+
+ /* Free image buffers to save memory during render. */
+ if(free_cache) {
+ b_image.buffers_free();
+ }
+
/* Premultiply, byte images are always straight for Blender. */
unsigned char *cp = pixels;
for(size_t i = 0; i < num_pixels; i++, cp += channels) {
@@ -1154,7 +1160,8 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
void *builtin_data,
float *pixels,
- const size_t pixels_size)
+ const size_t pixels_size,
+ const bool free_cache)
{
if(!builtin_data) {
return false;
@@ -1179,7 +1186,6 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
if(image_pixels && num_pixels * channels == pixels_size) {
memcpy(pixels, image_pixels, pixels_size * sizeof(float));
- MEM_freeN(image_pixels);
}
else {
if(channels == 1) {
@@ -1199,6 +1205,15 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
}
}
+ if(image_pixels) {
+ MEM_freeN(image_pixels);
+ }
+
+ /* Free image buffers to save memory during render. */
+ if(free_cache) {
+ b_image.buffers_free();
+ }
+
return true;
}
else if(b_id.is_a(&RNA_Object)) {
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 536808c5b18..cbd2303d282 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -156,15 +156,18 @@ protected:
int &width,
int &height,
int &depth,
- int &channels);
+ int &channels,
+ bool &free_cache);
bool builtin_image_pixels(const string &builtin_name,
void *builtin_data,
unsigned char *pixels,
- const size_t pixels_size);
+ const size_t pixels_size,
+ const bool free_cache);
bool builtin_image_float_pixels(const string &builtin_name,
void *builtin_data,
float *pixels,
- const size_t pixels_size);
+ const size_t pixels_size,
+ const bool free_cache);
/* Update tile manager to reflect resumable render settings. */
void update_resumable_tile_manager(int num_samples);
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 41723599874..42e3721883f 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -234,7 +234,6 @@ void BlenderSync::sync_integrator()
Integrator *integrator = scene->integrator;
Integrator previntegrator = *integrator;
- integrator->min_bounce = get_int(cscene, "min_bounces");
integrator->max_bounce = get_int(cscene, "max_bounces");
integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
@@ -243,8 +242,6 @@ void BlenderSync::sync_integrator()
integrator->max_volume_bounce = get_int(cscene, "volume_bounces");
integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
- integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
- integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows");
integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
integrator->volume_step_size = get_float(cscene, "volume_step_size");
@@ -553,11 +550,16 @@ int BlenderSync::get_denoising_pass(BL::RenderPass& b_pass)
}
array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
- BL::SceneRenderLayer& b_srlay)
+ BL::SceneRenderLayer& b_srlay,
+ const SessionParams &session_params)
{
array<Pass> passes;
Pass::add(PASS_COMBINED, passes);
+ if(!session_params.device.advanced_shading) {
+ return passes;
+ }
+
/* loop over passes */
BL::RenderLayer::passes_iterator b_pass_iter;
@@ -572,7 +574,9 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
}
PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles");
- if(get_boolean(crp, "denoising_store_passes")) {
+ if(get_boolean(crp, "denoising_store_passes") &&
+ get_boolean(crp, "use_denoising") &&
+ !session_params.progressive_refine) {
b_engine.add_pass("Denoising Normal", 3, "XYZ", b_srlay.name().c_str());
b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_srlay.name().c_str());
b_engine.add_pass("Denoising Albedo", 3, "RGB", b_srlay.name().c_str());
@@ -622,14 +626,10 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
else if(shadingsystem == 1)
params.shadingsystem = SHADINGSYSTEM_OSL;
- if(background)
+ if(background || DebugFlags().viewport_static_bvh)
params.bvh_type = SceneParams::BVH_STATIC;
else
- params.bvh_type = (SceneParams::BVHType)get_enum(
- cscene,
- "debug_bvh_type",
- SceneParams::BVH_NUM_TYPES,
- SceneParams::BVH_STATIC);
+ params.bvh_type = SceneParams::BVH_DYNAMIC;
params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
@@ -803,6 +803,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
}
params.start_resolution = get_int(cscene, "preview_start_resolution");
+ params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
/* other parameters */
if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED)
@@ -823,6 +824,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
params.progressive = false;
params.start_resolution = INT_MAX;
+ params.pixel_size = 1;
}
else
params.progressive = true;
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 0950285d976..4ec46424b5a 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -68,7 +68,8 @@ public:
const char *layer = 0);
void sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer);
array<Pass> sync_render_passes(BL::RenderLayer& b_rlay,
- BL::SceneRenderLayer& b_srlay);
+ BL::SceneRenderLayer& b_srlay,
+ const SessionParams &session_params);
void sync_integrator();
void sync_camera(BL::RenderSettings& b_render,
BL::Object& b_override,
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index ebbf325f95b..363e19f7a20 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -51,8 +51,8 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
bool calc_undeformed,
Mesh::SubdivisionType subdivision_type)
{
- bool subsurf_mod_show_render;
- bool subsurf_mod_show_viewport;
+ bool subsurf_mod_show_render = false;
+ bool subsurf_mod_show_viewport = false;
if(subdivision_type != Mesh::SUBDIVISION_NONE) {
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 33143e2d8aa..0ad3c8a7429 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -153,7 +153,6 @@ void BVH::pack_primitives()
if(pack.prim_index[i] != -1) {
int tob = pack.prim_object[i];
Object *ob = objects[tob];
-
if((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
pack_triangle(i, (float4*)&pack.prim_tri_verts[3 * prim_triangle_index]);
pack.prim_tri_index[i] = 3 * prim_triangle_index;
@@ -162,11 +161,10 @@ void BVH::pack_primitives()
else {
pack.prim_tri_index[i] = -1;
}
-
- pack.prim_visibility[i] = ob->visibility;
-
- if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
+ pack.prim_visibility[i] = ob->visibility_for_tracing();
+ if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
pack.prim_visibility[i] |= PATH_RAY_CURVE;
+ }
}
else {
pack.prim_tri_index[i] = -1;
diff --git a/intern/cycles/bvh/bvh2.cpp b/intern/cycles/bvh/bvh2.cpp
index 340ba7dcf53..9aa8e71dfd0 100644
--- a/intern/cycles/bvh/bvh2.cpp
+++ b/intern/cycles/bvh/bvh2.cpp
@@ -312,10 +312,8 @@ void BVH2::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
}
}
}
-
- visibility |= ob->visibility;
+ visibility |= ob->visibility_for_tracing();
}
-
/* TODO(sergey): De-duplicate with pack_leaf(). */
float4 leaf_data[BVH_NODE_LEAF_SIZE];
leaf_data[0].x = __int_as_float(c0);
diff --git a/intern/cycles/bvh/bvh4.cpp b/intern/cycles/bvh/bvh4.cpp
index 5034ab811d5..777de20423b 100644
--- a/intern/cycles/bvh/bvh4.cpp
+++ b/intern/cycles/bvh/bvh4.cpp
@@ -242,21 +242,21 @@ void BVH4::pack_unaligned_node(int idx,
* so kernel might safely assume there are always 4 child nodes.
*/
- data[1][i] = 1.0f;
- data[2][i] = 0.0f;
- data[3][i] = 0.0f;
+ data[1][i] = NAN;
+ data[2][i] = NAN;
+ data[3][i] = NAN;
- data[4][i] = 0.0f;
- data[5][i] = 0.0f;
- data[6][i] = 0.0f;
+ data[4][i] = NAN;
+ data[5][i] = NAN;
+ data[6][i] = NAN;
- data[7][i] = 0.0f;
- data[8][i] = 0.0f;
- data[9][i] = 0.0f;
+ data[7][i] = NAN;
+ data[8][i] = NAN;
+ data[9][i] = NAN;
- data[10][i] = -FLT_MAX;
- data[11][i] = -FLT_MAX;
- data[12][i] = -FLT_MAX;
+ data[10][i] = NAN;
+ data[11][i] = NAN;
+ data[12][i] = NAN;
data[13][i] = __int_as_float(0);
}
@@ -438,10 +438,8 @@ void BVH4::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
}
}
}
-
- visibility |= ob->visibility;
+ visibility |= ob->visibility_for_tracing();
}
-
/* TODO(sergey): This is actually a copy of pack_leaf(),
* but this chunk of code only knows actual data and has
* no idea about BVHNode.
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 1880964355c..649ce52da05 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -529,7 +529,9 @@ BVHNode* BVHBuild::run()
<< " Allocation slop factor: "
<< ((prim_type.capacity() != 0)
? (float)prim_type.size() / prim_type.capacity()
- : 1.0f) << "\n";
+ : 1.0f) << "\n"
+ << " Maximum depth: "
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_DEPTH)) << "\n";
}
}
@@ -671,7 +673,7 @@ BVHNode* BVHBuild::build_node(const BVHObjectBinning& range, int level)
return create_leaf_node(range, references);
}
}
- /* Check whether unaligned split is better than the regulat one. */
+ /* Check whether unaligned split is better than the regular one. */
if(unalignedSplitSAH < splitSAH) {
do_unalinged_split = true;
}
@@ -865,7 +867,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
prim_time[start] = make_float2(ref->time_from(), ref->time_to());
}
- uint visibility = objects[ref->prim_object()]->visibility;
+ const uint visibility = objects[ref->prim_object()]->visibility_for_tracing();
BVHNode *leaf_node = new LeafNode(ref->bounds(), visibility, start, start+1);
leaf_node->time_from = ref->time_from();
leaf_node->time_to = ref->time_to();
@@ -939,7 +941,7 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
ref.time_to()));
bounds[type_index].grow(ref.bounds());
- visibility[type_index] |= objects[ref.prim_object()]->visibility;
+ visibility[type_index] |= objects[ref.prim_object()]->visibility_for_tracing();
if(ref.prim_type() & PRIMITIVE_ALL_CURVE) {
visibility[type_index] |= PATH_RAY_CURVE;
}
@@ -1040,7 +1042,6 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
*/
start_index = spatial_free_index;
spatial_free_index += range.size();
-
/* Extend an array when needed. */
const size_t range_end = start_index + range.size();
if(prim_type.size() < range_end) {
@@ -1066,8 +1067,6 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
prim_time.resize(range_end);
}
}
- spatial_spin_lock.unlock();
-
/* Perform actual data copy. */
if(new_leaf_data_size > 0) {
memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
@@ -1077,6 +1076,7 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2)*num_new_leaf_data);
}
}
+ spatial_spin_lock.unlock();
}
else {
/* For the regular BVH builder we simply copy new data starting at the
diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp
index 4237c62ab5b..ab6df4d265d 100644
--- a/intern/cycles/bvh/bvh_node.cpp
+++ b/intern/cycles/bvh/bvh_node.cpp
@@ -132,6 +132,17 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
case BVH_STAT_UNALIGNED_LEAF_COUNT:
cnt = (is_leaf() && is_unaligned) ? 1 : 0;
break;
+ case BVH_STAT_DEPTH:
+ if(is_leaf()) {
+ cnt = 1;
+ }
+ else {
+ for(int i = 0; i < num_children(); i++) {
+ cnt = max(cnt, get_child(i)->getSubtreeSize(stat));
+ }
+ cnt += 1;
+ }
+ return cnt;
default:
assert(0); /* unknown mode */
}
diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h
index 1c875f5a524..94cf5ab730c 100644
--- a/intern/cycles/bvh/bvh_node.h
+++ b/intern/cycles/bvh/bvh_node.h
@@ -38,6 +38,7 @@ enum BVH_STAT {
BVH_STAT_UNALIGNED_INNER_QNODE_COUNT,
BVH_STAT_ALIGNED_LEAF_COUNT,
BVH_STAT_UNALIGNED_LEAF_COUNT,
+ BVH_STAT_DEPTH,
};
class BVHParams;
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index 74ec57ddf74..3c632160fbd 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -34,11 +34,13 @@ set(SRC
set(SRC_OPENCL
opencl/opencl.h
+ opencl/memory_manager.h
opencl/opencl_base.cpp
opencl/opencl_mega.cpp
opencl/opencl_split.cpp
opencl/opencl_util.cpp
+ opencl/memory_manager.cpp
)
if(WITH_CYCLES_NETWORK)
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 0603ecb3afb..f64436aec7b 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -68,6 +68,8 @@ std::ostream& operator <<(std::ostream &os,
<< string_from_bool(requested_features.use_transparent) << std::endl;
os << "Use Principled BSDF: "
<< string_from_bool(requested_features.use_principled) << std::endl;
+ os << "Use Denoising: "
+ << string_from_bool(requested_features.use_denoising) << std::endl;
return os;
}
@@ -377,11 +379,9 @@ DeviceInfo Device::get_multi_device(vector<DeviceInfo> subdevices)
info.num = 0;
info.has_bindless_textures = true;
- info.pack_images = false;
foreach(DeviceInfo &device, subdevices) {
assert(device.type == info.multi_devices[0].type);
- info.pack_images |= device.pack_images;
info.has_bindless_textures &= device.has_bindless_textures;
}
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 527940e8f50..26d6d380a10 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -53,7 +53,6 @@ public:
int num;
bool display_device;
bool advanced_shading;
- bool pack_images;
bool has_bindless_textures; /* flag for GPU and Multi device */
bool use_split_kernel; /* Denotes if the device is going to run cycles using split-kernel */
vector<DeviceInfo> multi_devices;
@@ -65,7 +64,6 @@ public:
num = 0;
display_device = false;
advanced_shading = true;
- pack_images = false;
has_bindless_textures = false;
use_split_kernel = false;
}
@@ -127,6 +125,9 @@ public:
/* Per-uber shader usage flags. */
bool use_principled;
+ /* Denoising features. */
+ bool use_denoising;
+
DeviceRequestedFeatures()
{
/* TODO(sergey): Find more meaningful defaults. */
@@ -145,6 +146,7 @@ public:
use_transparent = false;
use_shadow_tricks = false;
use_principled = false;
+ use_denoising = false;
}
bool modified(const DeviceRequestedFeatures& requested_features)
@@ -163,7 +165,8 @@ public:
use_patch_evaluation == requested_features.use_patch_evaluation &&
use_transparent == requested_features.use_transparent &&
use_shadow_tricks == requested_features.use_shadow_tricks &&
- use_principled == requested_features.use_principled);
+ use_principled == requested_features.use_principled &&
+ use_denoising == requested_features.use_denoising);
}
/* Convert the requested features structure to a build options,
@@ -213,6 +216,9 @@ public:
if(!use_principled) {
build_options += " -D__NO_PRINCIPLED__";
}
+ if(!use_denoising) {
+ build_options += " -D__NO_DENOISING__";
+ }
return build_options;
}
};
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index c2f74aa8903..6a1106328fb 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -48,6 +48,7 @@
#include "util/util_logging.h"
#include "util/util_map.h"
#include "util/util_opengl.h"
+#include "util/util_optimization.h"
#include "util/util_progress.h"
#include "util/util_system.h"
#include "util/util_thread.h"
@@ -119,7 +120,7 @@ public:
}
#endif
- if(strstr(architecture_name, logged_architecture) != 0) {
+ if(strcmp(architecture_name, logged_architecture) != 0) {
VLOG(1) << "Will be using " << architecture_name << " kernels.";
logged_architecture = architecture_name;
}
@@ -149,7 +150,8 @@ public:
device_memory& use_queues_flag,
device_memory& work_pool_wgs);
- virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&);
+ virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
+ const DeviceRequestedFeatures&);
virtual int2 split_kernel_local_size();
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
@@ -185,9 +187,9 @@ public:
KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int, int)> filter_nlm_update_output_kernel;
KernelFunctions<void(*)(float*, float*, int*, int)> filter_nlm_normalize_kernel;
- KernelFunctions<void(*)(float*, int, int, int, float*, int*, int*, int, int, float)> filter_construct_transform_kernel;
- KernelFunctions<void(*)(int, int, float*, float*, float*, float*, float*, int*, float*, float3*, int*, int*, int, int, int, int)> filter_nlm_construct_gramian_kernel;
- KernelFunctions<void(*)(int, int, int, int, int, float*, int*, float*, float3*, int*, int)> filter_finalize_kernel;
+ KernelFunctions<void(*)(float*, int, int, int, float*, int*, int*, int, int, float)> filter_construct_transform_kernel;
+ KernelFunctions<void(*)(int, int, float*, float*, float*, int*, float*, float3*, int*, int*, int, int, int, int)> filter_nlm_construct_gramian_kernel;
+ KernelFunctions<void(*)(int, int, int, int, int, float*, int*, float*, float3*, int*, int)> filter_finalize_kernel;
KernelFunctions<void(*)(KernelGlobals *, ccl_constant KernelData*, ccl_global void*, int, ccl_global char*,
ccl_global uint*, int, int, int, int, int, int, int, int, ccl_global int*, int,
@@ -248,6 +250,7 @@ public:
REGISTER_SPLIT_KERNEL(direct_lighting);
REGISTER_SPLIT_KERNEL(shadow_blocked_ao);
REGISTER_SPLIT_KERNEL(shadow_blocked_dl);
+ REGISTER_SPLIT_KERNEL(enqueue_inactive);
REGISTER_SPLIT_KERNEL(next_iteration_setup);
REGISTER_SPLIT_KERNEL(indirect_subsurface);
REGISTER_SPLIT_KERNEL(buffer_update);
@@ -465,8 +468,6 @@ public:
bool denoising_reconstruct(device_ptr color_ptr,
device_ptr color_variance_ptr,
- device_ptr guide_ptr,
- device_ptr guide_variance_ptr,
device_ptr output_ptr,
DenoisingTask *task)
{
@@ -485,8 +486,8 @@ public:
task->reconstruction_state.source_w - max(0, dx),
task->reconstruction_state.source_h - max(0, dy)};
filter_nlm_calc_difference_kernel()(dx, dy,
- (float*) guide_ptr,
- (float*) guide_variance_ptr,
+ (float*) color_ptr,
+ (float*) color_variance_ptr,
difference,
local_rect,
task->buffer.w,
@@ -499,8 +500,6 @@ public:
filter_nlm_construct_gramian_kernel()(dx, dy,
blurDifference,
(float*) task->buffer.mem.device_pointer,
- (float*) color_ptr,
- (float*) color_variance_ptr,
(float*) task->storage.transform.device_pointer,
(int*) task->storage.rank.device_pointer,
(float*) task->storage.XtWX.device_pointer,
@@ -648,7 +647,7 @@ public:
DenoisingTask denoising(this);
denoising.functions.construct_transform = function_bind(&CPUDevice::denoising_construct_transform, this, &denoising);
- denoising.functions.reconstruct = function_bind(&CPUDevice::denoising_reconstruct, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.reconstruct = function_bind(&CPUDevice::denoising_reconstruct, this, _1, _2, _3, &denoising);
denoising.functions.divide_shadow = function_bind(&CPUDevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
denoising.functions.non_local_means = function_bind(&CPUDevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
denoising.functions.combine_halves = function_bind(&CPUDevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
@@ -935,7 +934,8 @@ bool CPUSplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim,
return true;
}
-SplitKernelFunction* CPUSplitKernel::get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&)
+SplitKernelFunction* CPUSplitKernel::get_split_kernel_function(const string& kernel_name,
+ const DeviceRequestedFeatures&)
{
CPUSplitKernelFunction *kernel = new CPUSplitKernelFunction(device);
@@ -977,7 +977,6 @@ void device_cpu_info(vector<DeviceInfo>& devices)
info.id = "CPU";
info.num = 0;
info.advanced_shading = true;
- info.pack_images = false;
devices.insert(devices.begin(), info);
}
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 99537e9a983..3b75142ee67 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -105,7 +105,8 @@ public:
device_memory& use_queues_flag,
device_memory& work_pool_wgs);
- virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&);
+ virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
+ const DeviceRequestedFeatures&);
virtual int2 split_kernel_local_size();
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
};
@@ -1051,8 +1052,6 @@ public:
bool denoising_reconstruct(device_ptr color_ptr,
device_ptr color_variance_ptr,
- device_ptr guide_ptr,
- device_ptr guide_variance_ptr,
device_ptr output_ptr,
DenoisingTask *task)
{
@@ -1096,8 +1095,8 @@ public:
task->reconstruction_state.source_h - max(0, dy)};
void *calc_difference_args[] = {&dx, &dy,
- &guide_ptr,
- &guide_variance_ptr,
+ &color_ptr,
+ &color_variance_ptr,
&difference,
&local_rect,
&task->buffer.w,
@@ -1126,8 +1125,6 @@ public:
void *construct_gramian_args[] = {&dx, &dy,
&blurDifference,
&task->buffer.mem.device_pointer,
- &color_ptr,
- &color_variance_ptr,
&task->storage.transform.device_pointer,
&task->storage.rank.device_pointer,
&task->storage.XtWX.device_pointer,
@@ -1294,7 +1291,7 @@ public:
DenoisingTask denoising(this);
denoising.functions.construct_transform = function_bind(&CUDADevice::denoising_construct_transform, this, &denoising);
- denoising.functions.reconstruct = function_bind(&CUDADevice::denoising_reconstruct, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.reconstruct = function_bind(&CUDADevice::denoising_reconstruct, this, _1, _2, _3, &denoising);
denoising.functions.divide_shadow = function_bind(&CUDADevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
denoising.functions.non_local_means = function_bind(&CUDADevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
denoising.functions.combine_halves = function_bind(&CUDADevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
@@ -1901,17 +1898,13 @@ public:
int threads_per_block;
cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func));
- int xthreads = (int)sqrt(threads_per_block);
- int ythreads = (int)sqrt(threads_per_block);
-
- int xblocks = (dim.global_size[0] + xthreads - 1)/xthreads;
- int yblocks = (dim.global_size[1] + ythreads - 1)/ythreads;
+ int xblocks = (dim.global_size[0]*dim.global_size[1] + threads_per_block - 1)/threads_per_block;
cuda_assert(cuFuncSetCacheConfig(func, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuLaunchKernel(func,
- xblocks , yblocks, 1, /* blocks */
- xthreads, ythreads, 1, /* threads */
+ xblocks, 1, 1, /* blocks */
+ threads_per_block, 1, 1, /* threads */
0, 0, args, 0));
device->cuda_pop_context();
@@ -2041,7 +2034,8 @@ bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim
return !device->have_error();
}
-SplitKernelFunction* CUDASplitKernel::get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&)
+SplitKernelFunction* CUDASplitKernel::get_split_kernel_function(const string& kernel_name,
+ const DeviceRequestedFeatures&)
{
CUfunction func;
@@ -2129,18 +2123,34 @@ Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background)
return new CUDADevice(info, stats, background);
}
-void device_cuda_info(vector<DeviceInfo>& devices)
+static CUresult device_cuda_safe_init()
{
- CUresult result;
- int count = 0;
+#ifdef _WIN32
+ __try {
+ return cuInit(0);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ /* Ignore crashes inside the CUDA driver and hope we can
+ * survive even with corrupted CUDA installs. */
+ fprintf(stderr, "Cycles CUDA: driver crashed, continuing without CUDA.\n");
+ }
+
+ return CUDA_ERROR_NO_DEVICE;
+#else
+ return cuInit(0);
+#endif
+}
- result = cuInit(0);
+void device_cuda_info(vector<DeviceInfo>& devices)
+{
+ CUresult result = device_cuda_safe_init();
if(result != CUDA_SUCCESS) {
if(result != CUDA_ERROR_NO_DEVICE)
fprintf(stderr, "CUDA cuInit: %s\n", cuewErrorString(result));
return;
}
+ int count = 0;
result = cuDeviceGetCount(&count);
if(result != CUDA_SUCCESS) {
fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", cuewErrorString(result));
@@ -2170,7 +2180,6 @@ void device_cuda_info(vector<DeviceInfo>& devices)
info.advanced_shading = (major >= 2);
info.has_bindless_textures = (major >= 3);
- info.pack_images = false;
int pci_location[3] = {0, 0, 0};
cuDeviceGetAttribute(&pci_location[0], CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, num);
@@ -2198,7 +2207,7 @@ void device_cuda_info(vector<DeviceInfo>& devices)
string device_cuda_capabilities(void)
{
- CUresult result = cuInit(0);
+ CUresult result = device_cuda_safe_init();
if(result != CUDA_SUCCESS) {
if(result != CUDA_ERROR_NO_DEVICE) {
return string("Error initializing CUDA: ") + cuewErrorString(result);
diff --git a/intern/cycles/device/device_denoising.cpp b/intern/cycles/device/device_denoising.cpp
index 613bd9112cf..619cc1d171e 100644
--- a/intern/cycles/device/device_denoising.cpp
+++ b/intern/cycles/device/device_denoising.cpp
@@ -215,7 +215,7 @@ bool DenoisingTask::run_denoising()
{
device_sub_ptr color_ptr (device, buffer.mem, 8*buffer.pass_stride, 3*buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr color_var_ptr(device, buffer.mem, 11*buffer.pass_stride, 3*buffer.pass_stride, MEM_READ_WRITE);
- functions.reconstruct(*color_ptr, *color_var_ptr, *color_ptr, *color_var_ptr, render_buffer.ptr);
+ functions.reconstruct(*color_ptr, *color_var_ptr, render_buffer.ptr);
}
device->mem_free(storage.XtWX);
diff --git a/intern/cycles/device/device_denoising.h b/intern/cycles/device/device_denoising.h
index 25b93c2ad74..def7b72f67d 100644
--- a/intern/cycles/device/device_denoising.h
+++ b/intern/cycles/device/device_denoising.h
@@ -58,8 +58,6 @@ public:
)> non_local_means;
function<bool(device_ptr color_ptr,
device_ptr color_variance_ptr,
- device_ptr guide_ptr,
- device_ptr guide_variance_ptr,
device_ptr output_ptr
)> reconstruct;
function<bool()> construct_transform;
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index 66758954f44..571ba9465ca 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -344,7 +344,6 @@ void device_network_info(vector<DeviceInfo>& devices)
info.id = "NETWORK";
info.num = 0;
info.advanced_shading = true; /* todo: get this info from device */
- info.pack_images = false;
devices.push_back(info);
}
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index edd2047debc..9d89decaaaf 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -73,8 +73,34 @@ bool device_opencl_init(void)
return result;
}
+
+static cl_int device_opencl_get_num_platforms_safe(cl_uint *num_platforms)
+{
+#ifdef _WIN32
+ __try {
+ return clGetPlatformIDs(0, NULL, num_platforms);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ /* Ignore crashes inside the OpenCL driver and hope we can
+ * survive even with corrupted OpenCL installs. */
+ fprintf(stderr, "Cycles OpenCL: driver crashed, continuing without OpenCL.\n");
+ }
+
+ *num_platforms = 0;
+ return CL_DEVICE_NOT_FOUND;
+#else
+ return clGetPlatformIDs(0, NULL, num_platforms);
+#endif
+}
+
void device_opencl_info(vector<DeviceInfo>& devices)
{
+ cl_uint num_platforms = 0;
+ device_opencl_get_num_platforms_safe(&num_platforms);
+ if(num_platforms == 0) {
+ return;
+ }
+
vector<OpenCLPlatformDevice> usable_devices;
OpenCLInfo::get_usable_devices(&usable_devices);
/* Devices are numbered consecutively across platforms. */
@@ -95,7 +121,6 @@ void device_opencl_info(vector<DeviceInfo>& devices)
/* We don't know if it's used for display, but assume it is. */
info.display_device = true;
info.advanced_shading = OpenCLInfo::kernel_use_advanced_shading(platform_name);
- info.pack_images = true;
info.use_split_kernel = OpenCLInfo::kernel_use_split(platform_name,
device_type);
info.id = string("OPENCL_") + platform_name + "_" + device_name + "_" + hardware_id;
@@ -114,7 +139,7 @@ string device_opencl_capabilities(void)
* it could also be nicely reported to the console.
*/
cl_uint num_platforms = 0;
- opencl_assert(clGetPlatformIDs(0, NULL, &num_platforms));
+ opencl_assert(device_opencl_get_num_platforms_safe(&num_platforms));
if(num_platforms == 0) {
return "No OpenCL platforms found\n";
}
@@ -130,10 +155,22 @@ string device_opencl_capabilities(void)
opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
result += string_printf("%s: %s\n", name, data); \
} while(false)
+#define APPEND_STRING_EXTENSION_INFO(func, id, name, what) \
+ do { \
+ char data[1024] = "\0"; \
+ size_t length = 0; \
+ if(func(id, what, sizeof(data), &data, &length) == CL_SUCCESS) { \
+ if(length != 0 && data[0] != '\0') { \
+ result += string_printf("%s: %s\n", name, data); \
+ } \
+ } \
+ } while(false)
#define APPEND_PLATFORM_STRING_INFO(id, name, what) \
APPEND_STRING_INFO(clGetPlatformInfo, id, "\tPlatform " name, what)
#define APPEND_DEVICE_STRING_INFO(id, name, what) \
APPEND_STRING_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
+#define APPEND_DEVICE_STRING_EXTENSION_INFO(id, name, what) \
+ APPEND_STRING_EXTENSION_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
vector<cl_device_id> device_ids;
for(cl_uint platform = 0; platform < num_platforms; ++platform) {
@@ -167,6 +204,7 @@ string device_opencl_capabilities(void)
result += string_printf("\t\tDevice: #%u\n", device);
APPEND_DEVICE_STRING_INFO(device_id, "Name", CL_DEVICE_NAME);
+ APPEND_DEVICE_STRING_EXTENSION_INFO(device_id, "Board Name", CL_DEVICE_BOARD_NAME_AMD);
APPEND_DEVICE_STRING_INFO(device_id, "Vendor", CL_DEVICE_VENDOR);
APPEND_DEVICE_STRING_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION);
APPEND_DEVICE_STRING_INFO(device_id, "Profile", CL_DEVICE_PROFILE);
diff --git a/intern/cycles/device/device_split_kernel.cpp b/intern/cycles/device/device_split_kernel.cpp
index dddd19f179f..d2b3a89fa98 100644
--- a/intern/cycles/device/device_split_kernel.cpp
+++ b/intern/cycles/device/device_split_kernel.cpp
@@ -47,6 +47,7 @@ DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device)
kernel_direct_lighting = NULL;
kernel_shadow_blocked_ao = NULL;
kernel_shadow_blocked_dl = NULL;
+ kernel_enqueue_inactive = NULL;
kernel_next_iteration_setup = NULL;
kernel_indirect_subsurface = NULL;
kernel_buffer_update = NULL;
@@ -74,6 +75,7 @@ DeviceSplitKernel::~DeviceSplitKernel()
delete kernel_direct_lighting;
delete kernel_shadow_blocked_ao;
delete kernel_shadow_blocked_dl;
+ delete kernel_enqueue_inactive;
delete kernel_next_iteration_setup;
delete kernel_indirect_subsurface;
delete kernel_buffer_update;
@@ -101,6 +103,7 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe
LOAD_KERNEL(direct_lighting);
LOAD_KERNEL(shadow_blocked_ao);
LOAD_KERNEL(shadow_blocked_dl);
+ LOAD_KERNEL(enqueue_inactive);
LOAD_KERNEL(next_iteration_setup);
LOAD_KERNEL(indirect_subsurface);
LOAD_KERNEL(buffer_update);
@@ -256,6 +259,7 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(shadow_blocked_ao, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(shadow_blocked_dl, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(enqueue_inactive, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(indirect_subsurface, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
diff --git a/intern/cycles/device/device_split_kernel.h b/intern/cycles/device/device_split_kernel.h
index 68c2ba974a5..9c42cb58520 100644
--- a/intern/cycles/device/device_split_kernel.h
+++ b/intern/cycles/device/device_split_kernel.h
@@ -69,6 +69,7 @@ private:
SplitKernelFunction *kernel_direct_lighting;
SplitKernelFunction *kernel_shadow_blocked_ao;
SplitKernelFunction *kernel_shadow_blocked_dl;
+ SplitKernelFunction *kernel_enqueue_inactive;
SplitKernelFunction *kernel_next_iteration_setup;
SplitKernelFunction *kernel_indirect_subsurface;
SplitKernelFunction *kernel_buffer_update;
@@ -124,7 +125,8 @@ public:
device_memory& use_queues_flag,
device_memory& work_pool_wgs) = 0;
- virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&) = 0;
+ virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
+ const DeviceRequestedFeatures&) = 0;
virtual int2 split_kernel_local_size() = 0;
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task) = 0;
};
diff --git a/intern/cycles/device/opencl/memory_manager.cpp b/intern/cycles/device/opencl/memory_manager.cpp
new file mode 100644
index 00000000000..b67dfef88aa
--- /dev/null
+++ b/intern/cycles/device/opencl/memory_manager.cpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2011-2017 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.
+ */
+
+#ifdef WITH_OPENCL
+
+#include "util/util_foreach.h"
+
+#include "device/opencl/opencl.h"
+#include "device/opencl/memory_manager.h"
+
+CCL_NAMESPACE_BEGIN
+
+void MemoryManager::DeviceBuffer::add_allocation(Allocation& allocation)
+{
+ allocations.push_back(&allocation);
+}
+
+void MemoryManager::DeviceBuffer::update_device_memory(OpenCLDeviceBase *device)
+{
+ bool need_realloc = false;
+
+ /* Calculate total size and remove any freed. */
+ size_t total_size = 0;
+
+ for(int i = allocations.size()-1; i >= 0; i--) {
+ Allocation* allocation = allocations[i];
+
+ /* Remove allocations that have been freed. */
+ if(!allocation->mem || allocation->mem->memory_size() == 0) {
+ allocation->device_buffer = NULL;
+ allocation->size = 0;
+
+ allocations.erase(allocations.begin()+i);
+
+ need_realloc = true;
+
+ continue;
+ }
+
+ /* Get actual size for allocation. */
+ size_t alloc_size = align_up(allocation->mem->memory_size(), 16);
+
+ if(allocation->size != alloc_size) {
+ /* Allocation is either new or resized. */
+ allocation->size = alloc_size;
+ allocation->needs_copy_to_device = true;
+
+ need_realloc = true;
+ }
+
+ total_size += alloc_size;
+ }
+
+ if(need_realloc) {
+ cl_ulong max_buffer_size;
+ clGetDeviceInfo(device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
+
+ if(total_size > max_buffer_size) {
+ device->set_error("Scene too complex to fit in available memory.");
+ return;
+ }
+
+ device_memory *new_buffer = new device_memory;
+
+ new_buffer->resize(total_size);
+ device->mem_alloc(string_printf("buffer_%p", this).data(), *new_buffer, MEM_READ_ONLY);
+
+ size_t offset = 0;
+
+ foreach(Allocation* allocation, allocations) {
+ if(allocation->needs_copy_to_device) {
+ /* Copy from host to device. */
+ opencl_device_assert(device, clEnqueueWriteBuffer(device->cqCommandQueue,
+ CL_MEM_PTR(new_buffer->device_pointer),
+ CL_FALSE,
+ offset,
+ allocation->mem->memory_size(),
+ (void*)allocation->mem->data_pointer,
+ 0, NULL, NULL
+ ));
+
+ allocation->needs_copy_to_device = false;
+ }
+ else {
+ /* Fast copy from memory already on device. */
+ opencl_device_assert(device, clEnqueueCopyBuffer(device->cqCommandQueue,
+ CL_MEM_PTR(buffer->device_pointer),
+ CL_MEM_PTR(new_buffer->device_pointer),
+ allocation->desc.offset,
+ offset,
+ allocation->mem->memory_size(),
+ 0, NULL, NULL
+ ));
+ }
+
+ allocation->desc.offset = offset;
+ offset += allocation->size;
+ }
+
+ device->mem_free(*buffer);
+ delete buffer;
+
+ buffer = new_buffer;
+ }
+ else {
+ assert(total_size == buffer->data_size);
+
+ size_t offset = 0;
+
+ foreach(Allocation* allocation, allocations) {
+ if(allocation->needs_copy_to_device) {
+ /* Copy from host to device. */
+ opencl_device_assert(device, clEnqueueWriteBuffer(device->cqCommandQueue,
+ CL_MEM_PTR(buffer->device_pointer),
+ CL_FALSE,
+ offset,
+ allocation->mem->memory_size(),
+ (void*)allocation->mem->data_pointer,
+ 0, NULL, NULL
+ ));
+
+ allocation->needs_copy_to_device = false;
+ }
+
+ offset += allocation->size;
+ }
+ }
+
+ /* Not really necessary, but seems to improve responsiveness for some reason. */
+ clFinish(device->cqCommandQueue);
+}
+
+void MemoryManager::DeviceBuffer::free(OpenCLDeviceBase *device)
+{
+ device->mem_free(*buffer);
+}
+
+MemoryManager::DeviceBuffer* MemoryManager::smallest_device_buffer()
+{
+ DeviceBuffer* smallest = device_buffers;
+
+ foreach(DeviceBuffer& device_buffer, device_buffers) {
+ if(device_buffer.size < smallest->size) {
+ smallest = &device_buffer;
+ }
+ }
+
+ return smallest;
+}
+
+MemoryManager::MemoryManager(OpenCLDeviceBase *device) : device(device), need_update(false)
+{
+}
+
+void MemoryManager::free()
+{
+ foreach(DeviceBuffer& device_buffer, device_buffers) {
+ device_buffer.free(device);
+ }
+}
+
+void MemoryManager::alloc(const char *name, device_memory& mem)
+{
+ Allocation& allocation = allocations[name];
+
+ allocation.mem = &mem;
+ allocation.needs_copy_to_device = true;
+
+ if(!allocation.device_buffer) {
+ DeviceBuffer* device_buffer = smallest_device_buffer();
+ allocation.device_buffer = device_buffer;
+
+ allocation.desc.device_buffer = device_buffer - device_buffers;
+
+ device_buffer->add_allocation(allocation);
+
+ device_buffer->size += mem.memory_size();
+ }
+
+ need_update = true;
+}
+
+bool MemoryManager::free(device_memory& mem)
+{
+ foreach(AllocationsMap::value_type& value, allocations) {
+ Allocation& allocation = value.second;
+ if(allocation.mem == &mem) {
+
+ allocation.device_buffer->size -= mem.memory_size();
+
+ allocation.mem = NULL;
+ allocation.needs_copy_to_device = false;
+
+ need_update = true;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+MemoryManager::BufferDescriptor MemoryManager::get_descriptor(string name)
+{
+ update_device_memory();
+
+ Allocation& allocation = allocations[name];
+ return allocation.desc;
+}
+
+void MemoryManager::update_device_memory()
+{
+ if(!need_update) {
+ return;
+ }
+
+ need_update = false;
+
+ foreach(DeviceBuffer& device_buffer, device_buffers) {
+ device_buffer.update_device_memory(device);
+ }
+}
+
+void MemoryManager::set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg)
+{
+ update_device_memory();
+
+ foreach(DeviceBuffer& device_buffer, device_buffers) {
+ if(device_buffer.buffer->device_pointer) {
+ device->kernel_set_args(kernel, (*narg)++, *device_buffer.buffer);
+ }
+ else {
+ device->kernel_set_args(kernel, (*narg)++, device->null_mem);
+ }
+ }
+}
+
+CCL_NAMESPACE_END
+
+#endif /* WITH_OPENCL */
+
diff --git a/intern/cycles/device/opencl/memory_manager.h b/intern/cycles/device/opencl/memory_manager.h
new file mode 100644
index 00000000000..3714405d026
--- /dev/null
+++ b/intern/cycles/device/opencl/memory_manager.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2011-2017 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.
+ */
+
+#pragma once
+
+#include "device/device.h"
+
+#include "util/util_map.h"
+#include "util/util_vector.h"
+#include "util/util_string.h"
+
+#include "clew.h"
+
+CCL_NAMESPACE_BEGIN
+
+class OpenCLDeviceBase;
+
+class MemoryManager {
+public:
+ static const int NUM_DEVICE_BUFFERS = 8;
+
+ struct BufferDescriptor {
+ uint device_buffer;
+ cl_ulong offset;
+ };
+
+private:
+ struct DeviceBuffer;
+
+ struct Allocation {
+ device_memory *mem;
+
+ DeviceBuffer *device_buffer;
+ size_t size; /* Size of actual allocation, may be larger than requested. */
+
+ BufferDescriptor desc;
+
+ bool needs_copy_to_device;
+
+ Allocation() : mem(NULL), device_buffer(NULL), size(0), needs_copy_to_device(false)
+ {
+ }
+ };
+
+ struct DeviceBuffer {
+ device_memory *buffer;
+ vector<Allocation*> allocations;
+ size_t size; /* Size of all allocations. */
+
+ DeviceBuffer() : buffer(new device_memory), size(0)
+ {
+ }
+
+ ~DeviceBuffer() {
+ delete buffer;
+ buffer = NULL;
+ }
+
+ void add_allocation(Allocation& allocation);
+
+ void update_device_memory(OpenCLDeviceBase *device);
+
+ void free(OpenCLDeviceBase *device);
+ };
+
+ OpenCLDeviceBase *device;
+
+ DeviceBuffer device_buffers[NUM_DEVICE_BUFFERS];
+
+ typedef unordered_map<string, Allocation> AllocationsMap;
+ AllocationsMap allocations;
+
+ bool need_update;
+
+ DeviceBuffer* smallest_device_buffer();
+
+public:
+ MemoryManager(OpenCLDeviceBase *device);
+
+ void free(); /* Free all memory. */
+
+ void alloc(const char *name, device_memory& mem);
+ bool free(device_memory& mem);
+
+ BufferDescriptor get_descriptor(string name);
+
+ void update_device_memory();
+ void set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg);
+};
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/device/opencl/opencl.h b/intern/cycles/device/opencl/opencl.h
index 27e196d1e68..26bf4a9af5b 100644
--- a/intern/cycles/device/opencl/opencl.h
+++ b/intern/cycles/device/opencl/opencl.h
@@ -25,8 +25,13 @@
#include "clew.h"
+#include "device/opencl/memory_manager.h"
+
CCL_NAMESPACE_BEGIN
+/* Disable workarounds, seems to be working fine on latest drivers. */
+#define CYCLES_DISABLE_DRIVER_WORKAROUNDS
+
/* Define CYCLES_DISABLE_DRIVER_WORKAROUNDS to disable workaounds for testing */
#ifndef CYCLES_DISABLE_DRIVER_WORKAROUNDS
/* Work around AMD driver hangs by ensuring each command is finished before doing anything else. */
@@ -84,7 +89,7 @@ public:
string *error = NULL);
static bool device_version_check(cl_device_id device,
string *error = NULL);
- static string get_hardware_id(string platform_name,
+ static string get_hardware_id(const string& platform_name,
cl_device_id device_id);
static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
bool force_all = false);
@@ -130,6 +135,11 @@ public:
cl_int* error = NULL);
static cl_device_type get_device_type(cl_device_id device_id);
+ static bool get_driver_version(cl_device_id device_id,
+ int *major,
+ int *minor,
+ cl_int* error = NULL);
+
static int mem_address_alignment(cl_device_id device_id);
/* Get somewhat more readable device name.
@@ -216,6 +226,18 @@ public:
static string get_kernel_md5();
};
+#define opencl_device_assert(device, stmt) \
+ { \
+ cl_int err = stmt; \
+ \
+ if(err != CL_SUCCESS) { \
+ string message = string_printf("OpenCL error: %s in %s (%s:%d)", clewErrorString(err), #stmt, __FILE__, __LINE__); \
+ if((device)->error_message() == "") \
+ (device)->set_error(message); \
+ fprintf(stderr, "%s\n", message.c_str()); \
+ } \
+ } (void)0
+
#define opencl_assert(stmt) \
{ \
cl_int err = stmt; \
@@ -242,17 +264,17 @@ public:
public:
OpenCLProgram() : loaded(false), device(NULL) {}
OpenCLProgram(OpenCLDeviceBase *device,
- string program_name,
- string kernel_name,
- string kernel_build_options,
+ const string& program_name,
+ const string& kernel_name,
+ const string& kernel_build_options,
bool use_stdout = true);
~OpenCLProgram();
void add_kernel(ustring name);
void load();
- bool is_loaded() { return loaded; }
- string get_log() { return log; }
+ bool is_loaded() const { return loaded; }
+ const string& get_log() const { return log; }
void report_error();
cl_kernel operator()();
@@ -266,8 +288,8 @@ public:
bool load_binary(const string& clbin, const string *debug_src = NULL);
bool save_binary(const string& clbin);
- void add_log(string msg, bool is_debug);
- void add_error(string msg);
+ void add_log(const string& msg, bool is_debug);
+ void add_error(const string& msg);
bool loaded;
cl_program program;
@@ -336,6 +358,7 @@ public:
size_t global_size_round_up(int group_size, int global_size);
void enqueue_kernel(cl_kernel kernel, size_t w, size_t h, size_t max_workgroup_size = -1);
void set_kernel_arg_mem(cl_kernel kernel, cl_uint *narg, const char *name);
+ void set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg);
void film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half);
void shader(DeviceTask& task);
@@ -390,8 +413,6 @@ protected:
bool denoising_construct_transform(DenoisingTask *task);
bool denoising_reconstruct(device_ptr color_ptr,
device_ptr color_variance_ptr,
- device_ptr guide_ptr,
- device_ptr guide_variance_ptr,
device_ptr output_ptr,
DenoisingTask *task);
bool denoising_combine_halves(device_ptr a_ptr,
@@ -519,6 +540,42 @@ protected:
virtual string build_options_for_base_program(
const DeviceRequestedFeatures& /*requested_features*/);
+
+private:
+ MemoryManager memory_manager;
+ friend class MemoryManager;
+
+ struct tex_info_t {
+ uint buffer, padding;
+ cl_ulong offset;
+ uint width, height, depth, options;
+ };
+ static_assert_align(tex_info_t, 16);
+
+ vector<tex_info_t> texture_descriptors;
+ device_memory texture_descriptors_buffer;
+
+ struct Texture {
+ Texture() {}
+ Texture(device_memory* mem,
+ InterpolationType interpolation,
+ ExtensionType extension)
+ : mem(mem),
+ interpolation(interpolation),
+ extension(extension) {
+ }
+ device_memory* mem;
+ InterpolationType interpolation;
+ ExtensionType extension;
+ };
+
+ typedef map<string, Texture> TexturesMap;
+ TexturesMap textures;
+
+ bool textures_need_update;
+
+protected:
+ void flush_texture_buffers();
};
Device *opencl_create_mega_device(DeviceInfo& info, Stats& stats, bool background);
diff --git a/intern/cycles/device/opencl/opencl_base.cpp b/intern/cycles/device/opencl/opencl_base.cpp
index 24b70e3446c..7bdf81462b8 100644
--- a/intern/cycles/device/opencl/opencl_base.cpp
+++ b/intern/cycles/device/opencl/opencl_base.cpp
@@ -20,6 +20,7 @@
#include "kernel/kernel_types.h"
+#include "util/util_algorithm.h"
#include "util/util_foreach.h"
#include "util/util_logging.h"
#include "util/util_md5.h"
@@ -28,6 +29,15 @@
CCL_NAMESPACE_BEGIN
+struct texture_slot_t {
+ texture_slot_t(const string& name, int slot)
+ : name(name),
+ slot(slot) {
+ }
+ string name;
+ int slot;
+};
+
bool OpenCLDeviceBase::opencl_error(cl_int err)
{
if(err != CL_SUCCESS) {
@@ -62,7 +72,7 @@ void OpenCLDeviceBase::opencl_assert_err(cl_int err, const char* where)
}
OpenCLDeviceBase::OpenCLDeviceBase(DeviceInfo& info, Stats &stats, bool background_)
-: Device(info, stats, background_)
+: Device(info, stats, background_), memory_manager(this)
{
cpPlatform = NULL;
cdDevice = NULL;
@@ -70,6 +80,7 @@ OpenCLDeviceBase::OpenCLDeviceBase(DeviceInfo& info, Stats &stats, bool backgrou
cqCommandQueue = NULL;
null_mem = 0;
device_initialized = false;
+ textures_need_update = true;
vector<OpenCLPlatformDevice> usable_devices;
OpenCLInfo::get_usable_devices(&usable_devices);
@@ -125,6 +136,12 @@ OpenCLDeviceBase::OpenCLDeviceBase(DeviceInfo& info, Stats &stats, bool backgrou
return;
}
+ /* Allocate this right away so that texture_descriptors_buffer is placed at offset 0 in the device memory buffers */
+ texture_descriptors.resize(1);
+ texture_descriptors_buffer.resize(1);
+ texture_descriptors_buffer.data_pointer = (device_ptr)&texture_descriptors[0];
+ memory_manager.alloc("texture_descriptors", texture_descriptors_buffer);
+
fprintf(stderr, "Device init success\n");
device_initialized = true;
}
@@ -133,6 +150,8 @@ OpenCLDeviceBase::~OpenCLDeviceBase()
{
task_pool.stop();
+ memory_manager.free();
+
if(null_mem)
clReleaseMemObject(CL_MEM_PTR(null_mem));
@@ -276,6 +295,25 @@ void OpenCLDeviceBase::mem_alloc(const char *name, device_memory& mem, MemoryTyp
size_t size = mem.memory_size();
+ /* check there is enough memory available for the allocation */
+ cl_ulong max_alloc_size = 0;
+ clGetDeviceInfo(cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_alloc_size, NULL);
+
+ if(DebugFlags().opencl.mem_limit) {
+ max_alloc_size = min(max_alloc_size,
+ cl_ulong(DebugFlags().opencl.mem_limit - stats.mem_used));
+ }
+
+ if(size > max_alloc_size) {
+ string error = "Scene too complex to fit in available memory.";
+ if(name != NULL) {
+ error += string_printf(" (allocating buffer %s failed.)", name);
+ }
+ set_error(error);
+
+ return;
+ }
+
cl_mem_flags mem_flag;
void *mem_ptr = NULL;
@@ -473,29 +511,35 @@ void OpenCLDeviceBase::const_copy_to(const char *name, void *host, size_t size)
void OpenCLDeviceBase::tex_alloc(const char *name,
device_memory& mem,
- InterpolationType /*interpolation*/,
- ExtensionType /*extension*/)
+ InterpolationType interpolation,
+ ExtensionType extension)
{
VLOG(1) << "Texture allocate: " << name << ", "
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
<< string_human_readable_size(mem.memory_size()) << ")";
- mem_alloc(NULL, mem, MEM_READ_ONLY);
- mem_copy_to(mem);
- assert(mem_map.find(name) == mem_map.end());
- mem_map.insert(MemMap::value_type(name, mem.device_pointer));
+
+ memory_manager.alloc(name, mem);
+ /* Set the pointer to non-null to keep code that inspects its value from thinking its unallocated. */
+ mem.device_pointer = 1;
+ textures[name] = Texture(&mem, interpolation, extension);
+ textures_need_update = true;
}
void OpenCLDeviceBase::tex_free(device_memory& mem)
{
if(mem.device_pointer) {
- foreach(const MemMap::value_type& value, mem_map) {
- if(value.second == mem.device_pointer) {
- mem_map.erase(value.first);
+ mem.device_pointer = 0;
+
+ if(memory_manager.free(mem)) {
+ textures_need_update = true;
+ }
+
+ foreach(TexturesMap::value_type& value, textures) {
+ if(value.second.mem == &mem) {
+ textures.erase(value.first);
break;
}
}
-
- mem_free(mem);
}
}
@@ -561,6 +605,98 @@ void OpenCLDeviceBase::set_kernel_arg_mem(cl_kernel kernel, cl_uint *narg, const
opencl_assert(clSetKernelArg(kernel, (*narg)++, sizeof(ptr), (void*)&ptr));
}
+void OpenCLDeviceBase::set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg)
+{
+ flush_texture_buffers();
+
+ memory_manager.set_kernel_arg_buffers(kernel, narg);
+}
+
+void OpenCLDeviceBase::flush_texture_buffers()
+{
+ if(!textures_need_update) {
+ return;
+ }
+ textures_need_update = false;
+
+ /* Setup slots for textures. */
+ int num_slots = 0;
+
+ vector<texture_slot_t> texture_slots;
+
+#define KERNEL_TEX(type, ttype, name) \
+ if(textures.find(#name) != textures.end()) { \
+ texture_slots.push_back(texture_slot_t(#name, num_slots)); \
+ } \
+ num_slots++;
+#include "kernel/kernel_textures.h"
+
+ int num_data_slots = num_slots;
+
+ foreach(TexturesMap::value_type& tex, textures) {
+ string name = tex.first;
+
+ if(string_startswith(name, "__tex_image")) {
+ int pos = name.rfind("_");
+ int id = atoi(name.data() + pos + 1);
+ texture_slots.push_back(texture_slot_t(name,
+ num_data_slots + id));
+ num_slots = max(num_slots, num_data_slots + id + 1);
+ }
+ }
+
+ /* Realloc texture descriptors buffer. */
+ memory_manager.free(texture_descriptors_buffer);
+
+ texture_descriptors.resize(num_slots);
+ texture_descriptors_buffer.resize(num_slots * sizeof(tex_info_t));
+ texture_descriptors_buffer.data_pointer = (device_ptr)&texture_descriptors[0];
+
+ memory_manager.alloc("texture_descriptors", texture_descriptors_buffer);
+
+ /* Fill in descriptors */
+ foreach(texture_slot_t& slot, texture_slots) {
+ Texture& tex = textures[slot.name];
+
+ tex_info_t& info = texture_descriptors[slot.slot];
+
+ MemoryManager::BufferDescriptor desc = memory_manager.get_descriptor(slot.name);
+
+ info.offset = desc.offset;
+ info.buffer = desc.device_buffer;
+
+ if(string_startswith(slot.name, "__tex_image")) {
+ info.width = tex.mem->data_width;
+ info.height = tex.mem->data_height;
+ info.depth = tex.mem->data_depth;
+
+ info.options = 0;
+
+ if(tex.interpolation == INTERPOLATION_CLOSEST) {
+ info.options |= (1 << 0);
+ }
+
+ switch(tex.extension) {
+ case EXTENSION_REPEAT:
+ info.options |= (1 << 1);
+ break;
+ case EXTENSION_EXTEND:
+ info.options |= (1 << 2);
+ break;
+ case EXTENSION_CLIP:
+ info.options |= (1 << 3);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /* Force write of descriptors. */
+ memory_manager.free(texture_descriptors_buffer);
+ memory_manager.alloc("texture_descriptors", texture_descriptors_buffer);
+}
+
void OpenCLDeviceBase::film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half)
{
/* cast arguments to cl types */
@@ -585,10 +721,7 @@ void OpenCLDeviceBase::film_convert(DeviceTask& task, device_ptr buffer, device_
d_rgba,
d_buffer);
-#define KERNEL_TEX(type, ttype, name) \
-set_kernel_arg_mem(ckFilmConvertKernel, &start_arg_index, #name);
-#include "kernel/kernel_textures.h"
-#undef KERNEL_TEX
+ set_kernel_arg_buffers(ckFilmConvertKernel, &start_arg_index);
start_arg_index += kernel_set_args(ckFilmConvertKernel,
start_arg_index,
@@ -693,8 +826,6 @@ bool OpenCLDeviceBase::denoising_construct_transform(DenoisingTask *task)
bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
device_ptr color_variance_ptr,
- device_ptr guide_ptr,
- device_ptr guide_variance_ptr,
device_ptr output_ptr,
DenoisingTask *task)
{
@@ -703,8 +834,6 @@ bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
cl_mem color_mem = CL_MEM_PTR(color_ptr);
cl_mem color_variance_mem = CL_MEM_PTR(color_variance_ptr);
- cl_mem guide_mem = CL_MEM_PTR(guide_ptr);
- cl_mem guide_variance_mem = CL_MEM_PTR(guide_variance_ptr);
cl_mem output_mem = CL_MEM_PTR(output_ptr);
cl_mem buffer_mem = CL_MEM_PTR(task->buffer.mem.device_pointer);
@@ -735,8 +864,8 @@ bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
kernel_set_args(ckNLMCalcDifference, 0,
dx, dy,
- guide_mem,
- guide_variance_mem,
+ color_mem,
+ color_variance_mem,
difference,
local_rect,
task->buffer.w,
@@ -775,8 +904,6 @@ bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
dx, dy,
blurDifference,
buffer_mem,
- color_mem,
- color_variance_mem,
transform_mem,
rank_mem,
XtWX_mem,
@@ -961,7 +1088,7 @@ void OpenCLDeviceBase::denoise(RenderTile &rtile, const DeviceTask &task)
denoising.functions.set_tiles = function_bind(&OpenCLDeviceBase::denoising_set_tiles, this, _1, &denoising);
denoising.functions.construct_transform = function_bind(&OpenCLDeviceBase::denoising_construct_transform, this, &denoising);
- denoising.functions.reconstruct = function_bind(&OpenCLDeviceBase::denoising_reconstruct, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.reconstruct = function_bind(&OpenCLDeviceBase::denoising_reconstruct, this, _1, _2, _3, &denoising);
denoising.functions.divide_shadow = function_bind(&OpenCLDeviceBase::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
denoising.functions.non_local_means = function_bind(&OpenCLDeviceBase::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
denoising.functions.combine_halves = function_bind(&OpenCLDeviceBase::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
@@ -1016,10 +1143,7 @@ void OpenCLDeviceBase::shader(DeviceTask& task)
d_output_luma);
}
-#define KERNEL_TEX(type, ttype, name) \
- set_kernel_arg_mem(kernel, &start_arg_index, #name);
-#include "kernel/kernel_textures.h"
-#undef KERNEL_TEX
+ set_kernel_arg_buffers(kernel, &start_arg_index);
start_arg_index += kernel_set_args(kernel,
start_arg_index,
@@ -1232,7 +1356,7 @@ void OpenCLDeviceBase::store_cached_kernel(
}
string OpenCLDeviceBase::build_options_for_base_program(
- const DeviceRequestedFeatures& /*requested_features*/)
+ const DeviceRequestedFeatures& requested_features)
{
/* TODO(sergey): By default we compile all features, meaning
* mega kernel is not getting feature-based optimizations.
@@ -1240,6 +1364,14 @@ string OpenCLDeviceBase::build_options_for_base_program(
* Ideally we need always compile kernel with as less features
* enabled as possible to keep performance at it's max.
*/
+
+ /* For now disable baking when not in use as this has major
+ * impact on kernel build times.
+ */
+ if(!requested_features.use_baking) {
+ return "-D__NO_BAKING__";
+ }
+
return "";
}
diff --git a/intern/cycles/device/opencl/opencl_mega.cpp b/intern/cycles/device/opencl/opencl_mega.cpp
index 06c15bcf401..ec47fdafa3d 100644
--- a/intern/cycles/device/opencl/opencl_mega.cpp
+++ b/intern/cycles/device/opencl/opencl_mega.cpp
@@ -82,10 +82,7 @@ public:
d_buffer,
d_rng_state);
-#define KERNEL_TEX(type, ttype, name) \
- set_kernel_arg_mem(ckPathTraceKernel, &start_arg_index, #name);
-#include "kernel/kernel_textures.h"
-#undef KERNEL_TEX
+ set_kernel_arg_buffers(ckPathTraceKernel, &start_arg_index);
start_arg_index += kernel_set_args(ckPathTraceKernel,
start_arg_index,
diff --git a/intern/cycles/device/opencl/opencl_split.cpp b/intern/cycles/device/opencl/opencl_split.cpp
index 76dcbd6fc9a..16a96213100 100644
--- a/intern/cycles/device/opencl/opencl_split.cpp
+++ b/intern/cycles/device/opencl/opencl_split.cpp
@@ -25,6 +25,7 @@
#include "device/device_split_kernel.h"
+#include "util/util_algorithm.h"
#include "util/util_logging.h"
#include "util/util_md5.h"
#include "util/util_path.h"
@@ -98,6 +99,8 @@ public:
void thread_run(DeviceTask *task)
{
+ flush_texture_buffers();
+
if(task->type == DeviceTask::FILM_CONVERT) {
film_convert(*task, task->buffer, task->rgba_byte, task->rgba_half);
}
@@ -112,10 +115,19 @@ public:
*/
typedef struct KernelGlobals {
ccl_constant KernelData *data;
+ ccl_global char *buffers[8];
+
+ typedef struct _tex_info_t {
+ uint buffer, padding;
+ uint64_t offset;
+ uint width, height, depth, options;
+ } _tex_info_t;
+
#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name;
+ _tex_info_t name;
#include "kernel/kernel_textures.h"
#undef KERNEL_TEX
+
SplitData split_data;
SplitParams split_param_data;
} KernelGlobals;
@@ -176,17 +188,58 @@ protected:
friend class OpenCLSplitKernelFunction;
};
+struct CachedSplitMemory {
+ int id;
+ device_memory *split_data;
+ device_memory *ray_state;
+ device_ptr *rng_state;
+ device_memory *queue_index;
+ device_memory *use_queues_flag;
+ device_memory *work_pools;
+ device_ptr *buffer;
+};
+
class OpenCLSplitKernelFunction : public SplitKernelFunction {
public:
OpenCLDeviceSplitKernel* device;
OpenCLDeviceBase::OpenCLProgram program;
+ CachedSplitMemory& cached_memory;
+ int cached_id;
- OpenCLSplitKernelFunction(OpenCLDeviceSplitKernel* device) : device(device) {}
- ~OpenCLSplitKernelFunction() { program.release(); }
+ OpenCLSplitKernelFunction(OpenCLDeviceSplitKernel* device, CachedSplitMemory& cached_memory) :
+ device(device), cached_memory(cached_memory), cached_id(cached_memory.id-1)
+ {
+ }
+
+ ~OpenCLSplitKernelFunction()
+ {
+ program.release();
+ }
virtual bool enqueue(const KernelDimensions& dim, device_memory& kg, device_memory& data)
{
- device->kernel_set_args(program(), 0, kg, data);
+ if(cached_id != cached_memory.id) {
+ cl_uint start_arg_index =
+ device->kernel_set_args(program(),
+ 0,
+ kg,
+ data,
+ *cached_memory.split_data,
+ *cached_memory.ray_state,
+ *cached_memory.rng_state);
+
+ device->set_kernel_arg_buffers(program(), &start_arg_index);
+
+ start_arg_index +=
+ device->kernel_set_args(program(),
+ start_arg_index,
+ *cached_memory.queue_index,
+ *cached_memory.use_queues_flag,
+ *cached_memory.work_pools,
+ *cached_memory.buffer);
+
+ cached_id = cached_memory.id;
+ }
device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
program(),
@@ -213,14 +266,15 @@ public:
class OpenCLSplitKernel : public DeviceSplitKernel {
OpenCLDeviceSplitKernel *device;
+ CachedSplitMemory cached_memory;
public:
explicit OpenCLSplitKernel(OpenCLDeviceSplitKernel *device) : DeviceSplitKernel(device), device(device) {
}
- virtual SplitKernelFunction* get_split_kernel_function(string kernel_name,
+ virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
const DeviceRequestedFeatures& requested_features)
{
- OpenCLSplitKernelFunction* kernel = new OpenCLSplitKernelFunction(device);
+ OpenCLSplitKernelFunction* kernel = new OpenCLSplitKernelFunction(device, cached_memory);
bool single_program = OpenCLInfo::use_single_program();
kernel->program =
@@ -305,11 +359,7 @@ public:
ray_state,
rtile.rng_state);
-/* TODO(sergey): Avoid map lookup here. */
-#define KERNEL_TEX(type, ttype, name) \
- device->set_kernel_arg_mem(device->program_data_init(), &start_arg_index, #name);
-#include "kernel/kernel_textures.h"
-#undef KERNEL_TEX
+ device->set_kernel_arg_buffers(device->program_data_init(), &start_arg_index);
start_arg_index +=
device->kernel_set_args(device->program_data_init(),
@@ -349,6 +399,15 @@ public:
return false;
}
+ cached_memory.split_data = &split_data;
+ cached_memory.ray_state = &ray_state;
+ cached_memory.rng_state = &rtile.rng_state;
+ cached_memory.queue_index = &queue_index;
+ cached_memory.use_queues_flag = &use_queues_flag;
+ cached_memory.work_pools = &work_pool_wgs;
+ cached_memory.buffer = &rtile.buffer;
+ cached_memory.id++;
+
return true;
}
@@ -368,12 +427,18 @@ public:
cl_ulong max_buffer_size;
clGetDeviceInfo(device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
+
+ if(DebugFlags().opencl.mem_limit) {
+ max_buffer_size = min(max_buffer_size,
+ cl_ulong(DebugFlags().opencl.mem_limit - device->stats.mem_used));
+ }
+
VLOG(1) << "Maximum device allocation size: "
<< string_human_readable_number(max_buffer_size) << " bytes. ("
<< string_human_readable_size(max_buffer_size) << ").";
size_t num_elements = max_elements_for_max_buffer_size(kg, data, max_buffer_size / 2);
- int2 global_size = make_int2(round_down((int)sqrt(num_elements), 64), (int)sqrt(num_elements));
+ int2 global_size = make_int2(max(round_down((int)sqrt(num_elements), 64), 64), (int)sqrt(num_elements));
VLOG(1) << "Global size: " << global_size << ".";
return global_size;
}
diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp
index 642c1bfa11c..7d5173a5f1d 100644
--- a/intern/cycles/device/opencl/opencl_util.cpp
+++ b/intern/cycles/device/opencl/opencl_util.cpp
@@ -241,9 +241,9 @@ string OpenCLCache::get_kernel_md5()
}
OpenCLDeviceBase::OpenCLProgram::OpenCLProgram(OpenCLDeviceBase *device,
- string program_name,
- string kernel_file,
- string kernel_build_options,
+ const string& program_name,
+ const string& kernel_file,
+ const string& kernel_build_options,
bool use_stdout)
: device(device),
program_name(program_name),
@@ -274,7 +274,7 @@ void OpenCLDeviceBase::OpenCLProgram::release()
}
}
-void OpenCLDeviceBase::OpenCLProgram::add_log(string msg, bool debug)
+void OpenCLDeviceBase::OpenCLProgram::add_log(const string& msg, bool debug)
{
if(!use_stdout) {
log += msg + "\n";
@@ -288,7 +288,7 @@ void OpenCLDeviceBase::OpenCLProgram::add_log(string msg, bool debug)
}
}
-void OpenCLDeviceBase::OpenCLProgram::add_error(string msg)
+void OpenCLDeviceBase::OpenCLProgram::add_error(const string& msg)
{
if(use_stdout) {
fprintf(stderr, "%s\n", msg.c_str());
@@ -608,6 +608,14 @@ bool OpenCLInfo::device_supported(const string& platform_name,
if(!get_device_name(device_id, &device_name)) {
return false;
}
+
+ int driver_major = 0;
+ int driver_minor = 0;
+ if(!get_driver_version(device_id, &driver_major, &driver_minor)) {
+ return false;
+ }
+ VLOG(3) << "OpenCL driver version " << driver_major << "." << driver_minor;
+
/* It is possible tyo have Iris GPU on AMD/Apple OpenCL framework
* (aka, it will not be on Intel framework). This isn't supported
* and needs an explicit blacklist.
@@ -618,6 +626,21 @@ bool OpenCLInfo::device_supported(const string& platform_name,
if(platform_name == "AMD Accelerated Parallel Processing" &&
device_type == CL_DEVICE_TYPE_GPU)
{
+ if(driver_major < 2236) {
+ VLOG(1) << "AMD driver version " << driver_major << "." << driver_minor << " not supported.";
+ return false;
+ }
+ const char *blacklist[] = {
+ /* GCN 1 */
+ "Tahiti", "Pitcairn", "Capeverde", "Oland",
+ NULL
+ };
+ for(int i = 0; blacklist[i] != NULL; i++) {
+ if(device_name == blacklist[i]) {
+ VLOG(1) << "AMD device " << device_name << " not supported";
+ return false;
+ }
+ }
return true;
}
if(platform_name == "Apple" && device_type == CL_DEVICE_TYPE_GPU) {
@@ -684,7 +707,7 @@ bool OpenCLInfo::device_version_check(cl_device_id device,
return true;
}
-string OpenCLInfo::get_hardware_id(string platform_name, cl_device_id device_id)
+string OpenCLInfo::get_hardware_id(const string& platform_name, cl_device_id device_id)
{
if(platform_name == "AMD Accelerated Parallel Processing" || platform_name == "Apple") {
/* Use cl_amd_device_topology extension. */
@@ -1063,7 +1086,7 @@ string OpenCLInfo::get_readable_device_name(cl_device_id device_id)
CL_DEVICE_BOARD_NAME_AMD,
sizeof(board_name),
&board_name,
- &length) == CL_SUCCESS)
+ &length) == CL_SUCCESS)
{
if(length != 0 && board_name[0] != '\0') {
return board_name;
@@ -1073,6 +1096,34 @@ string OpenCLInfo::get_readable_device_name(cl_device_id device_id)
return get_device_name(device_id);
}
+bool OpenCLInfo::get_driver_version(cl_device_id device_id,
+ int *major,
+ int *minor,
+ cl_int* error)
+{
+ char buffer[1024];
+ cl_int err;
+ if((err = clGetDeviceInfo(device_id,
+ CL_DRIVER_VERSION,
+ sizeof(buffer),
+ &buffer,
+ NULL)) != CL_SUCCESS)
+ {
+ if(error != NULL) {
+ *error = err;
+ }
+ return false;
+ }
+ if(error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ if(sscanf(buffer, "%d.%d", major, minor) < 2) {
+ VLOG(1) << string_printf("OpenCL: failed to parse driver version string (%s).", buffer);
+ return false;
+ }
+ return true;
+}
+
int OpenCLInfo::mem_address_alignment(cl_device_id device_id)
{
int base_align_bits;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index bef869f34b4..b4ca16bdb48 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -45,6 +45,7 @@ set(SRC
kernels/opencl/kernel_direct_lighting.cl
kernels/opencl/kernel_shadow_blocked_ao.cl
kernels/opencl/kernel_shadow_blocked_dl.cl
+ kernels/opencl/kernel_enqueue_inactive.cl
kernels/opencl/kernel_next_iteration_setup.cl
kernels/opencl/kernel_indirect_subsurface.cl
kernels/opencl/kernel_buffer_update.cl
@@ -78,7 +79,6 @@ set(SRC_HEADERS
kernel_compat_cpu.h
kernel_compat_cuda.h
kernel_compat_opencl.h
- kernel_debug.h
kernel_differential.h
kernel_emission.h
kernel_film.h
@@ -121,6 +121,10 @@ set(SRC_KERNELS_CUDA_HEADERS
kernels/cuda/kernel_config.h
)
+set(SRC_KERNELS_OPENCL_HEADERS
+ kernels/opencl/kernel_split_function.h
+)
+
set(SRC_CLOSURE_HEADERS
closure/alloc.h
closure/bsdf.h
@@ -197,6 +201,7 @@ set(SRC_GEOM_HEADERS
geom/geom.h
geom/geom_attribute.h
geom/geom_curve.h
+ geom/geom_curve_intersect.h
geom/geom_motion_curve.h
geom/geom_motion_triangle.h
geom/geom_motion_triangle_intersect.h
@@ -228,6 +233,7 @@ set(SRC_FILTER_HEADERS
set(SRC_UTIL_HEADERS
../util/util_atomic.h
../util/util_color.h
+ ../util/util_defines.h
../util/util_half.h
../util/util_hash.h
../util/util_math.h
@@ -278,6 +284,7 @@ set(SRC_SPLIT_HEADERS
split/kernel_data_init.h
split/kernel_direct_lighting.h
split/kernel_do_volume.h
+ split/kernel_enqueue_inactive.h
split/kernel_holdout_emission_blurring_pathtermination_ao.h
split/kernel_indirect_background.h
split/kernel_indirect_subsurface.h
@@ -450,6 +457,7 @@ add_library(cycles_kernel
${SRC_HEADERS}
${SRC_KERNELS_CPU_HEADERS}
${SRC_KERNELS_CUDA_HEADERS}
+ ${SRC_KERNELS_OPENCL_HEADERS}
${SRC_BVH_HEADERS}
${SRC_CLOSURE_HEADERS}
${SRC_FILTER_HEADERS}
@@ -490,9 +498,11 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_subsurface_sc
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_direct_lighting.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocked_ao.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocked_dl.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_enqueue_inactive.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_next_iteration_setup.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_indirect_subsurface.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_buffer_update.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_split_function.h" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/filter.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel_split.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index 85741016b25..cf0c8542d69 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -233,7 +233,7 @@ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
const Ray *ray,
Intersection *isect,
- int skip_object,
+ uint visibility,
uint max_hits,
uint *num_hits)
{
@@ -244,7 +244,7 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
return bvh_intersect_shadow_all_hair_motion(kg,
ray,
isect,
- skip_object,
+ visibility,
max_hits,
num_hits);
}
@@ -253,7 +253,7 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
return bvh_intersect_shadow_all_motion(kg,
ray,
isect,
- skip_object,
+ visibility,
max_hits,
num_hits);
}
@@ -264,7 +264,7 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
return bvh_intersect_shadow_all_hair(kg,
ray,
isect,
- skip_object,
+ visibility,
max_hits,
num_hits);
}
@@ -275,7 +275,7 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
return bvh_intersect_shadow_all_instancing(kg,
ray,
isect,
- skip_object,
+ visibility,
max_hits,
num_hits);
}
@@ -284,7 +284,7 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
return bvh_intersect_shadow_all(kg,
ray,
isect,
- skip_object,
+ visibility,
max_hits,
num_hits);
}
diff --git a/intern/cycles/kernel/bvh/bvh_nodes.h b/intern/cycles/kernel/bvh/bvh_nodes.h
index 74a9ebf14e4..6c33dad5426 100644
--- a/intern/cycles/kernel/bvh/bvh_nodes.h
+++ b/intern/cycles/kernel/bvh/bvh_nodes.h
@@ -52,8 +52,8 @@ ccl_device_forceinline int bvh_aligned_node_intersect(KernelGlobals *kg,
float c0hiy = (node1.z - P.y) * idir.y;
float c0loz = (node2.x - P.z) * idir.z;
float c0hiz = (node2.z - P.z) * idir.z;
- float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
- float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
+ float c0min = max4(0.0f, min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz));
+ float c0max = min4(t, max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz));
float c1lox = (node0.y - P.x) * idir.x;
float c1hix = (node0.w - P.x) * idir.x;
@@ -61,8 +61,8 @@ ccl_device_forceinline int bvh_aligned_node_intersect(KernelGlobals *kg,
float c1hiy = (node1.w - P.y) * idir.y;
float c1loz = (node2.y - P.z) * idir.z;
float c1hiz = (node2.w - P.z) * idir.z;
- float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
- float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
+ float c1min = max4(0.0f, min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz));
+ float c1max = min4(t, max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz));
dist[0] = c0min;
dist[1] = c1min;
@@ -101,8 +101,8 @@ ccl_device_forceinline int bvh_aligned_node_intersect_robust(KernelGlobals *kg,
float c0hiy = (node1.z - P.y) * idir.y;
float c0loz = (node2.x - P.z) * idir.z;
float c0hiz = (node2.z - P.z) * idir.z;
- float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
- float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
+ float c0min = max4(0.0f, min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz));
+ float c0max = min4(t, max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz));
float c1lox = (node0.y - P.x) * idir.x;
float c1hix = (node0.w - P.x) * idir.x;
@@ -110,8 +110,8 @@ ccl_device_forceinline int bvh_aligned_node_intersect_robust(KernelGlobals *kg,
float c1hiy = (node1.w - P.y) * idir.y;
float c1loz = (node2.y - P.z) * idir.z;
float c1hiz = (node2.w - P.z) * idir.z;
- float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
- float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
+ float c1min = max4(0.0f, min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz));
+ float c1max = min4(t, max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz));
if(difl != 0.0f) {
float hdiff = 1.0f + difl;
@@ -483,8 +483,8 @@ ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
ssef tfar_y = max(lower_y, upper_y);
ssef tfar_z = max(lower_z, upper_z);
- const ssef tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
- const ssef tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
sseb vmask = tnear <= tfar;
dist[0] = tnear.f[0];
dist[1] = tnear.f[1];
@@ -545,8 +545,8 @@ ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg
ssef tfar_y = max(lower_y, upper_y);
ssef tfar_z = max(lower_z, upper_z);
- const ssef tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
- const ssef tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
sseb vmask;
if(difl != 0.0f) {
const float round_down = 1.0f - difl;
@@ -615,7 +615,7 @@ ccl_device_forceinline int bvh_node_intersect_robust(KernelGlobals *kg,
const float3& P,
const float3& dir,
const ssef& isect_near,
- const ssef& isect_far,
+ const ssef& isect_far,
const ssef& tsplat,
const ssef Psplat[3],
const ssef idirsplat[3],
diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h
index 267e098f912..a6a4353562c 100644
--- a/intern/cycles/kernel/bvh/bvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h
@@ -45,7 +45,7 @@ ccl_device_inline
bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
- const int skip_object,
+ const uint visibility,
const uint max_hits,
uint *num_hits)
{
@@ -119,7 +119,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
idir,
isect_t,
node_addr,
- PATH_RAY_SHADOW,
+ visibility,
dist);
#else // __KERNEL_SSE2__
traverse_mask = NODE_INTERSECT(kg,
@@ -134,7 +134,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
idirsplat,
shufflexyz,
node_addr,
- PATH_RAY_SHADOW,
+ visibility,
dist);
#endif // __KERNEL_SSE2__
@@ -186,17 +186,6 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* primitive intersection */
while(prim_addr < prim_addr2) {
kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
-
-#ifdef __SHADOW_TRICKS__
- uint tri_object = (object == OBJECT_NONE)
- ? kernel_tex_fetch(__prim_object, prim_addr)
- : object;
- if(tri_object == skip_object) {
- ++prim_addr;
- continue;
- }
-#endif
-
bool hit;
/* todo: specialized intersect functions which don't fill in
@@ -209,7 +198,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
isect_array,
P,
dir,
- PATH_RAY_SHADOW,
+ visibility,
object,
prim_addr);
break;
@@ -221,7 +210,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
P,
dir,
ray->time,
- PATH_RAY_SHADOW,
+ visibility,
object,
prim_addr);
break;
@@ -232,30 +221,30 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
case PRIMITIVE_MOTION_CURVE: {
const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = bvh_cardinal_curve_intersect(kg,
- isect_array,
- P,
- dir,
- PATH_RAY_SHADOW,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
+ hit = cardinal_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0, 0);
}
else {
- hit = bvh_curve_intersect(kg,
- isect_array,
- P,
- dir,
- PATH_RAY_SHADOW,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
+ hit = curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0, 0);
}
break;
}
@@ -402,7 +391,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
- const int skip_object,
+ const uint visibility,
const uint max_hits,
uint *num_hits)
{
@@ -411,7 +400,7 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
ray,
isect_array,
- skip_object,
+ visibility,
max_hits,
num_hits);
}
@@ -422,7 +411,7 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
return BVH_FUNCTION_FULL_NAME(BVH)(kg,
ray,
isect_array,
- skip_object,
+ visibility,
max_hits,
num_hits);
}
diff --git a/intern/cycles/kernel/bvh/bvh_traversal.h b/intern/cycles/kernel/bvh/bvh_traversal.h
index c58d3b0316c..ae8f54821f2 100644
--- a/intern/cycles/kernel/bvh/bvh_traversal.h
+++ b/intern/cycles/kernel/bvh/bvh_traversal.h
@@ -244,14 +244,14 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
{
/* shadow ray early termination */
#if defined(__KERNEL_SSE2__)
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ if(visibility & PATH_RAY_SHADOW_OPAQUE)
return true;
tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
tfar = ssef(isect->t);
# endif
#else
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ if(visibility & PATH_RAY_SHADOW_OPAQUE)
return true;
#endif
}
@@ -274,14 +274,14 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
{
/* shadow ray early termination */
# if defined(__KERNEL_SSE2__)
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ if(visibility & PATH_RAY_SHADOW_OPAQUE)
return true;
tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
tfar = ssef(isect->t);
# endif
# else
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ if(visibility & PATH_RAY_SHADOW_OPAQUE)
return true;
# endif
}
@@ -298,44 +298,44 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
bool hit;
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = bvh_cardinal_curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
+ hit = cardinal_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
}
else {
- hit = bvh_curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
+ hit = curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
}
if(hit) {
/* shadow ray early termination */
# if defined(__KERNEL_SSE2__)
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ if(visibility & PATH_RAY_SHADOW_OPAQUE)
return true;
tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
tfar = ssef(isect->t);
# endif
# else
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ if(visibility & PATH_RAY_SHADOW_OPAQUE)
return true;
# endif
}
diff --git a/intern/cycles/kernel/bvh/qbvh_nodes.h b/intern/cycles/kernel/bvh/qbvh_nodes.h
index 6d22f0b0d6a..3036efd4198 100644
--- a/intern/cycles/kernel/bvh/qbvh_nodes.h
+++ b/intern/cycles/kernel/bvh/qbvh_nodes.h
@@ -126,8 +126,8 @@ ccl_device_inline int qbvh_aligned_node_intersect(KernelGlobals *ccl_restrict kg
const sseb vmask = cast(tnear) > cast(tfar);
int mask = (int)movemask(vmask)^0xf;
#else
- const ssef tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
- const ssef tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
const sseb vmask = tnear <= tfar;
int mask = (int)movemask(vmask);
#endif
@@ -174,8 +174,8 @@ ccl_device_inline int qbvh_aligned_node_intersect_robust(
const float round_down = 1.0f - difl;
const float round_up = 1.0f + difl;
- const ssef tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
- const ssef tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
const sseb vmask = round_down*tnear <= round_up*tfar;
*dist = tnear;
return (int)movemask(vmask);
diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
index ce474438f2c..522213f30ca 100644
--- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
@@ -33,7 +33,7 @@
ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
- const int skip_object,
+ const uint visibility,
const uint max_hits,
uint *num_hits)
{
@@ -107,7 +107,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(false
#ifdef __VISIBILITY_FLAG__
- || ((__float_as_uint(inodes.x) & PATH_RAY_SHADOW) == 0)
+ || ((__float_as_uint(inodes.x) & visibility) == 0)
#endif
#if BVH_FEATURE(BVH_MOTION)
|| UNLIKELY(ray->time < inodes.y)
@@ -244,7 +244,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(node_addr < 0) {
float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(leaf.z) & PATH_RAY_SHADOW) == 0) {
+ if((__float_as_uint(leaf.z) & visibility) == 0) {
/* Pop. */
node_addr = traversal_stack[stack_ptr].addr;
--stack_ptr;
@@ -268,17 +268,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Primitive intersection. */
while(prim_addr < prim_addr2) {
kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
-
-#ifdef __SHADOW_TRICKS__
- uint tri_object = (object == OBJECT_NONE)
- ? kernel_tex_fetch(__prim_object, prim_addr)
- : object;
- if(tri_object == skip_object) {
- ++prim_addr;
- continue;
- }
-#endif
-
bool hit;
/* todo: specialized intersect functions which don't fill in
@@ -291,7 +280,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
isect_array,
P,
dir,
- PATH_RAY_SHADOW,
+ visibility,
object,
prim_addr);
break;
@@ -303,7 +292,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
P,
dir,
ray->time,
- PATH_RAY_SHADOW,
+ visibility,
object,
prim_addr);
break;
@@ -314,30 +303,30 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
case PRIMITIVE_MOTION_CURVE: {
const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = bvh_cardinal_curve_intersect(kg,
- isect_array,
- P,
- dir,
- PATH_RAY_SHADOW,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
+ hit = cardinal_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0, 0);
}
else {
- hit = bvh_curve_intersect(kg,
- isect_array,
- P,
- dir,
- PATH_RAY_SHADOW,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
+ hit = curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0, 0);
}
break;
}
diff --git a/intern/cycles/kernel/bvh/qbvh_traversal.h b/intern/cycles/kernel/bvh/qbvh_traversal.h
index fca75a1d416..335a4afd47a 100644
--- a/intern/cycles/kernel/bvh/qbvh_traversal.h
+++ b/intern/cycles/kernel/bvh/qbvh_traversal.h
@@ -340,7 +340,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
prim_addr)) {
tfar = ssef(isect->t);
/* Shadow ray early termination. */
- if(visibility == PATH_RAY_SHADOW_OPAQUE) {
+ if(visibility & PATH_RAY_SHADOW_OPAQUE) {
return true;
}
}
@@ -362,7 +362,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
prim_addr)) {
tfar = ssef(isect->t);
/* Shadow ray early termination. */
- if(visibility == PATH_RAY_SHADOW_OPAQUE) {
+ if(visibility & PATH_RAY_SHADOW_OPAQUE) {
return true;
}
}
@@ -379,37 +379,37 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
bool hit;
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = bvh_cardinal_curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
+ hit = cardinal_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
}
else {
- hit = bvh_curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
+ hit = curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
}
if(hit) {
tfar = ssef(isect->t);
/* Shadow ray early termination. */
- if(visibility == PATH_RAY_SHADOW_OPAQUE) {
+ if(visibility & PATH_RAY_SHADOW_OPAQUE) {
return true;
}
}
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index a04c157dc40..86a00d2124d 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -423,6 +423,11 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
return bsdf_hair_merge(a, b);
+#ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ return bsdf_principled_diffuse_merge(a, b);
+#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
return volume_henyey_greenstein_merge(a, b);
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 30cc8b90330..b12e248f0a3 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -288,12 +288,16 @@ ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
+ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
+
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
@@ -302,12 +306,16 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf)
+ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F;
+
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
@@ -343,12 +351,16 @@ ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf)
+ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
+
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = saturate(bsdf->alpha_y);
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
index b07b515c405..2f2c35d5d1f 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
@@ -40,20 +40,20 @@ ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
}
/* Sample slope distribution (based on page 14 of the supplemental implementation). */
-ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float2 randU)
+ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float randx, const float randy)
{
if(cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
- const float r = sqrtf(randU.x / max(1.0f - randU.x, 1e-7f));
- const float phi = M_2PI_F * randU.y;
+ const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
+ const float phi = M_2PI_F * randy;
return make_float2(r*cosf(phi), r*sinf(phi));
}
- const float sinI = sqrtf(1.0f - cosI*cosI);
+ const float sinI = safe_sqrtf(1.0f - cosI*cosI);
const float tanI = sinI/cosI;
const float projA = 0.5f * (cosI + 1.0f);
if(projA < 0.0001f)
return make_float2(0.0f, 0.0f);
- const float A = 2.0f*randU.x*projA / cosI - 1.0f;
+ const float A = 2.0f*randx*projA / cosI - 1.0f;
float tmp = A*A-1.0f;
if(fabsf(tmp) < 1e-7f)
return make_float2(0.0f, 0.0f);
@@ -64,24 +64,24 @@ ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float2 ran
const float slopeX = (A < 0.0f || slopeX2 > 1.0f/tanI)? (tanI*tmp - D) : slopeX2;
float U2;
- if(randU.y >= 0.5f)
- U2 = 2.0f*(randU.y - 0.5f);
+ if(randy >= 0.5f)
+ U2 = 2.0f*(randy - 0.5f);
else
- U2 = 2.0f*(0.5f - randU.y);
+ U2 = 2.0f*(0.5f - randy);
const float z = (U2*(U2*(U2*0.27385f-0.73369f)+0.46341f)) / (U2*(U2*(U2*0.093073f+0.309420f)-1.0f)+0.597999f);
const float slopeY = z * sqrtf(1.0f + slopeX*slopeX);
- if(randU.y >= 0.5f)
+ if(randy >= 0.5f)
return make_float2(slopeX, slopeY);
else
return make_float2(slopeX, -slopeY);
}
/* Visible normal sampling for the GGX distribution (based on page 7 of the supplemental implementation). */
-ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float2 randU)
+ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float randx, const float randy)
{
const float3 wi_11 = normalize(make_float3(alpha.x*wi.x, alpha.y*wi.y, wi.z));
- const float2 slope_11 = mf_sampleP22_11(wi_11.z, randU);
+ const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
const float slope_x = alpha.x*(cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
@@ -245,35 +245,69 @@ ccl_device_forceinline float mf_ggx_albedo(float r)
return saturate(albedo);
}
+ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior)
+{
+ if(ior < 1.0f) {
+ ior = 1.0f/ior;
+ }
+ a = saturate(a);
+ ior = clamp(ior, 1.0f, 3.0f);
+ float I_1 = 0.0476898f*expf(-0.978352f*(ior-0.65657f)*(ior-0.65657f)) - 0.033756f*ior + 0.993261f;
+ float R_1 = (((0.116991f*a - 0.270369f)*a + 0.0501366f)*a - 0.00411511f)*a + 1.00008f;
+ float I_2 = (((-2.08704f*ior + 26.3298f)*ior - 127.906f)*ior + 292.958f)*ior - 287.946f + 199.803f/(ior*ior) - 101.668f/(ior*ior*ior);
+ float R_2 = ((((5.3725f*a -24.9307f)*a + 22.7437f)*a - 3.40751f)*a + 0.0986325f)*a + 0.00493504f;
+
+ return saturate(1.0f + I_2*R_2*0.0019127f - (1.0f - I_1)*(1.0f - R_1)*9.3205f);
+}
+
ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
{
float D = D_ggx(normalize(wi+wo), alpha);
float lambda = mf_lambda(wi, make_float2(alpha, alpha));
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
+
+ float multiscatter = wo.z * M_1_PI_F;
+
float albedo = mf_ggx_albedo(alpha);
- return 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f) + (1.0f - albedo) * wo.z;
+ return albedo*singlescatter + (1.0f - albedo)*multiscatter;
}
ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
{
- return 0.25f * D_ggx_aniso(normalize(wi+wo), alpha) / ((1.0f + mf_lambda(wi, alpha)) * wi.z) + (1.0f - mf_ggx_albedo(sqrtf(alpha.x*alpha.y))) * wo.z;
+ float D = D_ggx_aniso(normalize(wi+wo), alpha);
+ float lambda = mf_lambda(wi, alpha);
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
+
+ float multiscatter = wo.z * M_1_PI_F;
+
+ float albedo = mf_ggx_albedo(sqrtf(alpha.x*alpha.y));
+ return albedo*singlescatter + (1.0f - albedo)*multiscatter;
}
ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, const float alpha, const float eta)
{
- float3 wh;
- float fresnel;
- if(wi.z*wo.z > 0.0f) {
- wh = normalize(wi + wo);
- fresnel = fresnel_dielectric_cos(dot(wi, wh), eta);
- }
- else {
- wh = normalize(wi + wo*eta);
- fresnel = 1.0f - fresnel_dielectric_cos(dot(wi, wh), eta);
- }
+ bool reflective = (wi.z*wo.z > 0.0f);
+
+ float wh_len;
+ float3 wh = normalize_len(wi + (reflective? wo : (wo*eta)), &wh_len);
if(wh.z < 0.0f)
wh = -wh;
float3 r_wi = (wi.z < 0.0f)? -wi: wi;
- return fresnel * max(0.0f, dot(r_wi, wh)) * D_ggx(wh, alpha) / ((1.0f + mf_lambda(r_wi, make_float2(alpha, alpha))) * r_wi.z) + fabsf(wo.z);
+ float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
+ float D = D_ggx(wh, alpha);
+ float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
+
+ float multiscatter = fabsf(wo.z * M_1_PI_F);
+ if(reflective) {
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
+ float albedo = mf_ggx_albedo(alpha);
+ return fresnel * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
+ }
+ else {
+ float singlescatter = fabsf(dot(r_wi, wh)*dot(wo, wh) * D * eta*eta / max((1.0f + lambda) * r_wi.z * wh_len*wh_len, 1e-7f));
+ float albedo = mf_ggx_transmission_albedo(alpha, eta);
+ return (1.0f - fresnel) * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
+ }
}
/* === Actual random walk implementations, one version of mf_eval and mf_sample per phase function. === */
@@ -326,13 +360,17 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
-ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf)
+ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
if(is_zero(bsdf->T))
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
+
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
@@ -345,12 +383,16 @@ ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
-ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
+ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
bsdf->alpha_y = bsdf->alpha_x;
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
+
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
@@ -432,6 +474,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
*eval *= *pdf;
*omega_in = X*localO.x + Y*localO.y + Z*localO.z;
+
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
*domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
@@ -455,7 +498,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
}
-ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf)
+ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
bsdf->alpha_y = bsdf->alpha_x;
@@ -469,6 +512,10 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsd
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
+
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
}
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
index 2eb2457c9e5..e73915dbda7 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
@@ -100,11 +100,14 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
bool outside = true;
for(int order = 0; order < 10; order++) {
- /* Sample microfacet height and normal */
- if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float_addrspace(lcg_state)))
+ /* Sample microfacet height. */
+ float height_rand = lcg_step_float_addrspace(lcg_state);
+ if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
break;
- float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float_addrspace(lcg_state),
- lcg_step_float_addrspace(lcg_state)));
+ /* Sample microfacet normal. */
+ float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
+ float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
+ float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
#ifdef MF_MULTI_GLASS
if(order == 0 && use_fresnel) {
@@ -136,7 +139,8 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
#ifdef MF_MULTI_GLASS
bool next_outside;
float3 wi_prev = -wr;
- wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
+ float phase_rand = lcg_step_float_addrspace(lcg_state);
+ wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
if(!next_outside) {
outside = !outside;
wr = -wr;
@@ -204,14 +208,16 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(
int order;
for(order = 0; order < 10; order++) {
/* Sample microfacet height. */
- if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float_addrspace(lcg_state))) {
+ float height_rand = lcg_step_float_addrspace(lcg_state);
+ if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
/* The random walk has left the surface. */
*wo = outside? wr: -wr;
return throughput;
}
/* Sample microfacet normal. */
- float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float_addrspace(lcg_state),
- lcg_step_float_addrspace(lcg_state)));
+ float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
+ float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
+ float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
/* First-bounce color is already accounted for in mix weight. */
if(!use_fresnel && order > 0)
@@ -221,7 +227,8 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(
#ifdef MF_MULTI_GLASS
bool next_outside;
float3 wi_prev = -wr;
- wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
+ float phase_rand = lcg_step_float_addrspace(lcg_state);
+ wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
if(!next_outside) {
hr = -hr;
wr = -wr;
diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
index 215c32e1ffb..f8ca64293b0 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
@@ -58,6 +58,14 @@ ccl_device int bsdf_principled_diffuse_setup(PrincipledDiffuseBsdf *bsdf)
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
+ccl_device bool bsdf_principled_diffuse_merge(const ShaderClosure *a, const ShaderClosure *b)
+{
+ const PrincipledDiffuseBsdf *bsdf_a = (const PrincipledDiffuseBsdf*)a;
+ const PrincipledDiffuseBsdf *bsdf_b = (const PrincipledDiffuseBsdf*)b;
+
+ return (isequal_float3(bsdf_a->N, bsdf_b->N) && bsdf_a->roughness == bsdf_b->roughness);
+}
+
ccl_device float3 bsdf_principled_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I,
const float3 omega_in, float *pdf)
{
diff --git a/intern/cycles/kernel/filter/filter_features.h b/intern/cycles/kernel/filter/filter_features.h
index 53d703de143..6226ed2c2ef 100644
--- a/intern/cycles/kernel/filter/filter_features.h
+++ b/intern/cycles/kernel/filter/filter_features.h
@@ -78,16 +78,10 @@ ccl_device_inline void filter_calculate_scale(float *scale)
scale[3] = scale[4] = scale[5] = 1.0f/max(sqrtf(scale[3]), 0.01f);
}
-ccl_device_inline float3 filter_get_pixel_color(const ccl_global float *ccl_restrict buffer,
- int pass_stride)
+ccl_device_inline float3 filter_get_color(const ccl_global float *ccl_restrict buffer,
+ int pass_stride)
{
- return make_float3(ccl_get_feature(buffer, 0), ccl_get_feature(buffer, 1), ccl_get_feature(buffer, 2));
-}
-
-ccl_device_inline float filter_get_pixel_variance(const ccl_global float *ccl_restrict buffer,
- int pass_stride)
-{
- return average(make_float3(ccl_get_feature(buffer, 0), ccl_get_feature(buffer, 1), ccl_get_feature(buffer, 2)));
+ return make_float3(ccl_get_feature(buffer, 8), ccl_get_feature(buffer, 9), ccl_get_feature(buffer, 10));
}
ccl_device_inline void design_row_add(float *design_row,
diff --git a/intern/cycles/kernel/filter/filter_features_sse.h b/intern/cycles/kernel/filter/filter_features_sse.h
index 3185330994c..3ddd8712266 100644
--- a/intern/cycles/kernel/filter/filter_features_sse.h
+++ b/intern/cycles/kernel/filter/filter_features_sse.h
@@ -16,7 +16,7 @@
CCL_NAMESPACE_BEGIN
-#define ccl_get_feature_sse(pass) _mm_loadu_ps(buffer + (pass)*pass_stride)
+#define ccl_get_feature_sse(pass) load_float4(buffer + (pass)*pass_stride)
/* Loop over the pixels in the range [low.x, high.x) x [low.y, high.y), 4 at a time.
* pixel_buffer always points to the first of the 4 current pixel in the first pass.
@@ -24,25 +24,25 @@ CCL_NAMESPACE_BEGIN
#define FOR_PIXEL_WINDOW_SSE pixel_buffer = buffer + (low.y - rect.y)*buffer_w + (low.x - rect.x); \
for(pixel.y = low.y; pixel.y < high.y; pixel.y++) { \
- __m128 y4 = _mm_set1_ps(pixel.y); \
+ float4 y4 = make_float4(pixel.y); \
for(pixel.x = low.x; pixel.x < high.x; pixel.x += 4, pixel_buffer += 4) { \
- __m128 x4 = _mm_add_ps(_mm_set1_ps(pixel.x), _mm_set_ps(3.0f, 2.0f, 1.0f, 0.0f)); \
- __m128 active_pixels = _mm_cmplt_ps(x4, _mm_set1_ps(high.x));
+ float4 x4 = make_float4(pixel.x) + make_float4(0.0f, 1.0f, 2.0f, 3.0f); \
+ int4 active_pixels = x4 < make_float4(high.x);
#define END_FOR_PIXEL_WINDOW_SSE } \
pixel_buffer += buffer_w - (pixel.x - low.x); \
}
-ccl_device_inline void filter_get_features_sse(__m128 x, __m128 y,
- __m128 active_pixels,
+ccl_device_inline void filter_get_features_sse(float4 x, float4 y,
+ int4 active_pixels,
const float *ccl_restrict buffer,
- __m128 *features,
- const __m128 *ccl_restrict mean,
+ float4 *features,
+ const float4 *ccl_restrict mean,
int pass_stride)
{
features[0] = x;
features[1] = y;
- features[2] = _mm_fabs_ps(ccl_get_feature_sse(0));
+ features[2] = fabs(ccl_get_feature_sse(0));
features[3] = ccl_get_feature_sse(1);
features[4] = ccl_get_feature_sse(2);
features[5] = ccl_get_feature_sse(3);
@@ -52,53 +52,41 @@ ccl_device_inline void filter_get_features_sse(__m128 x, __m128 y,
features[9] = ccl_get_feature_sse(7);
if(mean) {
for(int i = 0; i < DENOISE_FEATURES; i++)
- features[i] = _mm_sub_ps(features[i], mean[i]);
+ features[i] = features[i] - mean[i];
}
for(int i = 0; i < DENOISE_FEATURES; i++)
- features[i] = _mm_mask_ps(features[i], active_pixels);
+ features[i] = mask(active_pixels, features[i]);
}
-ccl_device_inline void filter_get_feature_scales_sse(__m128 x, __m128 y,
- __m128 active_pixels,
+ccl_device_inline void filter_get_feature_scales_sse(float4 x, float4 y,
+ int4 active_pixels,
const float *ccl_restrict buffer,
- __m128 *scales,
- const __m128 *ccl_restrict mean,
+ float4 *scales,
+ const float4 *ccl_restrict mean,
int pass_stride)
{
- scales[0] = _mm_mask_ps(_mm_fabs_ps(_mm_sub_ps(x, mean[0])), active_pixels);
- scales[1] = _mm_mask_ps(_mm_fabs_ps(_mm_sub_ps(y, mean[1])), active_pixels);
-
- scales[2] = _mm_mask_ps(_mm_fabs_ps(_mm_sub_ps(_mm_fabs_ps(ccl_get_feature_sse(0)), mean[2])), active_pixels);
-
- __m128 diff, scale;
- diff = _mm_sub_ps(ccl_get_feature_sse(1), mean[3]);
- scale = _mm_mul_ps(diff, diff);
- diff = _mm_sub_ps(ccl_get_feature_sse(2), mean[4]);
- scale = _mm_add_ps(scale, _mm_mul_ps(diff, diff));
- diff = _mm_sub_ps(ccl_get_feature_sse(3), mean[5]);
- scale = _mm_add_ps(scale, _mm_mul_ps(diff, diff));
- scales[3] = _mm_mask_ps(scale, active_pixels);
-
- scales[4] = _mm_mask_ps(_mm_fabs_ps(_mm_sub_ps(ccl_get_feature_sse(4), mean[6])), active_pixels);
-
- diff = _mm_sub_ps(ccl_get_feature_sse(5), mean[7]);
- scale = _mm_mul_ps(diff, diff);
- diff = _mm_sub_ps(ccl_get_feature_sse(6), mean[8]);
- scale = _mm_add_ps(scale, _mm_mul_ps(diff, diff));
- diff = _mm_sub_ps(ccl_get_feature_sse(7), mean[9]);
- scale = _mm_add_ps(scale, _mm_mul_ps(diff, diff));
- scales[5] = _mm_mask_ps(scale, active_pixels);
+ scales[0] = fabs(x - mean[0]);
+ scales[1] = fabs(y - mean[1]);
+ scales[2] = fabs(fabs(ccl_get_feature_sse(0)) - mean[2]);
+ scales[3] = sqr(ccl_get_feature_sse(1) - mean[3]) +
+ sqr(ccl_get_feature_sse(2) - mean[4]) +
+ sqr(ccl_get_feature_sse(3) - mean[5]);
+ scales[4] = fabs(ccl_get_feature_sse(4) - mean[6]);
+ scales[5] = sqr(ccl_get_feature_sse(5) - mean[7]) +
+ sqr(ccl_get_feature_sse(6) - mean[8]) +
+ sqr(ccl_get_feature_sse(7) - mean[9]);
+ for(int i = 0; i < 6; i++)
+ scales[i] = mask(active_pixels, scales[i]);
}
-ccl_device_inline void filter_calculate_scale_sse(__m128 *scale)
+ccl_device_inline void filter_calculate_scale_sse(float4 *scale)
{
- scale[0] = _mm_rcp_ps(_mm_max_ps(_mm_hmax_ps(scale[0]), _mm_set1_ps(0.01f)));
- scale[1] = _mm_rcp_ps(_mm_max_ps(_mm_hmax_ps(scale[1]), _mm_set1_ps(0.01f)));
- scale[2] = _mm_rcp_ps(_mm_max_ps(_mm_hmax_ps(scale[2]), _mm_set1_ps(0.01f)));
- scale[6] = _mm_rcp_ps(_mm_max_ps(_mm_hmax_ps(scale[4]), _mm_set1_ps(0.01f)));
-
- scale[7] = scale[8] = scale[9] = _mm_rcp_ps(_mm_max_ps(_mm_hmax_ps(_mm_sqrt_ps(scale[5])), _mm_set1_ps(0.01f)));
- scale[3] = scale[4] = scale[5] = _mm_rcp_ps(_mm_max_ps(_mm_hmax_ps(_mm_sqrt_ps(scale[3])), _mm_set1_ps(0.01f)));
+ scale[0] = rcp(max(reduce_max(scale[0]), make_float4(0.01f)));
+ scale[1] = rcp(max(reduce_max(scale[1]), make_float4(0.01f)));
+ scale[2] = rcp(max(reduce_max(scale[2]), make_float4(0.01f)));
+ scale[6] = rcp(max(reduce_max(scale[4]), make_float4(0.01f)));
+ scale[7] = scale[8] = scale[9] = rcp(max(reduce_max(sqrt(scale[5])), make_float4(0.01f)));
+ scale[3] = scale[4] = scale[5] = rcp(max(reduce_max(sqrt(scale[3])), make_float4(0.01f)));
}
diff --git a/intern/cycles/kernel/filter/filter_nlm_cpu.h b/intern/cycles/kernel/filter/filter_nlm_cpu.h
index 5cb4038bc33..5e989331bc2 100644
--- a/intern/cycles/kernel/filter/filter_nlm_cpu.h
+++ b/intern/cycles/kernel/filter/filter_nlm_cpu.h
@@ -50,10 +50,8 @@ ccl_device_inline void kernel_filter_nlm_blur(const float *ccl_restrict differen
int w,
int f)
{
-#ifdef __KERNEL_SSE3__
- int aligned_lowx = (rect.x & ~(3));
- int aligned_highx = ((rect.z + 3) & ~(3));
-#endif
+ int aligned_lowx = rect.x / 4;
+ int aligned_highx = (rect.z + 3) / 4;
for(int y = rect.y; y < rect.w; y++) {
const int low = max(rect.y, y-f);
const int high = min(rect.w, y+f+1);
@@ -61,15 +59,11 @@ ccl_device_inline void kernel_filter_nlm_blur(const float *ccl_restrict differen
out_image[y*w+x] = 0.0f;
}
for(int y1 = low; y1 < high; y1++) {
-#ifdef __KERNEL_SSE3__
- for(int x = aligned_lowx; x < aligned_highx; x+=4) {
- _mm_store_ps(out_image + y*w+x, _mm_add_ps(_mm_load_ps(out_image + y*w+x), _mm_load_ps(difference_image + y1*w+x)));
+ float4* out_image4 = (float4*)(out_image + y*w);
+ float4* difference_image4 = (float4*)(difference_image + y1*w);
+ for(int x = aligned_lowx; x < aligned_highx; x++) {
+ out_image4[x] += difference_image4[x];
}
-#else
- for(int x = rect.x; x < rect.z; x++) {
- out_image[y*w+x] += difference_image[y1*w+x];
- }
-#endif
}
for(int x = rect.x; x < rect.z; x++) {
out_image[y*w+x] *= 1.0f/(high - low);
@@ -101,7 +95,7 @@ ccl_device_inline void kernel_filter_nlm_calc_weight(const float *ccl_restrict d
for(int x = rect.x; x < rect.z; x++) {
const int low = max(rect.x, x-f);
const int high = min(rect.z, x+f+1);
- out_image[y*w+x] = expf(-max(out_image[y*w+x] * (1.0f/(high - low)), 0.0f));
+ out_image[y*w+x] = fast_expf(-max(out_image[y*w+x] * (1.0f/(high - low)), 0.0f));
}
}
}
@@ -133,8 +127,6 @@ ccl_device_inline void kernel_filter_nlm_update_output(int dx, int dy,
ccl_device_inline void kernel_filter_nlm_construct_gramian(int dx, int dy,
const float *ccl_restrict difference_image,
const float *ccl_restrict buffer,
- float *color_pass,
- float *variance_pass,
float *transform,
int *rank,
float *XtWX,
@@ -167,7 +159,6 @@ ccl_device_inline void kernel_filter_nlm_construct_gramian(int dx, int dy,
dx, dy, w, h,
pass_stride,
buffer,
- color_pass, variance_pass,
l_transform, l_rank,
weight, l_XtWX, l_XtWY, 0);
}
diff --git a/intern/cycles/kernel/filter/filter_nlm_gpu.h b/intern/cycles/kernel/filter/filter_nlm_gpu.h
index 078c5f56763..2c5ac807051 100644
--- a/intern/cycles/kernel/filter/filter_nlm_gpu.h
+++ b/intern/cycles/kernel/filter/filter_nlm_gpu.h
@@ -66,7 +66,7 @@ ccl_device_inline void kernel_filter_nlm_calc_weight(int x, int y,
sum += difference_image[y*w+x1];
}
sum *= 1.0f/(high-low);
- out_image[y*w+x] = expf(-max(sum, 0.0f));
+ out_image[y*w+x] = fast_expf(-max(sum, 0.0f));
}
ccl_device_inline void kernel_filter_nlm_update_output(int x, int y,
@@ -97,8 +97,6 @@ ccl_device_inline void kernel_filter_nlm_construct_gramian(int fx, int fy,
int dx, int dy,
const ccl_global float *ccl_restrict difference_image,
const ccl_global float *ccl_restrict buffer,
- ccl_global float *color_pass,
- ccl_global float *variance_pass,
const ccl_global float *ccl_restrict transform,
ccl_global int *rank,
ccl_global float *XtWX,
@@ -130,7 +128,6 @@ ccl_device_inline void kernel_filter_nlm_construct_gramian(int fx, int fy,
dx, dy, w, h,
pass_stride,
buffer,
- color_pass, variance_pass,
transform, rank,
weight, XtWX, XtWY,
localIdx);
diff --git a/intern/cycles/kernel/filter/filter_prefilter.h b/intern/cycles/kernel/filter/filter_prefilter.h
index 82cc36625ec..2aeb54a62be 100644
--- a/intern/cycles/kernel/filter/filter_prefilter.h
+++ b/intern/cycles/kernel/filter/filter_prefilter.h
@@ -61,8 +61,8 @@ ccl_device void kernel_filter_divide_shadow(int sample,
varA = max(0.0f, varA - unfilteredA[idx]*unfilteredA[idx]*odd_sample);
varB = max(0.0f, varB - unfilteredB[idx]*unfilteredB[idx]*even_sample);
}
- varA /= (odd_sample - 1);
- varB /= (even_sample - 1);
+ varA /= max(odd_sample - 1, 1);
+ varB /= max(even_sample - 1, 1);
sampleVariance[idx] = 0.5f*(varA + varB) / sample;
sampleVarianceV[idx] = 0.5f * (varA - varB) * (varA - varB) / (sample*sample);
@@ -96,11 +96,17 @@ ccl_device void kernel_filter_get_feature(int sample,
int idx = (y-rect.y)*buffer_w + (x - rect.x);
mean[idx] = center_buffer[m_offset] / sample;
- if(use_split_variance) {
- variance[idx] = max(0.0f, (center_buffer[v_offset] - mean[idx]*mean[idx]*sample) / (sample * (sample-1)));
+ if(sample > 1) {
+ if(use_split_variance) {
+ variance[idx] = max(0.0f, (center_buffer[v_offset] - mean[idx]*mean[idx]*sample) / (sample * (sample-1)));
+ }
+ else {
+ variance[idx] = center_buffer[v_offset] / (sample * (sample-1));
+ }
}
else {
- variance[idx] = center_buffer[v_offset] / (sample * (sample-1));
+ /* Can't compute variance with single sample, just set it very high. */
+ variance[idx] = 1e10f;
}
}
@@ -114,41 +120,57 @@ ccl_device void kernel_filter_detect_outliers(int x, int y,
{
int buffer_w = align_up(rect.z - rect.x, 4);
- int n = 0;
- float values[25];
- for(int y1 = max(y-2, rect.y); y1 < min(y+3, rect.w); y1++) {
- for(int x1 = max(x-2, rect.x); x1 < min(x+3, rect.z); x1++) {
- int idx = (y1-rect.y)*buffer_w + (x1-rect.x);
- float L = average(make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]));
-
- /* Find the position of L. */
- int i;
- for(i = 0; i < n; i++) {
- if(values[i] > L) break;
- }
- /* Make space for L by shifting all following values to the right. */
- for(int j = n; j > i; j--) {
- values[j] = values[j-1];
- }
- /* Insert L. */
- values[i] = L;
- n++;
- }
- }
-
int idx = (y-rect.y)*buffer_w + (x-rect.x);
- float L = average(make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]));
+ float3 color = make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]);
- float ref = 2.0f*values[(int)(n*0.75f)];
float fac = 1.0f;
- if(L > ref) {
- /* If the pixel is an outlier, negate the depth value to mark it as one.
- * Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */
+ if(color.x < 0.0f || color.y < 0.0f || color.z < 0.0f) {
depth[idx] = -depth[idx];
- fac = ref/L;
- variance[idx ] *= fac*fac;
- variance[idx + pass_stride] *= fac*fac;
- variance[idx+2*pass_stride] *= fac*fac;
+ fac = 0.0f;
+ }
+ else {
+ float L = average(color);
+ int n = 0;
+ float values[25];
+ for(int y1 = max(y-2, rect.y); y1 < min(y+3, rect.w); y1++) {
+ for(int x1 = max(x-2, rect.x); x1 < min(x+3, rect.z); x1++) {
+ int idx = (y1-rect.y)*buffer_w + (x1-rect.x);
+ float L = average(make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]));
+
+ /* Find the position of L. */
+ int i;
+ for(i = 0; i < n; i++) {
+ if(values[i] > L) break;
+ }
+ /* Make space for L by shifting all following values to the right. */
+ for(int j = n; j > i; j--) {
+ values[j] = values[j-1];
+ }
+ /* Insert L. */
+ values[i] = L;
+ n++;
+ }
+ }
+
+ float ref = 2.0f*values[(int)(n*0.75f)];
+ if(L > ref) {
+ /* The pixel appears to be an outlier.
+ * However, it may just be a legitimate highlight. Therefore, it is checked how likely it is that the pixel
+ * should actually be at the reference value:
+ * If the reference is within the 3-sigma interval, the pixel is assumed to be a statistical outlier.
+ * Otherwise, it is very unlikely that the pixel should be darker, which indicates a legitimate highlight.
+ */
+ float stddev = sqrtf(average(make_float3(variance[idx], variance[idx+pass_stride], variance[idx+2*pass_stride])));
+ if(L - 3*stddev < ref) {
+ /* The pixel is an outlier, so negate the depth value to mark it as one.
+ * Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */
+ depth[idx] = -depth[idx];
+ fac = ref/L;
+ variance[idx ] *= fac*fac;
+ variance[idx + pass_stride] *= fac*fac;
+ variance[idx+2*pass_stride] *= fac*fac;
+ }
+ }
}
out[idx ] = fac*image[idx];
out[idx + pass_stride] = fac*image[idx + pass_stride];
diff --git a/intern/cycles/kernel/filter/filter_reconstruction.h b/intern/cycles/kernel/filter/filter_reconstruction.h
index 4a4c81b7ba3..25a3025056c 100644
--- a/intern/cycles/kernel/filter/filter_reconstruction.h
+++ b/intern/cycles/kernel/filter/filter_reconstruction.h
@@ -22,8 +22,6 @@ ccl_device_inline void kernel_filter_construct_gramian(int x, int y,
int w, int h,
int pass_stride,
const ccl_global float *ccl_restrict buffer,
- ccl_global float *color_pass,
- ccl_global float *variance_pass,
const ccl_global float *ccl_restrict transform,
ccl_global int *rank,
float weight,
@@ -31,38 +29,31 @@ ccl_device_inline void kernel_filter_construct_gramian(int x, int y,
ccl_global float3 *XtWY,
int localIdx)
{
+ if(weight < 1e-3f) {
+ return;
+ }
+
int p_offset = y *w + x;
int q_offset = (y+dy)*w + (x+dx);
-#ifdef __KERNEL_CPU__
- const int stride = 1;
- (void)storage_stride;
- (void)localIdx;
- float design_row[DENOISE_FEATURES+1];
-#elif defined(__KERNEL_CUDA__)
+#ifdef __KERNEL_GPU__
const int stride = storage_stride;
+#else
+ const int stride = 1;
+ (void) storage_stride;
+#endif
+
+#ifdef __KERNEL_CUDA__
ccl_local float shared_design_row[(DENOISE_FEATURES+1)*CCL_MAX_LOCAL_SIZE];
ccl_local_param float *design_row = shared_design_row + localIdx*(DENOISE_FEATURES+1);
#else
- const int stride = storage_stride;
float design_row[DENOISE_FEATURES+1];
#endif
- float3 p_color = filter_get_pixel_color(color_pass + p_offset, pass_stride);
- float3 q_color = filter_get_pixel_color(color_pass + q_offset, pass_stride);
+ float3 q_color = filter_get_color(buffer + q_offset, pass_stride);
- float p_std_dev = sqrtf(filter_get_pixel_variance(variance_pass + p_offset, pass_stride));
- float q_std_dev = sqrtf(filter_get_pixel_variance(variance_pass + q_offset, pass_stride));
-
- /* If the pixel was flagged as an outlier during prefiltering, skip it.
- * Otherwise, perform the regular confidence interval test unless
- * the center pixel is an outlier (in that case, using the confidence
- * interval test could result in no pixels being used at all). */
- bool p_outlier = (ccl_get_feature(buffer + p_offset, 0) < 0.0f);
- bool q_outlier = (ccl_get_feature(buffer + q_offset, 0) < 0.0f);
- bool outside_of_interval = (average(fabs(p_color - q_color)) > 2.0f*(p_std_dev + q_std_dev + 1e-3f));
-
- if(q_outlier || (!p_outlier && outside_of_interval)) {
+ /* If the pixel was flagged as an outlier during prefiltering, skip it. */
+ if(ccl_get_feature(buffer + q_offset, 0) < 0.0f) {
return;
}
@@ -83,13 +74,19 @@ ccl_device_inline void kernel_filter_finalize(int x, int y, int w, int h,
int4 buffer_params,
int sample)
{
-#ifdef __KERNEL_CPU__
- const int stride = 1;
- (void)storage_stride;
-#else
+#ifdef __KERNEL_GPU__
const int stride = storage_stride;
+#else
+ const int stride = 1;
+ (void) storage_stride;
#endif
+ if(XtWX[0] < 1e-3f) {
+ /* There is not enough information to determine a denoised result.
+ * As a fallback, keep the original value of the pixel. */
+ return;
+ }
+
/* The weighted average of pixel colors (essentially, the NLM-filtered image).
* In case the solution of the linear model fails due to numerical issues,
* fall back to this value. */
@@ -102,6 +99,9 @@ ccl_device_inline void kernel_filter_finalize(int x, int y, int w, int h,
final_color = mean_color;
}
+ /* Clamp pixel value to positive values. */
+ final_color = max(final_color, make_float3(0.0f, 0.0f, 0.0f));
+
ccl_global float *combined_buffer = buffer + (y*buffer_params.y + x + buffer_params.x)*buffer_params.z;
final_color *= sample;
if(buffer_params.w) {
@@ -114,6 +114,4 @@ ccl_device_inline void kernel_filter_finalize(int x, int y, int w, int h,
combined_buffer[2] = final_color.z;
}
-#undef STORAGE_TYPE
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/filter/filter_transform_sse.h b/intern/cycles/kernel/filter/filter_transform_sse.h
index 30dc2969b11..9e65f61664b 100644
--- a/intern/cycles/kernel/filter/filter_transform_sse.h
+++ b/intern/cycles/kernel/filter/filter_transform_sse.h
@@ -24,7 +24,7 @@ ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buff
{
int buffer_w = align_up(rect.z - rect.x, 4);
- __m128 features[DENOISE_FEATURES];
+ float4 features[DENOISE_FEATURES];
const float *ccl_restrict pixel_buffer;
int2 pixel;
@@ -34,19 +34,19 @@ ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buff
min(rect.w, y + radius + 1));
int num_pixels = (high.y - low.y) * (high.x - low.x);
- __m128 feature_means[DENOISE_FEATURES];
+ float4 feature_means[DENOISE_FEATURES];
math_vector_zero_sse(feature_means, DENOISE_FEATURES);
FOR_PIXEL_WINDOW_SSE {
filter_get_features_sse(x4, y4, active_pixels, pixel_buffer, features, NULL, pass_stride);
math_vector_add_sse(feature_means, DENOISE_FEATURES, features);
} END_FOR_PIXEL_WINDOW_SSE
- __m128 pixel_scale = _mm_set1_ps(1.0f / num_pixels);
+ float4 pixel_scale = make_float4(1.0f / num_pixels);
for(int i = 0; i < DENOISE_FEATURES; i++) {
- feature_means[i] = _mm_mul_ps(_mm_hsum_ps(feature_means[i]), pixel_scale);
+ feature_means[i] = reduce_add(feature_means[i]) * pixel_scale;
}
- __m128 feature_scale[DENOISE_FEATURES];
+ float4 feature_scale[DENOISE_FEATURES];
math_vector_zero_sse(feature_scale, DENOISE_FEATURES);
FOR_PIXEL_WINDOW_SSE {
filter_get_feature_scales_sse(x4, y4, active_pixels, pixel_buffer, features, feature_means, pass_stride);
@@ -55,12 +55,12 @@ ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buff
filter_calculate_scale_sse(feature_scale);
- __m128 feature_matrix_sse[DENOISE_FEATURES*DENOISE_FEATURES];
+ float4 feature_matrix_sse[DENOISE_FEATURES*DENOISE_FEATURES];
math_matrix_zero_sse(feature_matrix_sse, DENOISE_FEATURES);
FOR_PIXEL_WINDOW_SSE {
filter_get_features_sse(x4, y4, active_pixels, pixel_buffer, features, feature_means, pass_stride);
math_vector_mul_sse(features, DENOISE_FEATURES, feature_scale);
- math_matrix_add_gramian_sse(feature_matrix_sse, DENOISE_FEATURES, features, _mm_set1_ps(1.0f));
+ math_matrix_add_gramian_sse(feature_matrix_sse, DENOISE_FEATURES, features, make_float4(1.0f));
} END_FOR_PIXEL_WINDOW_SSE
float feature_matrix[DENOISE_FEATURES*DENOISE_FEATURES];
@@ -98,7 +98,7 @@ ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buff
/* Bake the feature scaling into the transformation matrix. */
for(int i = 0; i < DENOISE_FEATURES; i++) {
- math_vector_scale(transform + i*DENOISE_FEATURES, _mm_cvtss_f32(feature_scale[i]), *rank);
+ math_vector_scale(transform + i*DENOISE_FEATURES, feature_scale[i][0], *rank);
}
}
diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h
index c623e3490fd..f34b77ebc07 100644
--- a/intern/cycles/kernel/geom/geom.h
+++ b/intern/cycles/kernel/geom/geom.h
@@ -27,6 +27,7 @@
#include "kernel/geom/geom_motion_triangle_shader.h"
#include "kernel/geom/geom_motion_curve.h"
#include "kernel/geom/geom_curve.h"
+#include "kernel/geom/geom_curve_intersect.h"
#include "kernel/geom/geom_volume.h"
#include "kernel/geom/geom_primitive.h"
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index 5c3b0ee3c15..e35267f02bf 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -16,18 +16,13 @@ CCL_NAMESPACE_BEGIN
/* Curve Primitive
*
- * Curve primitive for rendering hair and fur. These can be render as flat ribbons
- * or curves with actual thickness. The curve can also be rendered as line segments
- * rather than curves for better performance */
+ * Curve primitive for rendering hair and fur. These can be render as flat
+ * ribbons or curves with actual thickness. The curve can also be rendered as
+ * line segments rather than curves for better performance.
+ */
#ifdef __HAIR__
-#if defined(__KERNEL_CUDA__) && (__CUDA_ARCH__ < 300)
-# define ccl_device_curveintersect ccl_device
-#else
-# define ccl_device_curveintersect ccl_device_forceinline
-#endif
-
/* Reading attributes on various curve elements */
ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
@@ -151,7 +146,7 @@ ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd
/* Curve tangent normal */
ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
-{
+{
float3 tgN = make_float3(0.0f,0.0f,0.0f);
if(sd->type & PRIMITIVE_ALL_CURVE) {
@@ -219,893 +214,6 @@ ccl_device_inline void curvebounds(float *lower, float *upper, float *extremta,
}
}
-#ifdef __KERNEL_SSE2__
-ccl_device_inline ssef transform_point_T3(const ssef t[3], const ssef &a)
-{
- return madd(shuffle<0>(a), t[0], madd(shuffle<1>(a), t[1], shuffle<2>(a) * t[2]));
-}
-#endif
-
-#ifdef __KERNEL_SSE2__
-/* Pass P and dir by reference to aligned vector */
-ccl_device_curveintersect bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
- const float3 &P, const float3 &dir, uint visibility, int object, int curveAddr, float time, int type, uint *lcg_state, float difl, float extmax)
-#else
-ccl_device_curveintersect bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
- float3 P, float3 dir, uint visibility, int object, int curveAddr, float time,int type, uint *lcg_state, float difl, float extmax)
-#endif
-{
- const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
-
- if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
- const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
- if(time < prim_time.x || time > prim_time.y) {
- return false;
- }
- }
-
- int segment = PRIMITIVE_UNPACK_SEGMENT(type);
- float epsilon = 0.0f;
- float r_st, r_en;
-
- int depth = kernel_data.curve.subdivisions;
- int flags = kernel_data.curve.curveflags;
- int prim = kernel_tex_fetch(__prim_index, curveAddr);
-
-#ifdef __KERNEL_SSE2__
- ssef vdir = load4f(dir);
- ssef vcurve_coef[4];
- const float3 *curve_coef = (float3 *)vcurve_coef;
-
- {
- ssef dtmp = vdir * vdir;
- ssef d_ss = mm_sqrt(dtmp + shuffle<2>(dtmp));
- ssef rd_ss = load1f_first(1.0f) / d_ss;
-
- ssei v00vec = load4i((ssei *)&kg->__curves.data[prim]);
- int2 &v00 = (int2 &)v00vec;
-
- int k0 = v00.x + segment;
- int k1 = k0 + 1;
- int ka = max(k0 - 1, v00.x);
- int kb = min(k1 + 1, v00.x + v00.y - 1);
-
-#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) && (!defined(_MSC_VER) || _MSC_VER > 1800)
- avxf P_curve_0_1, P_curve_2_3;
- if(is_curve_primitive) {
- P_curve_0_1 = _mm256_loadu2_m128(&kg->__curve_keys.data[k0].x, &kg->__curve_keys.data[ka].x);
- P_curve_2_3 = _mm256_loadu2_m128(&kg->__curve_keys.data[kb].x, &kg->__curve_keys.data[k1].x);
- }
- else {
- int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
- motion_cardinal_curve_keys_avx(kg, fobject, prim, time, ka, k0, k1, kb, &P_curve_0_1,&P_curve_2_3);
- }
-#else /* __KERNEL_AVX2__ */
- ssef P_curve[4];
-
- if(is_curve_primitive) {
- P_curve[0] = load4f(&kg->__curve_keys.data[ka].x);
- P_curve[1] = load4f(&kg->__curve_keys.data[k0].x);
- P_curve[2] = load4f(&kg->__curve_keys.data[k1].x);
- P_curve[3] = load4f(&kg->__curve_keys.data[kb].x);
- }
- else {
- int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
- motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, (float4*)&P_curve);
- }
-#endif /* __KERNEL_AVX2__ */
-
- ssef rd_sgn = set_sign_bit<0, 1, 1, 1>(shuffle<0>(rd_ss));
- ssef mul_zxxy = shuffle<2, 0, 0, 1>(vdir) * rd_sgn;
- ssef mul_yz = shuffle<1, 2, 1, 2>(vdir) * mul_zxxy;
- ssef mul_shuf = shuffle<0, 1, 2, 3>(mul_zxxy, mul_yz);
- ssef vdir0 = vdir & cast(ssei(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0));
-
- ssef htfm0 = shuffle<0, 2, 0, 3>(mul_shuf, vdir0);
- ssef htfm1 = shuffle<1, 0, 1, 3>(load1f_first(extract<0>(d_ss)), vdir0);
- ssef htfm2 = shuffle<1, 3, 2, 3>(mul_shuf, vdir0);
-
-#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) && (!defined(_MSC_VER) || _MSC_VER > 1800)
- const avxf vPP = _mm256_broadcast_ps(&P.m128);
- const avxf htfm00 = avxf(htfm0.m128, htfm0.m128);
- const avxf htfm11 = avxf(htfm1.m128, htfm1.m128);
- const avxf htfm22 = avxf(htfm2.m128, htfm2.m128);
-
- const avxf p01 = madd(shuffle<0>(P_curve_0_1 - vPP),
- htfm00,
- madd(shuffle<1>(P_curve_0_1 - vPP),
- htfm11,
- shuffle<2>(P_curve_0_1 - vPP) * htfm22));
- const avxf p23 = madd(shuffle<0>(P_curve_2_3 - vPP),
- htfm00,
- madd(shuffle<1>(P_curve_2_3 - vPP),
- htfm11,
- shuffle<2>(P_curve_2_3 - vPP)*htfm22));
-
- const ssef p0 = _mm256_castps256_ps128(p01);
- const ssef p1 = _mm256_extractf128_ps(p01, 1);
- const ssef p2 = _mm256_castps256_ps128(p23);
- const ssef p3 = _mm256_extractf128_ps(p23, 1);
-
- const ssef P_curve_1 = _mm256_extractf128_ps(P_curve_0_1, 1);
- r_st = ((float4 &)P_curve_1).w;
- const ssef P_curve_2 = _mm256_castps256_ps128(P_curve_2_3);
- r_en = ((float4 &)P_curve_2).w;
-#else /* __KERNEL_AVX2__ */
- ssef htfm[] = { htfm0, htfm1, htfm2 };
- ssef vP = load4f(P);
- ssef p0 = transform_point_T3(htfm, P_curve[0] - vP);
- ssef p1 = transform_point_T3(htfm, P_curve[1] - vP);
- ssef p2 = transform_point_T3(htfm, P_curve[2] - vP);
- ssef p3 = transform_point_T3(htfm, P_curve[3] - vP);
-
- r_st = ((float4 &)P_curve[1]).w;
- r_en = ((float4 &)P_curve[2]).w;
-#endif /* __KERNEL_AVX2__ */
-
- float fc = 0.71f;
- ssef vfc = ssef(fc);
- ssef vfcxp3 = vfc * p3;
-
- vcurve_coef[0] = p1;
- vcurve_coef[1] = vfc * (p2 - p0);
- vcurve_coef[2] = madd(ssef(fc * 2.0f), p0, madd(ssef(fc - 3.0f), p1, msub(ssef(3.0f - 2.0f * fc), p2, vfcxp3)));
- vcurve_coef[3] = msub(ssef(fc - 2.0f), p2 - p1, msub(vfc, p0, vfcxp3));
-
- }
-#else
- float3 curve_coef[4];
-
- /* curve Intersection check */
- /* obtain curve parameters */
- {
- /* ray transform created - this should be created at beginning of intersection loop */
- Transform htfm;
- float d = sqrtf(dir.x * dir.x + dir.z * dir.z);
- htfm = make_transform(
- dir.z / d, 0, -dir.x /d, 0,
- -dir.x * dir.y /d, d, -dir.y * dir.z /d, 0,
- dir.x, dir.y, dir.z, 0,
- 0, 0, 0, 1);
-
- float4 v00 = kernel_tex_fetch(__curves, prim);
-
- int k0 = __float_as_int(v00.x) + segment;
- int k1 = k0 + 1;
-
- int ka = max(k0 - 1,__float_as_int(v00.x));
- int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1);
-
- float4 P_curve[4];
-
- if(is_curve_primitive) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
- P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
- }
- else {
- int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
- motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, P_curve);
- }
-
- float3 p0 = transform_point(&htfm, float4_to_float3(P_curve[0]) - P);
- float3 p1 = transform_point(&htfm, float4_to_float3(P_curve[1]) - P);
- float3 p2 = transform_point(&htfm, float4_to_float3(P_curve[2]) - P);
- float3 p3 = transform_point(&htfm, float4_to_float3(P_curve[3]) - P);
-
- float fc = 0.71f;
- curve_coef[0] = p1;
- curve_coef[1] = -fc*p0 + fc*p2;
- curve_coef[2] = 2.0f * fc * p0 + (fc - 3.0f) * p1 + (3.0f - 2.0f * fc) * p2 - fc * p3;
- curve_coef[3] = -fc * p0 + (2.0f - fc) * p1 + (fc - 2.0f) * p2 + fc * p3;
- r_st = P_curve[1].w;
- r_en = P_curve[2].w;
- }
-#endif
-
- float r_curr = max(r_st, r_en);
-
- if((flags & CURVE_KN_RIBBONS) || !(flags & CURVE_KN_BACKFACING))
- epsilon = 2 * r_curr;
-
- /* find bounds - this is slow for cubic curves */
- float upper, lower;
-
- float zextrem[4];
- curvebounds(&lower, &upper, &zextrem[0], &zextrem[1], &zextrem[2], &zextrem[3], curve_coef[0].z, curve_coef[1].z, curve_coef[2].z, curve_coef[3].z);
- if(lower - r_curr > isect->t || upper + r_curr < epsilon)
- return false;
-
- /* minimum width extension */
- float mw_extension = min(difl * fabsf(upper), extmax);
- float r_ext = mw_extension + r_curr;
-
- float xextrem[4];
- curvebounds(&lower, &upper, &xextrem[0], &xextrem[1], &xextrem[2], &xextrem[3], curve_coef[0].x, curve_coef[1].x, curve_coef[2].x, curve_coef[3].x);
- if(lower > r_ext || upper < -r_ext)
- return false;
-
- float yextrem[4];
- curvebounds(&lower, &upper, &yextrem[0], &yextrem[1], &yextrem[2], &yextrem[3], curve_coef[0].y, curve_coef[1].y, curve_coef[2].y, curve_coef[3].y);
- if(lower > r_ext || upper < -r_ext)
- return false;
-
- /* setup recurrent loop */
- int level = 1 << depth;
- int tree = 0;
- float resol = 1.0f / (float)level;
- bool hit = false;
-
- /* begin loop */
- while(!(tree >> (depth))) {
- const float i_st = tree * resol;
- const float i_en = i_st + (level * resol);
-
-#ifdef __KERNEL_SSE2__
- ssef vi_st = ssef(i_st), vi_en = ssef(i_en);
- ssef vp_st = madd(madd(madd(vcurve_coef[3], vi_st, vcurve_coef[2]), vi_st, vcurve_coef[1]), vi_st, vcurve_coef[0]);
- ssef vp_en = madd(madd(madd(vcurve_coef[3], vi_en, vcurve_coef[2]), vi_en, vcurve_coef[1]), vi_en, vcurve_coef[0]);
-
- ssef vbmin = min(vp_st, vp_en);
- ssef vbmax = max(vp_st, vp_en);
-
- float3 &bmin = (float3 &)vbmin, &bmax = (float3 &)vbmax;
- float &bminx = bmin.x, &bminy = bmin.y, &bminz = bmin.z;
- float &bmaxx = bmax.x, &bmaxy = bmax.y, &bmaxz = bmax.z;
- float3 &p_st = (float3 &)vp_st, &p_en = (float3 &)vp_en;
-#else
- float3 p_st = ((curve_coef[3] * i_st + curve_coef[2]) * i_st + curve_coef[1]) * i_st + curve_coef[0];
- float3 p_en = ((curve_coef[3] * i_en + curve_coef[2]) * i_en + curve_coef[1]) * i_en + curve_coef[0];
-
- float bminx = min(p_st.x, p_en.x);
- float bmaxx = max(p_st.x, p_en.x);
- float bminy = min(p_st.y, p_en.y);
- float bmaxy = max(p_st.y, p_en.y);
- float bminz = min(p_st.z, p_en.z);
- float bmaxz = max(p_st.z, p_en.z);
-#endif
-
- if(xextrem[0] >= i_st && xextrem[0] <= i_en) {
- bminx = min(bminx,xextrem[1]);
- bmaxx = max(bmaxx,xextrem[1]);
- }
- if(xextrem[2] >= i_st && xextrem[2] <= i_en) {
- bminx = min(bminx,xextrem[3]);
- bmaxx = max(bmaxx,xextrem[3]);
- }
- if(yextrem[0] >= i_st && yextrem[0] <= i_en) {
- bminy = min(bminy,yextrem[1]);
- bmaxy = max(bmaxy,yextrem[1]);
- }
- if(yextrem[2] >= i_st && yextrem[2] <= i_en) {
- bminy = min(bminy,yextrem[3]);
- bmaxy = max(bmaxy,yextrem[3]);
- }
- if(zextrem[0] >= i_st && zextrem[0] <= i_en) {
- bminz = min(bminz,zextrem[1]);
- bmaxz = max(bmaxz,zextrem[1]);
- }
- if(zextrem[2] >= i_st && zextrem[2] <= i_en) {
- bminz = min(bminz,zextrem[3]);
- bmaxz = max(bmaxz,zextrem[3]);
- }
-
- float r1 = r_st + (r_en - r_st) * i_st;
- float r2 = r_st + (r_en - r_st) * i_en;
- r_curr = max(r1, r2);
-
- mw_extension = min(difl * fabsf(bmaxz), extmax);
- float r_ext = mw_extension + r_curr;
- float coverage = 1.0f;
-
- if(bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext|| bmaxx < -r_ext|| bminy > r_ext|| bmaxy < -r_ext) {
- /* the bounding box does not overlap the square centered at O */
- tree += level;
- level = tree & -tree;
- }
- else if(level == 1) {
-
- /* the maximum recursion depth is reached.
- * check if dP0.(Q-P0)>=0 and dPn.(Pn-Q)>=0.
- * dP* is reversed if necessary.*/
- float t = isect->t;
- float u = 0.0f;
- float gd = 0.0f;
-
- if(flags & CURVE_KN_RIBBONS) {
- float3 tg = (p_en - p_st);
-#ifdef __KERNEL_SSE__
- const float3 tg_sq = tg * tg;
- float w = tg_sq.x + tg_sq.y;
-#else
- float w = tg.x * tg.x + tg.y * tg.y;
-#endif
- if(w == 0) {
- tree++;
- level = tree & -tree;
- continue;
- }
-#ifdef __KERNEL_SSE__
- const float3 p_sttg = p_st * tg;
- w = -(p_sttg.x + p_sttg.y) / w;
-#else
- w = -(p_st.x * tg.x + p_st.y * tg.y) / w;
-#endif
- w = saturate(w);
-
- /* compute u on the curve segment */
- u = i_st * (1 - w) + i_en * w;
- r_curr = r_st + (r_en - r_st) * u;
- /* compare x-y distances */
- float3 p_curr = ((curve_coef[3] * u + curve_coef[2]) * u + curve_coef[1]) * u + curve_coef[0];
-
- float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
- if(dot(tg, dp_st)< 0)
- dp_st *= -1;
- if(dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) {
- tree++;
- level = tree & -tree;
- continue;
- }
- float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
- if(dot(tg, dp_en) < 0)
- dp_en *= -1;
- if(dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) {
- tree++;
- level = tree & -tree;
- continue;
- }
-
- /* compute coverage */
- float r_ext = r_curr;
- coverage = 1.0f;
- if(difl != 0.0f) {
- mw_extension = min(difl * fabsf(bmaxz), extmax);
- r_ext = mw_extension + r_curr;
-#ifdef __KERNEL_SSE__
- const float3 p_curr_sq = p_curr * p_curr;
- const float3 dxxx(_mm_sqrt_ss(_mm_hadd_ps(p_curr_sq.m128, p_curr_sq.m128)));
- float d = dxxx.x;
-#else
- float d = sqrtf(p_curr.x * p_curr.x + p_curr.y * p_curr.y);
-#endif
- float d0 = d - r_curr;
- float d1 = d + r_curr;
- float inv_mw_extension = 1.0f/mw_extension;
- if(d0 >= 0)
- coverage = (min(d1 * inv_mw_extension, 1.0f) - min(d0 * inv_mw_extension, 1.0f)) * 0.5f;
- else // inside
- coverage = (min(d1 * inv_mw_extension, 1.0f) + min(-d0 * inv_mw_extension, 1.0f)) * 0.5f;
- }
-
- if(p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon || isect->t < p_curr.z) {
- tree++;
- level = tree & -tree;
- continue;
- }
-
- t = p_curr.z;
-
- /* stochastic fade from minimum width */
- if(difl != 0.0f && lcg_state) {
- if(coverage != 1.0f && (lcg_step_float(lcg_state) > coverage))
- return hit;
- }
- }
- else {
- float l = len(p_en - p_st);
- /* minimum width extension */
- float or1 = r1;
- float or2 = r2;
-
- if(difl != 0.0f) {
- mw_extension = min(len(p_st - P) * difl, extmax);
- or1 = r1 < mw_extension ? mw_extension : r1;
- mw_extension = min(len(p_en - P) * difl, extmax);
- or2 = r2 < mw_extension ? mw_extension : r2;
- }
- /* --- */
- float invl = 1.0f/l;
- float3 tg = (p_en - p_st) * invl;
- gd = (or2 - or1) * invl;
- float difz = -dot(p_st,tg);
- float cyla = 1.0f - (tg.z * tg.z * (1 + gd*gd));
- float invcyla = 1.0f/cyla;
- float halfb = (-p_st.z - tg.z*(difz + gd*(difz*gd + or1)));
- float tcentre = -halfb*invcyla;
- float zcentre = difz + (tg.z * tcentre);
- float3 tdif = - p_st;
- tdif.z += tcentre;
- float tdifz = dot(tdif,tg);
- float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + or1)));
- float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - or1*or1 - 2*or1*tdifz*gd;
- float td = tb*tb - 4*cyla*tc;
- if(td < 0.0f) {
- tree++;
- level = tree & -tree;
- continue;
- }
-
- float rootd = sqrtf(td);
- float correction = (-tb - rootd) * 0.5f * invcyla;
- t = tcentre + correction;
-
- float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
- if(dot(tg, dp_st)< 0)
- dp_st *= -1;
- float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
- if(dot(tg, dp_en) < 0)
- dp_en *= -1;
-
- if(flags & CURVE_KN_BACKFACING && (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f)) {
- correction = (-tb + rootd) * 0.5f * invcyla;
- t = tcentre + correction;
- }
-
- if(dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f) {
- tree++;
- level = tree & -tree;
- continue;
- }
-
- float w = (zcentre + (tg.z * correction)) * invl;
- w = saturate(w);
- /* compute u on the curve segment */
- u = i_st * (1 - w) + i_en * w;
-
- /* stochastic fade from minimum width */
- if(difl != 0.0f && lcg_state) {
- r_curr = r1 + (r2 - r1) * w;
- r_ext = or1 + (or2 - or1) * w;
- coverage = r_curr/r_ext;
-
- if(coverage != 1.0f && (lcg_step_float(lcg_state) > coverage))
- return hit;
- }
- }
- /* we found a new intersection */
-
-#ifdef __VISIBILITY_FLAG__
- /* visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags */
- if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
-#endif
- {
- /* record intersection */
- isect->t = t;
- isect->u = u;
- isect->v = gd;
- isect->prim = curveAddr;
- isect->object = object;
- isect->type = type;
- hit = true;
- }
-
- tree++;
- level = tree & -tree;
- }
- else {
- /* split the curve into two curves and process */
- level = level >> 1;
- }
- }
-
- return hit;
-}
-
-ccl_device_curveintersect bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
- float3 P, float3 direction, uint visibility, int object, int curveAddr, float time, int type, uint *lcg_state, float difl, float extmax)
-{
- /* define few macros to minimize code duplication for SSE */
-#ifndef __KERNEL_SSE2__
-# define len3_squared(x) len_squared(x)
-# define len3(x) len(x)
-# define dot3(x, y) dot(x, y)
-#endif
-
- const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
-
- if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
- const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
- if(time < prim_time.x || time > prim_time.y) {
- return false;
- }
- }
-
- int segment = PRIMITIVE_UNPACK_SEGMENT(type);
- /* curve Intersection check */
- int flags = kernel_data.curve.curveflags;
-
- int prim = kernel_tex_fetch(__prim_index, curveAddr);
- float4 v00 = kernel_tex_fetch(__curves, prim);
-
- int cnum = __float_as_int(v00.x);
- int k0 = cnum + segment;
- int k1 = k0 + 1;
-
-#ifndef __KERNEL_SSE2__
- float4 P_curve[2];
-
- if(is_curve_primitive) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
- }
- else {
- int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
- motion_curve_keys(kg, fobject, prim, time, k0, k1, P_curve);
- }
-
- float or1 = P_curve[0].w;
- float or2 = P_curve[1].w;
- float3 p1 = float4_to_float3(P_curve[0]);
- float3 p2 = float4_to_float3(P_curve[1]);
-
- /* minimum width extension */
- float r1 = or1;
- float r2 = or2;
- float3 dif = P - p1;
- float3 dif_second = P - p2;
- if(difl != 0.0f) {
- float pixelsize = min(len3(dif) * difl, extmax);
- r1 = or1 < pixelsize ? pixelsize : or1;
- pixelsize = min(len3(dif_second) * difl, extmax);
- r2 = or2 < pixelsize ? pixelsize : or2;
- }
- /* --- */
-
- float3 p21_diff = p2 - p1;
- float3 sphere_dif1 = (dif + dif_second) * 0.5f;
- float3 dir = direction;
- float sphere_b_tmp = dot3(dir, sphere_dif1);
- float3 sphere_dif2 = sphere_dif1 - sphere_b_tmp * dir;
-#else
- ssef P_curve[2];
-
- if(is_curve_primitive) {
- P_curve[0] = load4f(&kg->__curve_keys.data[k0].x);
- P_curve[1] = load4f(&kg->__curve_keys.data[k1].x);
- }
- else {
- int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
- motion_curve_keys(kg, fobject, prim, time, k0, k1, (float4*)&P_curve);
- }
-
- const ssef or12 = shuffle<3, 3, 3, 3>(P_curve[0], P_curve[1]);
-
- ssef r12 = or12;
- const ssef vP = load4f(P);
- const ssef dif = vP - P_curve[0];
- const ssef dif_second = vP - P_curve[1];
- if(difl != 0.0f) {
- const ssef len1_sq = len3_squared_splat(dif);
- const ssef len2_sq = len3_squared_splat(dif_second);
- const ssef len12 = mm_sqrt(shuffle<0, 0, 0, 0>(len1_sq, len2_sq));
- const ssef pixelsize12 = min(len12 * difl, ssef(extmax));
- r12 = max(or12, pixelsize12);
- }
- float or1 = extract<0>(or12), or2 = extract<0>(shuffle<2>(or12));
- float r1 = extract<0>(r12), r2 = extract<0>(shuffle<2>(r12));
-
- const ssef p21_diff = P_curve[1] - P_curve[0];
- const ssef sphere_dif1 = (dif + dif_second) * 0.5f;
- const ssef dir = load4f(direction);
- const ssef sphere_b_tmp = dot3_splat(dir, sphere_dif1);
- const ssef sphere_dif2 = nmadd(sphere_b_tmp, dir, sphere_dif1);
-#endif
-
- float mr = max(r1, r2);
- float l = len3(p21_diff);
- float invl = 1.0f / l;
- float sp_r = mr + 0.5f * l;
-
- float sphere_b = dot3(dir, sphere_dif2);
- float sdisc = sphere_b * sphere_b - len3_squared(sphere_dif2) + sp_r * sp_r;
-
- if(sdisc < 0.0f)
- return false;
-
- /* obtain parameters and test midpoint distance for suitable modes */
-#ifndef __KERNEL_SSE2__
- float3 tg = p21_diff * invl;
-#else
- const ssef tg = p21_diff * invl;
-#endif
- float gd = (r2 - r1) * invl;
-
- float dirz = dot3(dir, tg);
- float difz = dot3(dif, tg);
-
- float a = 1.0f - (dirz*dirz*(1 + gd*gd));
-
- float halfb = dot3(dir, dif) - dirz*(difz + gd*(difz*gd + r1));
-
- float tcentre = -halfb/a;
- float zcentre = difz + (dirz * tcentre);
-
- if((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE))
- return false;
- if((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) && !(flags & CURVE_KN_INTERSECTCORRECTION))
- return false;
-
- /* test minimum separation */
-#ifndef __KERNEL_SSE2__
- float3 cprod = cross(tg, dir);
- float cprod2sq = len3_squared(cross(tg, dif));
-#else
- const ssef cprod = cross(tg, dir);
- float cprod2sq = len3_squared(cross_zxy(tg, dif));
-#endif
- float cprodsq = len3_squared(cprod);
- float distscaled = dot3(cprod, dif);
-
- if(cprodsq == 0)
- distscaled = cprod2sq;
- else
- distscaled = (distscaled*distscaled)/cprodsq;
-
- if(distscaled > mr*mr)
- return false;
-
- /* calculate true intersection */
-#ifndef __KERNEL_SSE2__
- float3 tdif = dif + tcentre * dir;
-#else
- const ssef tdif = madd(ssef(tcentre), dir, dif);
-#endif
- float tdifz = dot3(tdif, tg);
- float tdifma = tdifz*gd + r1;
- float tb = 2*(dot3(dir, tdif) - dirz*(tdifz + gd*tdifma));
- float tc = dot3(tdif, tdif) - tdifz*tdifz - tdifma*tdifma;
- float td = tb*tb - 4*a*tc;
-
- if(td < 0.0f)
- return false;
-
- float rootd = 0.0f;
- float correction = 0.0f;
- if(flags & CURVE_KN_ACCURATE) {
- rootd = sqrtf(td);
- correction = ((-tb - rootd)/(2*a));
- }
-
- float t = tcentre + correction;
-
- if(t < isect->t) {
-
- if(flags & CURVE_KN_INTERSECTCORRECTION) {
- rootd = sqrtf(td);
- correction = ((-tb - rootd)/(2*a));
- t = tcentre + correction;
- }
-
- float z = zcentre + (dirz * correction);
- // bool backface = false;
-
- if(flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) {
- // backface = true;
- correction = ((-tb + rootd)/(2*a));
- t = tcentre + correction;
- z = zcentre + (dirz * correction);
- }
-
- /* stochastic fade from minimum width */
- float adjradius = or1 + z * (or2 - or1) * invl;
- adjradius = adjradius / (r1 + z * gd);
- if(lcg_state && adjradius != 1.0f) {
- if(lcg_step_float(lcg_state) > adjradius)
- return false;
- }
- /* --- */
-
- if(t > 0.0f && t < isect->t && z >= 0 && z <= l) {
-
- if(flags & CURVE_KN_ENCLOSEFILTER) {
- float enc_ratio = 1.01f;
- if((difz > -r1 * enc_ratio) && (dot3(dif_second, tg) < r2 * enc_ratio)) {
- float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio));
- float c2 = dot3(dif, dif) - difz * difz * (1 + gd*gd*enc_ratio*enc_ratio) - r1*r1*enc_ratio*enc_ratio - 2*r1*difz*gd*enc_ratio;
- if(a2*c2 < 0.0f)
- return false;
- }
- }
-
-#ifdef __VISIBILITY_FLAG__
- /* visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags */
- if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
-#endif
- {
- /* record intersection */
- isect->t = t;
- isect->u = z*invl;
- isect->v = gd;
- isect->prim = curveAddr;
- isect->object = object;
- isect->type = type;
-
- return true;
- }
- }
- }
-
- return false;
-
-#ifndef __KERNEL_SSE2__
-# undef len3_squared
-# undef len3
-# undef dot3
-#endif
-}
-
-ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
-{
- float fc = 0.71f;
- float data[4];
- float t2 = t * t;
- data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
- data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
- data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
- data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
- return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
-}
-
-ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
-{
- float data[4];
- float fc = 0.71f;
- float t2 = t * t;
- float t3 = t2 * t;
- data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
- data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
- data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
- data[3] = fc * t3 - fc * t2;
- return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
-}
-
-ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
-{
- int flag = kernel_data.curve.curveflags;
- float t = isect->t;
- float3 P = ray->P;
- float3 D = ray->D;
-
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D*t);
- D = normalize_len(D, &t);
- }
-
- int prim = kernel_tex_fetch(__prim_index, isect->prim);
- float4 v00 = kernel_tex_fetch(__curves, prim);
-
- int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
- int k1 = k0 + 1;
-
- float3 tg;
-
- if(flag & CURVE_KN_INTERPOLATE) {
- int ka = max(k0 - 1,__float_as_int(v00.x));
- int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1);
-
- float4 P_curve[4];
-
- if(sd->type & PRIMITIVE_CURVE) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
- P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
- }
- else {
- motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
- }
-
- float3 p[4];
- p[0] = float4_to_float3(P_curve[0]);
- p[1] = float4_to_float3(P_curve[1]);
- p[2] = float4_to_float3(P_curve[2]);
- p[3] = float4_to_float3(P_curve[3]);
-
- P = P + D*t;
-
-#ifdef __UV__
- sd->u = isect->u;
- sd->v = 0.0f;
-#endif
-
- tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3]));
-
- if(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) {
- sd->Ng = normalize(-(D - tg * (dot(tg, D))));
- }
- else {
- /* direction from inside to surface of curve */
- float3 p_curr = curvepoint(isect->u, p[0], p[1], p[2], p[3]);
- sd->Ng = normalize(P - p_curr);
-
- /* adjustment for changing radius */
- float gd = isect->v;
-
- if(gd != 0.0f) {
- sd->Ng = sd->Ng - gd * tg;
- sd->Ng = normalize(sd->Ng);
- }
- }
-
- /* todo: sometimes the normal is still so that this is detected as
- * backfacing even if cull backfaces is enabled */
-
- sd->N = sd->Ng;
- }
- else {
- float4 P_curve[2];
-
- if(sd->type & PRIMITIVE_CURVE) {
- P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
- P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
- }
- else {
- motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
- }
-
- float l = 1.0f;
- tg = normalize_len(float4_to_float3(P_curve[1] - P_curve[0]), &l);
-
- P = P + D*t;
-
- float3 dif = P - float4_to_float3(P_curve[0]);
-
-#ifdef __UV__
- sd->u = dot(dif,tg)/l;
- sd->v = 0.0f;
-#endif
-
- if(flag & CURVE_KN_TRUETANGENTGNORMAL) {
- sd->Ng = -(D - tg * dot(tg, D));
- sd->Ng = normalize(sd->Ng);
- }
- else {
- float gd = isect->v;
-
- /* direction from inside to surface of curve */
- sd->Ng = (dif - tg * sd->u * l) / (P_curve[0].w + sd->u * l * gd);
-
- /* adjustment for changing radius */
- if(gd != 0.0f) {
- sd->Ng = sd->Ng - gd * tg;
- sd->Ng = normalize(sd->Ng);
- }
- }
-
- sd->N = sd->Ng;
- }
-
-#ifdef __DPDU__
- /* dPdu/dPdv */
- sd->dPdu = tg;
- sd->dPdv = cross(tg, sd->Ng);
-#endif
-
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- }
-
- return P;
-}
-
-#endif
+#endif /* __HAIR__ */
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/kernel/geom/geom_curve_intersect.h b/intern/cycles/kernel/geom/geom_curve_intersect.h
new file mode 100644
index 00000000000..e9a149ea1ab
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_curve_intersect.h
@@ -0,0 +1,934 @@
+/*
+ * 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
+
+/* Curve primitive intersection functions. */
+
+#ifdef __HAIR__
+
+#if defined(__KERNEL_CUDA__) && (__CUDA_ARCH__ < 300)
+# define ccl_device_curveintersect ccl_device
+#else
+# define ccl_device_curveintersect ccl_device_forceinline
+#endif
+
+#ifdef __KERNEL_SSE2__
+ccl_device_inline ssef transform_point_T3(const ssef t[3], const ssef &a)
+{
+ return madd(shuffle<0>(a), t[0], madd(shuffle<1>(a), t[1], shuffle<2>(a) * t[2]));
+}
+#endif
+
+/* On CPU pass P and dir by reference to aligned vector. */
+ccl_device_curveintersect bool cardinal_curve_intersect(
+ KernelGlobals *kg,
+ Intersection *isect,
+ const float3 ccl_ref P,
+ const float3 ccl_ref dir,
+ uint visibility,
+ int object,
+ int curveAddr,
+ float time,
+ int type,
+ uint *lcg_state,
+ float difl,
+ float extmax)
+{
+ const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
+
+ if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
+ const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
+ if(time < prim_time.x || time > prim_time.y) {
+ return false;
+ }
+ }
+
+ int segment = PRIMITIVE_UNPACK_SEGMENT(type);
+ float epsilon = 0.0f;
+ float r_st, r_en;
+
+ int depth = kernel_data.curve.subdivisions;
+ int flags = kernel_data.curve.curveflags;
+ int prim = kernel_tex_fetch(__prim_index, curveAddr);
+
+#ifdef __KERNEL_SSE2__
+ ssef vdir = load4f(dir);
+ ssef vcurve_coef[4];
+ const float3 *curve_coef = (float3 *)vcurve_coef;
+
+ {
+ ssef dtmp = vdir * vdir;
+ ssef d_ss = mm_sqrt(dtmp + shuffle<2>(dtmp));
+ ssef rd_ss = load1f_first(1.0f) / d_ss;
+
+ ssei v00vec = load4i((ssei *)&kg->__curves.data[prim]);
+ int2 &v00 = (int2 &)v00vec;
+
+ int k0 = v00.x + segment;
+ int k1 = k0 + 1;
+ int ka = max(k0 - 1, v00.x);
+ int kb = min(k1 + 1, v00.x + v00.y - 1);
+
+#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) && (!defined(_MSC_VER) || _MSC_VER > 1800)
+ avxf P_curve_0_1, P_curve_2_3;
+ if(is_curve_primitive) {
+ P_curve_0_1 = _mm256_loadu2_m128(&kg->__curve_keys.data[k0].x, &kg->__curve_keys.data[ka].x);
+ P_curve_2_3 = _mm256_loadu2_m128(&kg->__curve_keys.data[kb].x, &kg->__curve_keys.data[k1].x);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
+ motion_cardinal_curve_keys_avx(kg, fobject, prim, time, ka, k0, k1, kb, &P_curve_0_1,&P_curve_2_3);
+ }
+#else /* __KERNEL_AVX2__ */
+ ssef P_curve[4];
+
+ if(is_curve_primitive) {
+ P_curve[0] = load4f(&kg->__curve_keys.data[ka].x);
+ P_curve[1] = load4f(&kg->__curve_keys.data[k0].x);
+ P_curve[2] = load4f(&kg->__curve_keys.data[k1].x);
+ P_curve[3] = load4f(&kg->__curve_keys.data[kb].x);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
+ motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, (float4*)&P_curve);
+ }
+#endif /* __KERNEL_AVX2__ */
+
+ ssef rd_sgn = set_sign_bit<0, 1, 1, 1>(shuffle<0>(rd_ss));
+ ssef mul_zxxy = shuffle<2, 0, 0, 1>(vdir) * rd_sgn;
+ ssef mul_yz = shuffle<1, 2, 1, 2>(vdir) * mul_zxxy;
+ ssef mul_shuf = shuffle<0, 1, 2, 3>(mul_zxxy, mul_yz);
+ ssef vdir0 = vdir & cast(ssei(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0));
+
+ ssef htfm0 = shuffle<0, 2, 0, 3>(mul_shuf, vdir0);
+ ssef htfm1 = shuffle<1, 0, 1, 3>(load1f_first(extract<0>(d_ss)), vdir0);
+ ssef htfm2 = shuffle<1, 3, 2, 3>(mul_shuf, vdir0);
+
+#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) && (!defined(_MSC_VER) || _MSC_VER > 1800)
+ const avxf vPP = _mm256_broadcast_ps(&P.m128);
+ const avxf htfm00 = avxf(htfm0.m128, htfm0.m128);
+ const avxf htfm11 = avxf(htfm1.m128, htfm1.m128);
+ const avxf htfm22 = avxf(htfm2.m128, htfm2.m128);
+
+ const avxf p01 = madd(shuffle<0>(P_curve_0_1 - vPP),
+ htfm00,
+ madd(shuffle<1>(P_curve_0_1 - vPP),
+ htfm11,
+ shuffle<2>(P_curve_0_1 - vPP) * htfm22));
+ const avxf p23 = madd(shuffle<0>(P_curve_2_3 - vPP),
+ htfm00,
+ madd(shuffle<1>(P_curve_2_3 - vPP),
+ htfm11,
+ shuffle<2>(P_curve_2_3 - vPP)*htfm22));
+
+ const ssef p0 = _mm256_castps256_ps128(p01);
+ const ssef p1 = _mm256_extractf128_ps(p01, 1);
+ const ssef p2 = _mm256_castps256_ps128(p23);
+ const ssef p3 = _mm256_extractf128_ps(p23, 1);
+
+ const ssef P_curve_1 = _mm256_extractf128_ps(P_curve_0_1, 1);
+ r_st = ((float4 &)P_curve_1).w;
+ const ssef P_curve_2 = _mm256_castps256_ps128(P_curve_2_3);
+ r_en = ((float4 &)P_curve_2).w;
+#else /* __KERNEL_AVX2__ */
+ ssef htfm[] = { htfm0, htfm1, htfm2 };
+ ssef vP = load4f(P);
+ ssef p0 = transform_point_T3(htfm, P_curve[0] - vP);
+ ssef p1 = transform_point_T3(htfm, P_curve[1] - vP);
+ ssef p2 = transform_point_T3(htfm, P_curve[2] - vP);
+ ssef p3 = transform_point_T3(htfm, P_curve[3] - vP);
+
+ r_st = ((float4 &)P_curve[1]).w;
+ r_en = ((float4 &)P_curve[2]).w;
+#endif /* __KERNEL_AVX2__ */
+
+ float fc = 0.71f;
+ ssef vfc = ssef(fc);
+ ssef vfcxp3 = vfc * p3;
+
+ vcurve_coef[0] = p1;
+ vcurve_coef[1] = vfc * (p2 - p0);
+ vcurve_coef[2] = madd(ssef(fc * 2.0f), p0, madd(ssef(fc - 3.0f), p1, msub(ssef(3.0f - 2.0f * fc), p2, vfcxp3)));
+ vcurve_coef[3] = msub(ssef(fc - 2.0f), p2 - p1, msub(vfc, p0, vfcxp3));
+
+ }
+#else
+ float3 curve_coef[4];
+
+ /* curve Intersection check */
+ /* obtain curve parameters */
+ {
+ /* ray transform created - this should be created at beginning of intersection loop */
+ Transform htfm;
+ float d = sqrtf(dir.x * dir.x + dir.z * dir.z);
+ htfm = make_transform(
+ dir.z / d, 0, -dir.x /d, 0,
+ -dir.x * dir.y /d, d, -dir.y * dir.z /d, 0,
+ dir.x, dir.y, dir.z, 0,
+ 0, 0, 0, 1);
+
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int k0 = __float_as_int(v00.x) + segment;
+ int k1 = k0 + 1;
+
+ int ka = max(k0 - 1,__float_as_int(v00.x));
+ int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1);
+
+ float4 P_curve[4];
+
+ if(is_curve_primitive) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
+ P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
+ motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, P_curve);
+ }
+
+ float3 p0 = transform_point(&htfm, float4_to_float3(P_curve[0]) - P);
+ float3 p1 = transform_point(&htfm, float4_to_float3(P_curve[1]) - P);
+ float3 p2 = transform_point(&htfm, float4_to_float3(P_curve[2]) - P);
+ float3 p3 = transform_point(&htfm, float4_to_float3(P_curve[3]) - P);
+
+ float fc = 0.71f;
+ curve_coef[0] = p1;
+ curve_coef[1] = -fc*p0 + fc*p2;
+ curve_coef[2] = 2.0f * fc * p0 + (fc - 3.0f) * p1 + (3.0f - 2.0f * fc) * p2 - fc * p3;
+ curve_coef[3] = -fc * p0 + (2.0f - fc) * p1 + (fc - 2.0f) * p2 + fc * p3;
+ r_st = P_curve[1].w;
+ r_en = P_curve[2].w;
+ }
+#endif
+
+ float r_curr = max(r_st, r_en);
+
+ if((flags & CURVE_KN_RIBBONS) || !(flags & CURVE_KN_BACKFACING))
+ epsilon = 2 * r_curr;
+
+ /* find bounds - this is slow for cubic curves */
+ float upper, lower;
+
+ float zextrem[4];
+ curvebounds(&lower, &upper, &zextrem[0], &zextrem[1], &zextrem[2], &zextrem[3], curve_coef[0].z, curve_coef[1].z, curve_coef[2].z, curve_coef[3].z);
+ if(lower - r_curr > isect->t || upper + r_curr < epsilon)
+ return false;
+
+ /* minimum width extension */
+ float mw_extension = min(difl * fabsf(upper), extmax);
+ float r_ext = mw_extension + r_curr;
+
+ float xextrem[4];
+ curvebounds(&lower, &upper, &xextrem[0], &xextrem[1], &xextrem[2], &xextrem[3], curve_coef[0].x, curve_coef[1].x, curve_coef[2].x, curve_coef[3].x);
+ if(lower > r_ext || upper < -r_ext)
+ return false;
+
+ float yextrem[4];
+ curvebounds(&lower, &upper, &yextrem[0], &yextrem[1], &yextrem[2], &yextrem[3], curve_coef[0].y, curve_coef[1].y, curve_coef[2].y, curve_coef[3].y);
+ if(lower > r_ext || upper < -r_ext)
+ return false;
+
+ /* setup recurrent loop */
+ int level = 1 << depth;
+ int tree = 0;
+ float resol = 1.0f / (float)level;
+ bool hit = false;
+
+ /* begin loop */
+ while(!(tree >> (depth))) {
+ const float i_st = tree * resol;
+ const float i_en = i_st + (level * resol);
+
+#ifdef __KERNEL_SSE2__
+ ssef vi_st = ssef(i_st), vi_en = ssef(i_en);
+ ssef vp_st = madd(madd(madd(vcurve_coef[3], vi_st, vcurve_coef[2]), vi_st, vcurve_coef[1]), vi_st, vcurve_coef[0]);
+ ssef vp_en = madd(madd(madd(vcurve_coef[3], vi_en, vcurve_coef[2]), vi_en, vcurve_coef[1]), vi_en, vcurve_coef[0]);
+
+ ssef vbmin = min(vp_st, vp_en);
+ ssef vbmax = max(vp_st, vp_en);
+
+ float3 &bmin = (float3 &)vbmin, &bmax = (float3 &)vbmax;
+ float &bminx = bmin.x, &bminy = bmin.y, &bminz = bmin.z;
+ float &bmaxx = bmax.x, &bmaxy = bmax.y, &bmaxz = bmax.z;
+ float3 &p_st = (float3 &)vp_st, &p_en = (float3 &)vp_en;
+#else
+ float3 p_st = ((curve_coef[3] * i_st + curve_coef[2]) * i_st + curve_coef[1]) * i_st + curve_coef[0];
+ float3 p_en = ((curve_coef[3] * i_en + curve_coef[2]) * i_en + curve_coef[1]) * i_en + curve_coef[0];
+
+ float bminx = min(p_st.x, p_en.x);
+ float bmaxx = max(p_st.x, p_en.x);
+ float bminy = min(p_st.y, p_en.y);
+ float bmaxy = max(p_st.y, p_en.y);
+ float bminz = min(p_st.z, p_en.z);
+ float bmaxz = max(p_st.z, p_en.z);
+#endif
+
+ if(xextrem[0] >= i_st && xextrem[0] <= i_en) {
+ bminx = min(bminx,xextrem[1]);
+ bmaxx = max(bmaxx,xextrem[1]);
+ }
+ if(xextrem[2] >= i_st && xextrem[2] <= i_en) {
+ bminx = min(bminx,xextrem[3]);
+ bmaxx = max(bmaxx,xextrem[3]);
+ }
+ if(yextrem[0] >= i_st && yextrem[0] <= i_en) {
+ bminy = min(bminy,yextrem[1]);
+ bmaxy = max(bmaxy,yextrem[1]);
+ }
+ if(yextrem[2] >= i_st && yextrem[2] <= i_en) {
+ bminy = min(bminy,yextrem[3]);
+ bmaxy = max(bmaxy,yextrem[3]);
+ }
+ if(zextrem[0] >= i_st && zextrem[0] <= i_en) {
+ bminz = min(bminz,zextrem[1]);
+ bmaxz = max(bmaxz,zextrem[1]);
+ }
+ if(zextrem[2] >= i_st && zextrem[2] <= i_en) {
+ bminz = min(bminz,zextrem[3]);
+ bmaxz = max(bmaxz,zextrem[3]);
+ }
+
+ float r1 = r_st + (r_en - r_st) * i_st;
+ float r2 = r_st + (r_en - r_st) * i_en;
+ r_curr = max(r1, r2);
+
+ mw_extension = min(difl * fabsf(bmaxz), extmax);
+ float r_ext = mw_extension + r_curr;
+ float coverage = 1.0f;
+
+ if(bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext|| bmaxx < -r_ext|| bminy > r_ext|| bmaxy < -r_ext) {
+ /* the bounding box does not overlap the square centered at O */
+ tree += level;
+ level = tree & -tree;
+ }
+ else if(level == 1) {
+
+ /* the maximum recursion depth is reached.
+ * check if dP0.(Q-P0)>=0 and dPn.(Pn-Q)>=0.
+ * dP* is reversed if necessary.*/
+ float t = isect->t;
+ float u = 0.0f;
+ float gd = 0.0f;
+
+ if(flags & CURVE_KN_RIBBONS) {
+ float3 tg = (p_en - p_st);
+#ifdef __KERNEL_SSE__
+ const float3 tg_sq = tg * tg;
+ float w = tg_sq.x + tg_sq.y;
+#else
+ float w = tg.x * tg.x + tg.y * tg.y;
+#endif
+ if(w == 0) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+#ifdef __KERNEL_SSE__
+ const float3 p_sttg = p_st * tg;
+ w = -(p_sttg.x + p_sttg.y) / w;
+#else
+ w = -(p_st.x * tg.x + p_st.y * tg.y) / w;
+#endif
+ w = saturate(w);
+
+ /* compute u on the curve segment */
+ u = i_st * (1 - w) + i_en * w;
+ r_curr = r_st + (r_en - r_st) * u;
+ /* compare x-y distances */
+ float3 p_curr = ((curve_coef[3] * u + curve_coef[2]) * u + curve_coef[1]) * u + curve_coef[0];
+
+ float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
+ if(dot(tg, dp_st)< 0)
+ dp_st *= -1;
+ if(dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+ float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
+ if(dot(tg, dp_en) < 0)
+ dp_en *= -1;
+ if(dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ /* compute coverage */
+ float r_ext = r_curr;
+ coverage = 1.0f;
+ if(difl != 0.0f) {
+ mw_extension = min(difl * fabsf(bmaxz), extmax);
+ r_ext = mw_extension + r_curr;
+#ifdef __KERNEL_SSE__
+ const float3 p_curr_sq = p_curr * p_curr;
+ const float3 dxxx(_mm_sqrt_ss(_mm_hadd_ps(p_curr_sq.m128, p_curr_sq.m128)));
+ float d = dxxx.x;
+#else
+ float d = sqrtf(p_curr.x * p_curr.x + p_curr.y * p_curr.y);
+#endif
+ float d0 = d - r_curr;
+ float d1 = d + r_curr;
+ float inv_mw_extension = 1.0f/mw_extension;
+ if(d0 >= 0)
+ coverage = (min(d1 * inv_mw_extension, 1.0f) - min(d0 * inv_mw_extension, 1.0f)) * 0.5f;
+ else // inside
+ coverage = (min(d1 * inv_mw_extension, 1.0f) + min(-d0 * inv_mw_extension, 1.0f)) * 0.5f;
+ }
+
+ if(p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon || isect->t < p_curr.z) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ t = p_curr.z;
+
+ /* stochastic fade from minimum width */
+ if(difl != 0.0f && lcg_state) {
+ if(coverage != 1.0f && (lcg_step_float(lcg_state) > coverage))
+ return hit;
+ }
+ }
+ else {
+ float l = len(p_en - p_st);
+ /* minimum width extension */
+ float or1 = r1;
+ float or2 = r2;
+
+ if(difl != 0.0f) {
+ mw_extension = min(len(p_st - P) * difl, extmax);
+ or1 = r1 < mw_extension ? mw_extension : r1;
+ mw_extension = min(len(p_en - P) * difl, extmax);
+ or2 = r2 < mw_extension ? mw_extension : r2;
+ }
+ /* --- */
+ float invl = 1.0f/l;
+ float3 tg = (p_en - p_st) * invl;
+ gd = (or2 - or1) * invl;
+ float difz = -dot(p_st,tg);
+ float cyla = 1.0f - (tg.z * tg.z * (1 + gd*gd));
+ float invcyla = 1.0f/cyla;
+ float halfb = (-p_st.z - tg.z*(difz + gd*(difz*gd + or1)));
+ float tcentre = -halfb*invcyla;
+ float zcentre = difz + (tg.z * tcentre);
+ float3 tdif = - p_st;
+ tdif.z += tcentre;
+ float tdifz = dot(tdif,tg);
+ float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + or1)));
+ float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - or1*or1 - 2*or1*tdifz*gd;
+ float td = tb*tb - 4*cyla*tc;
+ if(td < 0.0f) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ float rootd = sqrtf(td);
+ float correction = (-tb - rootd) * 0.5f * invcyla;
+ t = tcentre + correction;
+
+ float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
+ if(dot(tg, dp_st)< 0)
+ dp_st *= -1;
+ float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
+ if(dot(tg, dp_en) < 0)
+ dp_en *= -1;
+
+ if(flags & CURVE_KN_BACKFACING && (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f)) {
+ correction = (-tb + rootd) * 0.5f * invcyla;
+ t = tcentre + correction;
+ }
+
+ if(dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ float w = (zcentre + (tg.z * correction)) * invl;
+ w = saturate(w);
+ /* compute u on the curve segment */
+ u = i_st * (1 - w) + i_en * w;
+
+ /* stochastic fade from minimum width */
+ if(difl != 0.0f && lcg_state) {
+ r_curr = r1 + (r2 - r1) * w;
+ r_ext = or1 + (or2 - or1) * w;
+ coverage = r_curr/r_ext;
+
+ if(coverage != 1.0f && (lcg_step_float(lcg_state) > coverage))
+ return hit;
+ }
+ }
+ /* we found a new intersection */
+
+#ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
+#endif
+ {
+ /* record intersection */
+ isect->t = t;
+ isect->u = u;
+ isect->v = gd;
+ isect->prim = curveAddr;
+ isect->object = object;
+ isect->type = type;
+ hit = true;
+ }
+
+ tree++;
+ level = tree & -tree;
+ }
+ else {
+ /* split the curve into two curves and process */
+ level = level >> 1;
+ }
+ }
+
+ return hit;
+}
+
+ccl_device_curveintersect bool curve_intersect(KernelGlobals *kg,
+ Intersection *isect,
+ float3 P,
+ float3 direction,
+ uint visibility,
+ int object,
+ int curveAddr,
+ float time,
+ int type,
+ uint *lcg_state,
+ float difl,
+ float extmax)
+{
+ /* define few macros to minimize code duplication for SSE */
+#ifndef __KERNEL_SSE2__
+# define len3_squared(x) len_squared(x)
+# define len3(x) len(x)
+# define dot3(x, y) dot(x, y)
+#endif
+
+ const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
+
+ if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
+ const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
+ if(time < prim_time.x || time > prim_time.y) {
+ return false;
+ }
+ }
+
+ int segment = PRIMITIVE_UNPACK_SEGMENT(type);
+ /* curve Intersection check */
+ int flags = kernel_data.curve.curveflags;
+
+ int prim = kernel_tex_fetch(__prim_index, curveAddr);
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int cnum = __float_as_int(v00.x);
+ int k0 = cnum + segment;
+ int k1 = k0 + 1;
+
+#ifndef __KERNEL_SSE2__
+ float4 P_curve[2];
+
+ if(is_curve_primitive) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
+ motion_curve_keys(kg, fobject, prim, time, k0, k1, P_curve);
+ }
+
+ float or1 = P_curve[0].w;
+ float or2 = P_curve[1].w;
+ float3 p1 = float4_to_float3(P_curve[0]);
+ float3 p2 = float4_to_float3(P_curve[1]);
+
+ /* minimum width extension */
+ float r1 = or1;
+ float r2 = or2;
+ float3 dif = P - p1;
+ float3 dif_second = P - p2;
+ if(difl != 0.0f) {
+ float pixelsize = min(len3(dif) * difl, extmax);
+ r1 = or1 < pixelsize ? pixelsize : or1;
+ pixelsize = min(len3(dif_second) * difl, extmax);
+ r2 = or2 < pixelsize ? pixelsize : or2;
+ }
+ /* --- */
+
+ float3 p21_diff = p2 - p1;
+ float3 sphere_dif1 = (dif + dif_second) * 0.5f;
+ float3 dir = direction;
+ float sphere_b_tmp = dot3(dir, sphere_dif1);
+ float3 sphere_dif2 = sphere_dif1 - sphere_b_tmp * dir;
+#else
+ ssef P_curve[2];
+
+ if(is_curve_primitive) {
+ P_curve[0] = load4f(&kg->__curve_keys.data[k0].x);
+ P_curve[1] = load4f(&kg->__curve_keys.data[k1].x);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
+ motion_curve_keys(kg, fobject, prim, time, k0, k1, (float4*)&P_curve);
+ }
+
+ const ssef or12 = shuffle<3, 3, 3, 3>(P_curve[0], P_curve[1]);
+
+ ssef r12 = or12;
+ const ssef vP = load4f(P);
+ const ssef dif = vP - P_curve[0];
+ const ssef dif_second = vP - P_curve[1];
+ if(difl != 0.0f) {
+ const ssef len1_sq = len3_squared_splat(dif);
+ const ssef len2_sq = len3_squared_splat(dif_second);
+ const ssef len12 = mm_sqrt(shuffle<0, 0, 0, 0>(len1_sq, len2_sq));
+ const ssef pixelsize12 = min(len12 * difl, ssef(extmax));
+ r12 = max(or12, pixelsize12);
+ }
+ float or1 = extract<0>(or12), or2 = extract<0>(shuffle<2>(or12));
+ float r1 = extract<0>(r12), r2 = extract<0>(shuffle<2>(r12));
+
+ const ssef p21_diff = P_curve[1] - P_curve[0];
+ const ssef sphere_dif1 = (dif + dif_second) * 0.5f;
+ const ssef dir = load4f(direction);
+ const ssef sphere_b_tmp = dot3_splat(dir, sphere_dif1);
+ const ssef sphere_dif2 = nmadd(sphere_b_tmp, dir, sphere_dif1);
+#endif
+
+ float mr = max(r1, r2);
+ float l = len3(p21_diff);
+ float invl = 1.0f / l;
+ float sp_r = mr + 0.5f * l;
+
+ float sphere_b = dot3(dir, sphere_dif2);
+ float sdisc = sphere_b * sphere_b - len3_squared(sphere_dif2) + sp_r * sp_r;
+
+ if(sdisc < 0.0f)
+ return false;
+
+ /* obtain parameters and test midpoint distance for suitable modes */
+#ifndef __KERNEL_SSE2__
+ float3 tg = p21_diff * invl;
+#else
+ const ssef tg = p21_diff * invl;
+#endif
+ float gd = (r2 - r1) * invl;
+
+ float dirz = dot3(dir, tg);
+ float difz = dot3(dif, tg);
+
+ float a = 1.0f - (dirz*dirz*(1 + gd*gd));
+
+ float halfb = dot3(dir, dif) - dirz*(difz + gd*(difz*gd + r1));
+
+ float tcentre = -halfb/a;
+ float zcentre = difz + (dirz * tcentre);
+
+ if((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE))
+ return false;
+ if((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) && !(flags & CURVE_KN_INTERSECTCORRECTION))
+ return false;
+
+ /* test minimum separation */
+#ifndef __KERNEL_SSE2__
+ float3 cprod = cross(tg, dir);
+ float cprod2sq = len3_squared(cross(tg, dif));
+#else
+ const ssef cprod = cross(tg, dir);
+ float cprod2sq = len3_squared(cross_zxy(tg, dif));
+#endif
+ float cprodsq = len3_squared(cprod);
+ float distscaled = dot3(cprod, dif);
+
+ if(cprodsq == 0)
+ distscaled = cprod2sq;
+ else
+ distscaled = (distscaled*distscaled)/cprodsq;
+
+ if(distscaled > mr*mr)
+ return false;
+
+ /* calculate true intersection */
+#ifndef __KERNEL_SSE2__
+ float3 tdif = dif + tcentre * dir;
+#else
+ const ssef tdif = madd(ssef(tcentre), dir, dif);
+#endif
+ float tdifz = dot3(tdif, tg);
+ float tdifma = tdifz*gd + r1;
+ float tb = 2*(dot3(dir, tdif) - dirz*(tdifz + gd*tdifma));
+ float tc = dot3(tdif, tdif) - tdifz*tdifz - tdifma*tdifma;
+ float td = tb*tb - 4*a*tc;
+
+ if(td < 0.0f)
+ return false;
+
+ float rootd = 0.0f;
+ float correction = 0.0f;
+ if(flags & CURVE_KN_ACCURATE) {
+ rootd = sqrtf(td);
+ correction = ((-tb - rootd)/(2*a));
+ }
+
+ float t = tcentre + correction;
+
+ if(t < isect->t) {
+
+ if(flags & CURVE_KN_INTERSECTCORRECTION) {
+ rootd = sqrtf(td);
+ correction = ((-tb - rootd)/(2*a));
+ t = tcentre + correction;
+ }
+
+ float z = zcentre + (dirz * correction);
+ // bool backface = false;
+
+ if(flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) {
+ // backface = true;
+ correction = ((-tb + rootd)/(2*a));
+ t = tcentre + correction;
+ z = zcentre + (dirz * correction);
+ }
+
+ /* stochastic fade from minimum width */
+ float adjradius = or1 + z * (or2 - or1) * invl;
+ adjradius = adjradius / (r1 + z * gd);
+ if(lcg_state && adjradius != 1.0f) {
+ if(lcg_step_float(lcg_state) > adjradius)
+ return false;
+ }
+ /* --- */
+
+ if(t > 0.0f && t < isect->t && z >= 0 && z <= l) {
+
+ if(flags & CURVE_KN_ENCLOSEFILTER) {
+ float enc_ratio = 1.01f;
+ if((difz > -r1 * enc_ratio) && (dot3(dif_second, tg) < r2 * enc_ratio)) {
+ float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio));
+ float c2 = dot3(dif, dif) - difz * difz * (1 + gd*gd*enc_ratio*enc_ratio) - r1*r1*enc_ratio*enc_ratio - 2*r1*difz*gd*enc_ratio;
+ if(a2*c2 < 0.0f)
+ return false;
+ }
+ }
+
+#ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
+#endif
+ {
+ /* record intersection */
+ isect->t = t;
+ isect->u = z*invl;
+ isect->v = gd;
+ isect->prim = curveAddr;
+ isect->object = object;
+ isect->type = type;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+
+#ifndef __KERNEL_SSE2__
+# undef len3_squared
+# undef len3
+# undef dot3
+#endif
+}
+
+ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
+{
+ float fc = 0.71f;
+ float data[4];
+ float t2 = t * t;
+ data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
+ data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
+ data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
+ data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+}
+
+ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
+{
+ float data[4];
+ float fc = 0.71f;
+ float t2 = t * t;
+ float t3 = t2 * t;
+ data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
+ data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
+ data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
+ data[3] = fc * t3 - fc * t2;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+}
+
+ccl_device_inline float3 curve_refine(KernelGlobals *kg,
+ ShaderData *sd,
+ const Intersection *isect,
+ const Ray *ray)
+{
+ int flag = kernel_data.curve.curveflags;
+ float t = isect->t;
+ float3 P = ray->P;
+ float3 D = ray->D;
+
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_itfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D*t);
+ D = normalize_len(D, &t);
+ }
+
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k1 = k0 + 1;
+
+ float3 tg;
+
+ if(flag & CURVE_KN_INTERPOLATE) {
+ int ka = max(k0 - 1,__float_as_int(v00.x));
+ int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1);
+
+ float4 P_curve[4];
+
+ if(sd->type & PRIMITIVE_CURVE) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
+ P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ }
+ else {
+ motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
+ }
+
+ float3 p[4];
+ p[0] = float4_to_float3(P_curve[0]);
+ p[1] = float4_to_float3(P_curve[1]);
+ p[2] = float4_to_float3(P_curve[2]);
+ p[3] = float4_to_float3(P_curve[3]);
+
+ P = P + D*t;
+
+#ifdef __UV__
+ sd->u = isect->u;
+ sd->v = 0.0f;
+#endif
+
+ tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3]));
+
+ if(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) {
+ sd->Ng = normalize(-(D - tg * (dot(tg, D))));
+ }
+ else {
+ /* direction from inside to surface of curve */
+ float3 p_curr = curvepoint(isect->u, p[0], p[1], p[2], p[3]);
+ sd->Ng = normalize(P - p_curr);
+
+ /* adjustment for changing radius */
+ float gd = isect->v;
+
+ if(gd != 0.0f) {
+ sd->Ng = sd->Ng - gd * tg;
+ sd->Ng = normalize(sd->Ng);
+ }
+ }
+
+ /* todo: sometimes the normal is still so that this is detected as
+ * backfacing even if cull backfaces is enabled */
+
+ sd->N = sd->Ng;
+ }
+ else {
+ float4 P_curve[2];
+
+ if(sd->type & PRIMITIVE_CURVE) {
+ P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
+ }
+
+ float l = 1.0f;
+ tg = normalize_len(float4_to_float3(P_curve[1] - P_curve[0]), &l);
+
+ P = P + D*t;
+
+ float3 dif = P - float4_to_float3(P_curve[0]);
+
+#ifdef __UV__
+ sd->u = dot(dif,tg)/l;
+ sd->v = 0.0f;
+#endif
+
+ if(flag & CURVE_KN_TRUETANGENTGNORMAL) {
+ sd->Ng = -(D - tg * dot(tg, D));
+ sd->Ng = normalize(sd->Ng);
+ }
+ else {
+ float gd = isect->v;
+
+ /* direction from inside to surface of curve */
+ sd->Ng = (dif - tg * sd->u * l) / (P_curve[0].w + sd->u * l * gd);
+
+ /* adjustment for changing radius */
+ if(gd != 0.0f) {
+ sd->Ng = sd->Ng - gd * tg;
+ sd->Ng = normalize(sd->Ng);
+ }
+ }
+
+ sd->N = sd->Ng;
+ }
+
+#ifdef __DPDU__
+ /* dPdu/dPdv */
+ sd->dPdu = tg;
+ sd->dPdv = cross(tg, sd->Ng);
+#endif
+
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_tfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
+}
+
+#endif
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h
index 6ecdfe0173a..1ffc143be34 100644
--- a/intern/cycles/kernel/geom/geom_object.h
+++ b/intern/cycles/kernel/geom/geom_object.h
@@ -415,12 +415,7 @@ ccl_device_inline float3 bvh_clamp_direction(float3 dir)
ccl_device_inline float3 bvh_inverse_direction(float3 dir)
{
- /* TODO(sergey): Currently disabled, gives speedup but causes precision issues. */
-#if defined(__KERNEL_SSE__) && 0
return rcp(dir);
-#else
- return 1.0f / dir;
-#endif
}
/* Transform ray into object space to enter static object in BVH */
diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h
index 1e0ef5201c9..698cd6b03fd 100644
--- a/intern/cycles/kernel/geom/geom_volume.h
+++ b/intern/cycles/kernel/geom/geom_volume.h
@@ -35,10 +35,10 @@ ccl_device float4 volume_image_texture_3d(int id, float x, float y, float z)
float4 r;
switch(id) {
case 0: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_000, x, y, z); break;
- case 1: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_001, x, y, z); break;
- case 2: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_002, x, y, z); break;
- case 3: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_003, x, y, z); break;
- case 4: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_004, x, y, z); break;
+ case 8: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_008, x, y, z); break;
+ case 16: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_016, x, y, z); break;
+ case 24: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_024, x, y, z); break;
+ case 32: r = kernel_tex_image_interp_3d(__tex_image_float4_3d_032, x, y, z); break;
}
return r;
}
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 06728415c15..82d3c153bf5 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -21,6 +21,9 @@ CCL_NAMESPACE_BEGIN
* BSDF evaluation result, split per BSDF type. This is used to accumulate
* render passes separately. */
+ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg,
+ const ShaderData *sd);
+
ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 value, int use_light_pass)
{
#ifdef __PASSES__
@@ -205,6 +208,7 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
L->path_scatter = make_float3(0.0f, 0.0f, 0.0f);
+ L->transparent = 0.0f;
L->emission = make_float3(0.0f, 0.0f, 0.0f);
L->background = make_float3(0.0f, 0.0f, 0.0f);
L->ao = make_float3(0.0f, 0.0f, 0.0f);
@@ -214,20 +218,31 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
else
#endif
{
+ L->transparent = 0.0f;
L->emission = make_float3(0.0f, 0.0f, 0.0f);
}
#ifdef __SHADOW_TRICKS__
L->path_total = make_float3(0.0f, 0.0f, 0.0f);
L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f);
- L->shadow_color = make_float3(0.0f, 0.0f, 0.0f);
+ L->shadow_background_color = make_float3(0.0f, 0.0f, 0.0f);
+ L->shadow_radiance_sum = make_float3(0.0f, 0.0f, 0.0f);
+ L->shadow_throughput = 0.0f;
+ L->shadow_transparency = 1.0f;
#endif
#ifdef __DENOISING_FEATURES__
L->denoising_normal = make_float3(0.0f, 0.0f, 0.0f);
L->denoising_albedo = make_float3(0.0f, 0.0f, 0.0f);
L->denoising_depth = 0.0f;
-#endif /* __DENOISING_FEATURES__ */
+#endif
+
+#ifdef __KERNEL_DEBUG__
+ L->debug_data.num_bvh_traversed_nodes = 0;
+ L->debug_data.num_bvh_traversed_instances = 0;
+ L->debug_data.num_bvh_intersections = 0;
+ L->debug_data.num_ray_bounces = 0;
+#endif
}
ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput,
@@ -396,10 +411,11 @@ ccl_device_inline void path_radiance_accum_total_light(
#endif
}
-ccl_device_inline void path_radiance_accum_background(PathRadiance *L,
- ccl_addr_space PathState *state,
- float3 throughput,
- float3 value)
+ccl_device_inline void path_radiance_accum_background(
+ PathRadiance *L,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ float3 value)
{
#ifdef __PASSES__
if(L->use_light_pass) {
@@ -419,9 +435,7 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L,
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
L->path_total += throughput * value;
- if(state->flag & PATH_RAY_SHADOW_CATCHER_ONLY) {
- L->path_total_shaded += throughput * value;
- }
+ L->path_total_shaded += throughput * value * L->shadow_transparency;
}
#endif
@@ -621,25 +635,43 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
{
float fac = 1.0f/num_samples;
+#ifdef __SPLIT_KERNEL__
+# define safe_float3_add(f, v) \
+ do { \
+ ccl_global float *p = (ccl_global float*)(&(f)); \
+ atomic_add_and_fetch_float(p+0, (v).x); \
+ atomic_add_and_fetch_float(p+1, (v).y); \
+ atomic_add_and_fetch_float(p+2, (v).z); \
+ } while(0)
+#else
+# define safe_float3_add(f, v) (f) += (v)
+#endif /* __SPLIT_KERNEL__ */
+
#ifdef __PASSES__
- L->direct_diffuse += L_sample->direct_diffuse*fac;
- L->direct_glossy += L_sample->direct_glossy*fac;
- L->direct_transmission += L_sample->direct_transmission*fac;
- L->direct_subsurface += L_sample->direct_subsurface*fac;
- L->direct_scatter += L_sample->direct_scatter*fac;
-
- L->indirect_diffuse += L_sample->indirect_diffuse*fac;
- L->indirect_glossy += L_sample->indirect_glossy*fac;
- L->indirect_transmission += L_sample->indirect_transmission*fac;
- L->indirect_subsurface += L_sample->indirect_subsurface*fac;
- L->indirect_scatter += L_sample->indirect_scatter*fac;
-
- L->background += L_sample->background*fac;
- L->ao += L_sample->ao*fac;
- L->shadow += L_sample->shadow*fac;
+ safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse*fac);
+ safe_float3_add(L->direct_glossy, L_sample->direct_glossy*fac);
+ safe_float3_add(L->direct_transmission, L_sample->direct_transmission*fac);
+ safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface*fac);
+ safe_float3_add(L->direct_scatter, L_sample->direct_scatter*fac);
+
+ safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse*fac);
+ safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy*fac);
+ safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission*fac);
+ safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface*fac);
+ safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter*fac);
+
+ safe_float3_add(L->background, L_sample->background*fac);
+ safe_float3_add(L->ao, L_sample->ao*fac);
+ safe_float3_add(L->shadow, L_sample->shadow*fac);
+# ifdef __SPLIT_KERNEL__
+ atomic_add_and_fetch_float(&L->mist, L_sample->mist*fac);
+# else
L->mist += L_sample->mist*fac;
-#endif
- L->emission += L_sample->emission * fac;
+# endif /* __SPLIT_KERNEL__ */
+#endif /* __PASSES__ */
+ safe_float3_add(L->emission, L_sample->emission*fac);
+
+#undef safe_float3_add
}
#ifdef __SHADOW_TRICKS__
@@ -651,7 +683,7 @@ ccl_device_inline float path_radiance_sum_shadow(const PathRadiance *L)
if(path_total != 0.0f) {
return path_total_shaded / path_total;
}
- return 1.0f;
+ return L->shadow_transparency;
}
/* Calculate final light sum and transparency for shadow catcher object. */
@@ -662,11 +694,12 @@ ccl_device_inline float3 path_radiance_sum_shadowcatcher(KernelGlobals *kg,
const float shadow = path_radiance_sum_shadow(L);
float3 L_sum;
if(kernel_data.background.transparent) {
- *alpha = 1.0f-shadow;
- L_sum = make_float3(0.0f, 0.0f, 0.0f);
+ *alpha = 1.0f - L->shadow_throughput * shadow;
+ L_sum = L->shadow_radiance_sum;
}
else {
- L_sum = L->shadow_color * shadow;
+ L_sum = L->shadow_background_color * L->shadow_throughput * shadow +
+ L->shadow_radiance_sum;
}
return L_sum;
}
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index f18d145f7cf..8af1187213d 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void compute_light_pass(KernelGlobals *kg,
ShaderData *sd,
PathRadiance *L,
- RNG rng,
+ uint rng_hash,
int pass_filter,
int sample)
{
@@ -48,11 +48,11 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
path_radiance_init(&L_sample, kernel_data.film.use_light_pass);
/* init path state */
- path_state_init(kg, &emission_sd, &state, &rng, sample, NULL);
+ path_state_init(kg, &emission_sd, &state, rng_hash, sample, NULL);
/* evaluate surface shader */
- float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF);
- shader_eval_surface(kg, sd, &rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+ float rbsdf = path_state_rng_1D(kg, &state, PRNG_BSDF);
+ shader_eval_surface(kg, sd, &state, rbsdf, state.flag);
/* TODO, disable more closures we don't need besides transparent */
shader_bsdf_disable_transparency(kg, sd);
@@ -64,7 +64,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
/* sample ambient occlusion */
if(pass_filter & BAKE_FILTER_AO) {
- kernel_path_ao(kg, sd, &emission_sd, &L_sample, &state, &rng, throughput, shader_bsdf_alpha(kg, sd));
+ kernel_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput, shader_bsdf_alpha(kg, sd));
}
/* sample emission */
@@ -86,7 +86,6 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
&emission_sd,
&L_sample,
&state,
- &rng,
&ray,
&throughput,
&ss_indirect))
@@ -101,7 +100,6 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
kernel_path_indirect(kg,
&indirect_sd,
&emission_sd,
- &rng,
&ray,
throughput,
state.num_samples,
@@ -116,14 +114,14 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
/* sample light and BSDF */
if(!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
- kernel_path_surface_connect_light(kg, &rng, sd, &emission_sd, throughput, &state, &L_sample);
+ kernel_path_surface_connect_light(kg, sd, &emission_sd, throughput, &state, &L_sample);
- if(kernel_path_surface_bounce(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) {
+ if(kernel_path_surface_bounce(kg, sd, &throughput, &state, &L_sample, &ray)) {
#ifdef __LAMP_MIS__
state.ray_t = 0.0f;
#endif
/* compute indirect light */
- kernel_path_indirect(kg, &indirect_sd, &emission_sd, &rng, &ray, throughput, 1, &state, &L_sample);
+ kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, 1, &state, &L_sample);
/* sum and reset indirect light pass variables for the next samples */
path_radiance_sum_indirect(&L_sample);
@@ -137,7 +135,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
/* sample ambient occlusion */
if(pass_filter & BAKE_FILTER_AO) {
- kernel_branched_path_ao(kg, sd, &emission_sd, &L_sample, &state, &rng, throughput);
+ kernel_branched_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput);
}
/* sample emission */
@@ -151,7 +149,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
if((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
/* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
kernel_branched_path_subsurface_scatter(kg, sd, &indirect_sd,
- &emission_sd, &L_sample, &state, &rng, &ray, throughput);
+ &emission_sd, &L_sample, &state, &ray, throughput);
}
#endif
@@ -161,13 +159,13 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
/* direct light */
if(kernel_data.integrator.use_direct_light) {
int all = kernel_data.integrator.sample_all_lights_direct;
- kernel_branched_path_surface_connect_light(kg, &rng,
+ kernel_branched_path_surface_connect_light(kg,
sd, &emission_sd, &state, throughput, 1.0f, &L_sample, all);
}
#endif
/* indirect light */
- kernel_branched_path_surface_indirect_light(kg, &rng,
+ kernel_branched_path_surface_indirect_light(kg,
sd, &indirect_sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
}
}
@@ -225,7 +223,6 @@ ccl_device_inline float3 kernel_bake_shader_bsdf(KernelGlobals *kg,
ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
ShaderData *sd,
- RNG *rng,
PathState *state,
float3 direct,
float3 indirect,
@@ -245,12 +242,12 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
}
else {
/* surface color of the pass only */
- shader_eval_surface(kg, sd, rng, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, sd, state, 0.0f, 0);
return kernel_bake_shader_bsdf(kg, sd, type);
}
}
else {
- shader_eval_surface(kg, sd, rng, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, sd, state, 0.0f, 0);
color = kernel_bake_shader_bsdf(kg, sd, type);
}
@@ -292,14 +289,14 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
int num_samples = kernel_data.integrator.aa_samples;
/* random number generator */
- RNG rng = cmj_hash(offset + i, kernel_data.integrator.seed);
+ uint rng_hash = cmj_hash(offset + i, kernel_data.integrator.seed);
float filter_x, filter_y;
if(sample == 0) {
filter_x = filter_y = 0.5f;
}
else {
- path_rng_2D(kg, &rng, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
+ path_rng_2D(kg, rng_hash, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
}
/* subpixel u/v offset */
@@ -335,18 +332,18 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
/* light passes if we need more than color */
if(pass_filter & ~BAKE_FILTER_COLOR)
- compute_light_pass(kg, &sd, &L, rng, pass_filter, sample);
+ compute_light_pass(kg, &sd, &L, rng_hash, pass_filter, sample);
switch(type) {
/* data passes */
case SHADER_EVAL_NORMAL:
{
if((sd.flag & SD_HAS_BUMP)) {
- shader_eval_surface(kg, &sd, &rng, &state, 0.f, 0, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, &sd, &state, 0.f, 0);
}
- /* compression: normal = (2 * color) - 1 */
- out = sd.N * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
+ /* encoding: normal = (2 * color) - 1 */
+ out = shader_bsdf_average_normal(kg, &sd) * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
break;
}
case SHADER_EVAL_UV:
@@ -356,7 +353,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
}
case SHADER_EVAL_EMISSION:
{
- shader_eval_surface(kg, &sd, &rng, &state, 0.f, 0, SHADER_CONTEXT_EMISSION);
+ shader_eval_surface(kg, &sd, &state, 0.f, 0);
out = shader_emissive_eval(kg, &sd);
break;
}
@@ -409,7 +406,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
{
out = kernel_bake_evaluate_direct_indirect(kg,
&sd,
- &rng,
&state,
L.direct_diffuse,
L.indirect_diffuse,
@@ -421,7 +417,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
{
out = kernel_bake_evaluate_direct_indirect(kg,
&sd,
- &rng,
&state,
L.direct_glossy,
L.indirect_glossy,
@@ -433,7 +428,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
{
out = kernel_bake_evaluate_direct_indirect(kg,
&sd,
- &rng,
&state,
L.direct_transmission,
L.indirect_transmission,
@@ -446,7 +440,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
#ifdef __SUBSURFACE__
out = kernel_bake_evaluate_direct_indirect(kg,
&sd,
- &rng,
&state,
L.direct_subsurface,
L.indirect_subsurface,
@@ -480,7 +473,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
/* evaluate */
int flag = 0; /* we can't know which type of BSDF this is for */
- out = shader_eval_background(kg, &sd, &state, flag, SHADER_CONTEXT_MAIN);
+ out = shader_eval_background(kg, &sd, &state, flag);
break;
}
default:
@@ -524,7 +517,7 @@ ccl_device void kernel_shader_evaluate(KernelGlobals *kg,
/* evaluate */
float3 P = sd.P;
- shader_eval_displacement(kg, &sd, &state, SHADER_CONTEXT_MAIN);
+ shader_eval_displacement(kg, &sd, &state);
out = sd.P - P;
object_inverse_dir_transform(kg, &sd, &out);
@@ -552,7 +545,7 @@ ccl_device void kernel_shader_evaluate(KernelGlobals *kg,
/* evaluate */
int flag = 0; /* we can't know which type of BSDF this is for */
- out = shader_eval_background(kg, &sd, &state, flag, SHADER_CONTEXT_MAIN);
+ out = shader_eval_background(kg, &sd, &state, flag);
}
/* write output */
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index 38708f7ff0b..1e2af9de8b3 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -38,11 +38,15 @@
/* Qualifier wrappers for different names on different devices */
#define ccl_device __device__ __inline__
+#if __CUDA_ARCH__ < 300
+# define ccl_device_inline __device__ __inline__
# define ccl_device_forceinline __device__ __forceinline__
-#if __CUDA_ARCH__ < 500
+#elif __CUDA_ARCH__ < 500
# define ccl_device_inline __device__ __forceinline__
+# define ccl_device_forceinline __device__ __forceinline__
#else
# define ccl_device_inline __device__ __inline__
+# define ccl_device_forceinline __device__ __forceinline__
#endif
#define ccl_device_noinline __device__ __noinline__
#define ccl_global
@@ -53,6 +57,10 @@
#define ccl_may_alias
#define ccl_addr_space
#define ccl_restrict __restrict__
+/* TODO(sergey): In theory we might use references with CUDA, however
+ * performance impact yet to be investigated.
+ */
+#define ccl_ref
#define ccl_align(n) __align__(n)
#define ATTR_FALLTHROUGH
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index 4836c290312..36d6031d042 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -42,6 +42,7 @@
#define ccl_local_param __local
#define ccl_private __private
#define ccl_restrict restrict
+#define ccl_ref
#define ccl_align(n) __attribute__((aligned(n)))
#ifdef __SPLIT_KERNEL__
@@ -129,6 +130,7 @@
# define expf(x) native_exp(((float)(x)))
# define sqrtf(x) native_sqrt(((float)(x)))
# define logf(x) native_log(((float)(x)))
+# define rcp(x) native_recip(x)
#else
# define sinf(x) sin(((float)(x)))
# define cosf(x) cos(((float)(x)))
@@ -136,11 +138,12 @@
# define expf(x) exp(((float)(x)))
# define sqrtf(x) sqrt(((float)(x)))
# define logf(x) log(((float)(x)))
+# define rcp(x) recip(x))
#endif
/* data lookup defines */
#define kernel_data (*kg->data)
-#define kernel_tex_fetch(t, index) kg->t[index]
+#define kernel_tex_fetch(tex, index) ((ccl_global tex##_t*)(kg->buffers[kg->tex.buffer] + kg->tex.offset))[(index)]
/* define NULL */
#define NULL 0
diff --git a/intern/cycles/kernel/kernel_debug.h b/intern/cycles/kernel/kernel_debug.h
deleted file mode 100644
index 5647bbae5b5..00000000000
--- a/intern/cycles/kernel/kernel_debug.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2011-2014 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
-
-ccl_device_inline void debug_data_init(DebugData *debug_data)
-{
- debug_data->num_bvh_traversed_nodes = 0;
- debug_data->num_bvh_traversed_instances = 0;
- debug_data->num_bvh_intersections = 0;
- debug_data->num_ray_bounces = 0;
-}
-
-ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg,
- ccl_global float *buffer,
- ccl_addr_space PathState *state,
- DebugData *debug_data,
- int sample)
-{
- int flag = kernel_data.film.pass_flag;
- if(flag & PASS_BVH_TRAVERSED_NODES) {
- kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_nodes,
- sample,
- debug_data->num_bvh_traversed_nodes);
- }
- if(flag & PASS_BVH_TRAVERSED_INSTANCES) {
- kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_instances,
- sample,
- debug_data->num_bvh_traversed_instances);
- }
- if(flag & PASS_BVH_INTERSECTIONS) {
- kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_intersections,
- sample,
- debug_data->num_bvh_intersections);
- }
- if(flag & PASS_RAY_BOUNCES) {
- kernel_write_pass_float(buffer + kernel_data.film.pass_ray_bounces,
- sample,
- debug_data->num_ray_bounces);
- }
-}
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 9e7d51f23f5..48a8e53be33 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -46,7 +46,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
shader_setup_from_background(kg, emission_sd, &ray);
path_state_modify_bounce(state, true);
- eval = shader_eval_background(kg, emission_sd, state, 0, SHADER_CONTEXT_EMISSION);
+ eval = shader_eval_background(kg, emission_sd, state, 0);
path_state_modify_bounce(state, false);
}
else
@@ -72,7 +72,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
/* no path flag, we're evaluating this for all closures. that's weak but
* we'd have to do multiple evaluations otherwise */
path_state_modify_bounce(state, true);
- shader_eval_surface(kg, emission_sd, NULL, state, 0.0f, 0, SHADER_CONTEXT_EMISSION);
+ shader_eval_surface(kg, emission_sd, state, 0.0f, 0);
path_state_modify_bounce(state, false);
/* evaluate emissive closure */
@@ -216,7 +216,7 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
{
/* multiple importance sampling, get triangle light pdf,
* and compute weight with respect to BSDF pdf */
- float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
+ float pdf = triangle_light_pdf(kg, sd, t);
float mis_weight = power_heuristic(bsdf_pdf, pdf);
return L*mis_weight;
@@ -319,7 +319,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
# endif
path_state_modify_bounce(state, true);
- float3 L = shader_eval_background(kg, emission_sd, state, state->flag, SHADER_CONTEXT_EMISSION);
+ float3 L = shader_eval_background(kg, emission_sd, state, state->flag);
path_state_modify_bounce(state, false);
#ifdef __BACKGROUND_MIS__
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index f95f0d98c52..9d55183d94b 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -23,6 +23,10 @@
# include "util/util_vector.h"
#endif
+#ifdef __KERNEL_OPENCL__
+# include "util/util_atomic.h"
+#endif
+
CCL_NAMESPACE_BEGIN
/* On the CPU, we pass along the struct KernelGlobals to nearly everywhere in
@@ -109,11 +113,22 @@ typedef struct KernelGlobals {
#ifdef __KERNEL_OPENCL__
+# define KERNEL_TEX(type, ttype, name) \
+typedef type name##_t;
+# include "kernel/kernel_textures.h"
+
+typedef struct tex_info_t {
+ uint buffer, padding;
+ uint64_t offset;
+ uint width, height, depth, options;
+} tex_info_t;
+
typedef ccl_addr_space struct KernelGlobals {
ccl_constant KernelData *data;
+ ccl_global char *buffers[8];
# define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name;
+ tex_info_t name;
# include "kernel/kernel_textures.h"
# ifdef __SPLIT_KERNEL__
@@ -122,6 +137,57 @@ typedef ccl_addr_space struct KernelGlobals {
# endif
} KernelGlobals;
+#define KERNEL_BUFFER_PARAMS \
+ ccl_global char *buffer0, \
+ ccl_global char *buffer1, \
+ ccl_global char *buffer2, \
+ ccl_global char *buffer3, \
+ ccl_global char *buffer4, \
+ ccl_global char *buffer5, \
+ ccl_global char *buffer6, \
+ ccl_global char *buffer7
+
+#define KERNEL_BUFFER_ARGS buffer0, buffer1, buffer2, buffer3, buffer4, buffer5, buffer6, buffer7
+
+ccl_device_inline void kernel_set_buffer_pointers(KernelGlobals *kg, KERNEL_BUFFER_PARAMS)
+{
+#ifdef __SPLIT_KERNEL__
+ if(ccl_local_id(0) + ccl_local_id(1) == 0)
+#endif
+ {
+ kg->buffers[0] = buffer0;
+ kg->buffers[1] = buffer1;
+ kg->buffers[2] = buffer2;
+ kg->buffers[3] = buffer3;
+ kg->buffers[4] = buffer4;
+ kg->buffers[5] = buffer5;
+ kg->buffers[6] = buffer6;
+ kg->buffers[7] = buffer7;
+ }
+
+# ifdef __SPLIT_KERNEL__
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+# endif
+}
+
+ccl_device_inline void kernel_set_buffer_info(KernelGlobals *kg)
+{
+# ifdef __SPLIT_KERNEL__
+ if(ccl_local_id(0) + ccl_local_id(1) == 0)
+# endif
+ {
+ ccl_global tex_info_t *info = (ccl_global tex_info_t*)kg->buffers[0];
+
+# define KERNEL_TEX(type, ttype, name) \
+ kg->name = *(info++);
+# include "kernel/kernel_textures.h"
+ }
+
+# ifdef __SPLIT_KERNEL__
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+# endif
+}
+
#endif /* __KERNEL_OPENCL__ */
/* Interpolated lookup table access */
diff --git a/intern/cycles/kernel/kernel_image_opencl.h b/intern/cycles/kernel/kernel_image_opencl.h
index 90747e09357..9e3373432ec 100644
--- a/intern/cycles/kernel/kernel_image_opencl.h
+++ b/intern/cycles/kernel/kernel_image_opencl.h
@@ -15,30 +15,42 @@
*/
-/* For OpenCL all images are packed in a single array, and we do manual lookup
- * and interpolation. */
+/* For OpenCL we do manual lookup and interpolation. */
+
+ccl_device_inline ccl_global tex_info_t* kernel_tex_info(KernelGlobals *kg, uint id) {
+ const uint tex_offset = id
+#define KERNEL_TEX(type, ttype, name) + 1
+#include "kernel/kernel_textures.h"
+ ;
+
+ return &((ccl_global tex_info_t*)kg->buffers[0])[tex_offset];
+}
+
+#define tex_fetch(type, info, index) ((ccl_global type*)(kg->buffers[info->buffer] + info->offset))[(index)]
ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg, int id, int offset)
{
+ const ccl_global tex_info_t *info = kernel_tex_info(kg, id);
const int texture_type = kernel_tex_type(id);
+
/* Float4 */
if(texture_type == IMAGE_DATA_TYPE_FLOAT4) {
- return kernel_tex_fetch(__tex_image_float4_packed, offset);
+ return tex_fetch(float4, info, offset);
}
/* Byte4 */
else if(texture_type == IMAGE_DATA_TYPE_BYTE4) {
- uchar4 r = kernel_tex_fetch(__tex_image_byte4_packed, offset);
+ uchar4 r = tex_fetch(uchar4, info, 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(texture_type == IMAGE_DATA_TYPE_FLOAT) {
- float f = kernel_tex_fetch(__tex_image_float_packed, offset);
+ float f = tex_fetch(float, info, offset);
return make_float4(f, f, f, 1.0f);
}
/* Byte */
else {
- uchar r = kernel_tex_fetch(__tex_image_byte_packed, offset);
+ uchar r = tex_fetch(uchar, info, offset);
float f = r * (1.0f/255.0f);
return make_float4(f, f, f, 1.0f);
}
@@ -64,17 +76,17 @@ ccl_device_inline float svm_image_texture_frac(float x, int *ix)
return x - (float)i;
}
-ccl_device_inline uint kernel_decode_image_interpolation(uint4 info)
+ccl_device_inline uint kernel_decode_image_interpolation(uint info)
{
- return (info.w & (1 << 0)) ? INTERPOLATION_CLOSEST : INTERPOLATION_LINEAR;
+ return (info & (1 << 0)) ? INTERPOLATION_CLOSEST : INTERPOLATION_LINEAR;
}
-ccl_device_inline uint kernel_decode_image_extension(uint4 info)
+ccl_device_inline uint kernel_decode_image_extension(uint info)
{
- if(info.w & (1 << 1)) {
+ if(info & (1 << 1)) {
return EXTENSION_REPEAT;
}
- else if(info.w & (1 << 2)) {
+ else if(info & (1 << 2)) {
return EXTENSION_EXTEND;
}
else {
@@ -84,13 +96,16 @@ ccl_device_inline uint kernel_decode_image_extension(uint4 info)
ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y)
{
- uint4 info = kernel_tex_fetch(__tex_image_packed_info, id*2);
- uint width = info.x;
- uint height = info.y;
- uint offset = info.z;
+ const ccl_global tex_info_t *info = kernel_tex_info(kg, id);
+
+ uint width = info->width;
+ uint height = info->height;
+ uint offset = 0;
+
/* Decode image options. */
- uint interpolation = kernel_decode_image_interpolation(info);
- uint extension = kernel_decode_image_extension(info);
+ uint interpolation = kernel_decode_image_interpolation(info->options);
+ uint extension = kernel_decode_image_extension(info->options);
+
/* Actual sampling. */
float4 r;
int ix, iy, nix, niy;
@@ -150,14 +165,17 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl
ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, float y, float z)
{
- uint4 info = kernel_tex_fetch(__tex_image_packed_info, id*2);
- uint width = info.x;
- uint height = info.y;
- uint offset = info.z;
- uint depth = kernel_tex_fetch(__tex_image_packed_info, id*2+1).x;
+ const ccl_global tex_info_t *info = kernel_tex_info(kg, id);
+
+ uint width = info->width;
+ uint height = info->height;
+ uint offset = 0;
+ uint depth = info->depth;
+
/* Decode image options. */
- uint interpolation = kernel_decode_image_interpolation(info);
- uint extension = kernel_decode_image_extension(info);
+ uint interpolation = kernel_decode_image_interpolation(info->options);
+ uint extension = kernel_decode_image_extension(info->options);
+
/* Actual sampling. */
float4 r;
int ix, iy, iz, nix, niy, niz;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 9baa9d54957..59db6cbd430 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -763,60 +763,252 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D,
/* Triangle Light */
-ccl_device void object_transform_light_sample(KernelGlobals *kg, LightSample *ls, int object, float time)
+/* returns true if the triangle is has motion blur or an instancing transform applied */
+ccl_device_inline bool triangle_world_space_vertices(KernelGlobals *kg, int object, int prim, float time, float3 V[3])
{
+ bool has_motion = false;
+ const int object_flag = kernel_tex_fetch(__object_flag, object);
+
+ if(object_flag & SD_OBJECT_HAS_VERTEX_MOTION && time >= 0.0f) {
+ motion_triangle_vertices(kg, object, prim, time, V);
+ has_motion = true;
+ } else {
+ triangle_vertices(kg, prim, V);
+ }
+
#ifdef __INSTANCING__
- /* instance transform */
- if(!(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED)) {
+ if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
# ifdef __OBJECT_MOTION__
- Transform itfm;
- Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm);
+ Transform tfm = object_fetch_transform_motion_test(kg, object, time, NULL);
# else
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
# endif
-
- ls->P = transform_point(&tfm, ls->P);
- ls->Ng = normalize(transform_direction(&tfm, ls->Ng));
+ V[0] = transform_point(&tfm, V[0]);
+ V[1] = transform_point(&tfm, V[1]);
+ V[2] = transform_point(&tfm, V[2]);
+ has_motion = true;
}
#endif
+ return has_motion;
}
-ccl_device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
- float randu, float randv, float time, LightSample *ls)
+ccl_device_inline float triangle_light_pdf_area(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
{
- float u, v;
+ float pdf = kernel_data.integrator.pdf_triangles;
+ float cos_pi = fabsf(dot(Ng, I));
- /* compute random point in triangle */
- randu = sqrtf(randu);
+ if(cos_pi == 0.0f)
+ return 0.0f;
- u = 1.0f - randu;
- v = randv*randu;
+ return t*t*pdf/cos_pi;
+}
- /* triangle, so get position, normal, shader */
- triangle_point_normal(kg, object, prim, u, v, &ls->P, &ls->Ng, &ls->shader);
+ccl_device_forceinline float triangle_light_pdf(KernelGlobals *kg, ShaderData *sd, float t)
+{
+ /* A naive heuristic to decide between costly solid angle sampling
+ * and simple area sampling, comparing the distance to the triangle plane
+ * to the length of the edges of the triangle. */
+
+ float3 V[3];
+ bool has_motion = triangle_world_space_vertices(kg, sd->object, sd->prim, sd->time, V);
+
+ const float3 e0 = V[1] - V[0];
+ const float3 e1 = V[2] - V[0];
+ const float3 e2 = V[2] - V[1];
+ const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
+ const float3 N = cross(e0, e1);
+ const float distance_to_plane = fabsf(dot(N, sd->I * t))/dot(N, N);
+
+ if(longest_edge_squared > distance_to_plane*distance_to_plane) {
+ /* sd contains the point on the light source
+ * calculate Px, the point that we're shading */
+ const float3 Px = sd->P + sd->I * t;
+ const float3 v0_p = V[0] - Px;
+ const float3 v1_p = V[1] - Px;
+ const float3 v2_p = V[2] - Px;
+
+ const float3 u01 = safe_normalize(cross(v0_p, v1_p));
+ const float3 u02 = safe_normalize(cross(v0_p, v2_p));
+ const float3 u12 = safe_normalize(cross(v1_p, v2_p));
+
+ const float alpha = fast_acosf(dot(u02, u01));
+ const float beta = fast_acosf(-dot(u01, u12));
+ const float gamma = fast_acosf(dot(u02, u12));
+ const float solid_angle = alpha + beta + gamma - M_PI_F;
+
+ /* pdf_triangles is calculated over triangle area, but we're not sampling over its area */
+ if(UNLIKELY(solid_angle == 0.0f)) {
+ return 0.0f;
+ } else {
+ float area = 1.0f;
+ if(has_motion) {
+ /* get the center frame vertices, this is what the PDF was calculated from */
+ triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
+ area = triangle_area(V[0], V[1], V[2]);
+ } else {
+ area = 0.5f * len(N);
+ }
+ const float pdf = area * kernel_data.integrator.pdf_triangles;
+ return pdf / solid_angle;
+ }
+ }
+ else {
+ float pdf = triangle_light_pdf_area(kg, sd->Ng, sd->I, t);
+ if(has_motion) {
+ const float area = 0.5f * len(N);
+ if(UNLIKELY(area == 0.0f)) {
+ return 0.0f;
+ }
+ /* scale the PDF.
+ * area = the area the sample was taken from
+ * area_pre = the are from which pdf_triangles was calculated from */
+ triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
+ const float area_pre = triangle_area(V[0], V[1], V[2]);
+ pdf = pdf * area_pre / area;
+ }
+ return pdf;
+ }
+}
+
+ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg, int prim, int object,
+ float randu, float randv, float time, LightSample *ls, const float3 P)
+{
+ /* A naive heuristic to decide between costly solid angle sampling
+ * and simple area sampling, comparing the distance to the triangle plane
+ * to the length of the edges of the triangle. */
+
+ float3 V[3];
+ bool has_motion = triangle_world_space_vertices(kg, object, prim, time, V);
+
+ const float3 e0 = V[1] - V[0];
+ const float3 e1 = V[2] - V[0];
+ const float3 e2 = V[2] - V[1];
+ const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
+ const float3 N0 = cross(e0, e1);
+ float Nl = 0.0f;
+ ls->Ng = safe_normalize_len(N0, &Nl);
+ float area = 0.5f * Nl;
+
+ /* flip normal if necessary */
+ const int object_flag = kernel_tex_fetch(__object_flag, object);
+ if(object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
+ ls->Ng = -ls->Ng;
+ }
+ ls->eval_fac = 1.0f;
+ ls->shader = kernel_tex_fetch(__tri_shader, prim);
ls->object = object;
ls->prim = prim;
ls->lamp = LAMP_NONE;
ls->shader |= SHADER_USE_MIS;
- ls->t = 0.0f;
- ls->u = u;
- ls->v = v;
ls->type = LIGHT_TRIANGLE;
- ls->eval_fac = 1.0f;
- object_transform_light_sample(kg, ls, object, time);
-}
+ float distance_to_plane = fabsf(dot(N0, V[0] - P)/dot(N0, N0));
+
+ if(longest_edge_squared > distance_to_plane*distance_to_plane) {
+ /* see James Arvo, "Stratified Sampling of Spherical Triangles"
+ * http://www.graphics.cornell.edu/pubs/1995/Arv95c.pdf */
+
+ /* project the triangle to the unit sphere
+ * and calculate its edges and angles */
+ const float3 v0_p = V[0] - P;
+ const float3 v1_p = V[1] - P;
+ const float3 v2_p = V[2] - P;
+
+ const float3 u01 = safe_normalize(cross(v0_p, v1_p));
+ const float3 u02 = safe_normalize(cross(v0_p, v2_p));
+ const float3 u12 = safe_normalize(cross(v1_p, v2_p));
+
+ const float3 A = safe_normalize(v0_p);
+ const float3 B = safe_normalize(v1_p);
+ const float3 C = safe_normalize(v2_p);
+
+ const float cos_alpha = dot(u02, u01);
+ const float cos_beta = -dot(u01, u12);
+ const float cos_gamma = dot(u02, u12);
+
+ /* calculate dihedral angles */
+ const float alpha = fast_acosf(cos_alpha);
+ const float beta = fast_acosf(cos_beta);
+ const float gamma = fast_acosf(cos_gamma);
+ /* the area of the unit spherical triangle = solid angle */
+ const float solid_angle = alpha + beta + gamma - M_PI_F;
+
+ /* precompute a few things
+ * these could be re-used to take several samples
+ * as they are independent of randu/randv */
+ const float cos_c = dot(A, B);
+ const float sin_alpha = fast_sinf(alpha);
+ const float product = sin_alpha * cos_c;
+
+ /* Select a random sub-area of the spherical triangle
+ * and calculate the third vertex C_ of that new triangle */
+ const float phi = randu * solid_angle - alpha;
+ float s, t;
+ fast_sincosf(phi, &s, &t);
+ const float u = t - cos_alpha;
+ const float v = s + product;
+
+ const float3 U = safe_normalize(C - dot(C, A) * A);
+
+ float q = 1.0f;
+ const float det = ((v * s + u * t) * sin_alpha);
+ if(det != 0.0f) {
+ q = ((v * t - u * s) * cos_alpha - v) / det;
+ }
+ const float temp = max(1.0f - q*q, 0.0f);
-ccl_device float triangle_light_pdf(KernelGlobals *kg,
- const float3 Ng, const float3 I, float t)
-{
- float pdf = kernel_data.integrator.pdf_triangles;
- float cos_pi = fabsf(dot(Ng, I));
+ const float3 C_ = safe_normalize(q * A + sqrtf(temp) * U);
- if(cos_pi == 0.0f)
- return 0.0f;
-
- return t*t*pdf/cos_pi;
+ /* Finally, select a random point along the edge of the new triangle
+ * That point on the spherical triangle is the sampled ray direction */
+ const float z = 1.0f - randv * (1.0f - dot(C_, B));
+ ls->D = z * B + safe_sqrtf(1.0f - z*z) * safe_normalize(C_ - dot(C_, B) * B);
+
+ /* calculate intersection with the planar triangle */
+ ray_triangle_intersect(P, ls->D, FLT_MAX,
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ (ssef*)V,
+#else
+ V[0], V[1], V[2],
+#endif
+ &ls->u, &ls->v, &ls->t);
+ ls->P = P + ls->D * ls->t;
+
+ /* pdf_triangles is calculated over triangle area, but we're sampling over solid angle */
+ if(UNLIKELY(solid_angle == 0.0f)) {
+ ls->pdf = 0.0f;
+ } else {
+ if(has_motion) {
+ /* get the center frame vertices, this is what the PDF was calculated from */
+ triangle_world_space_vertices(kg, object, prim, -1.0f, V);
+ area = triangle_area(V[0], V[1], V[2]);
+ }
+ const float pdf = area * kernel_data.integrator.pdf_triangles;
+ ls->pdf = pdf / solid_angle;
+ }
+ }
+ else {
+ /* compute random point in triangle */
+ randu = sqrtf(randu);
+
+ const float u = 1.0f - randu;
+ const float v = randv*randu;
+ const float t = 1.0f - u - v;
+ ls->P = u * V[0] + v * V[1] + t * V[2];
+ /* compute incoming direction, distance and pdf */
+ ls->D = normalize_len(ls->P - P, &ls->t);
+ ls->pdf = triangle_light_pdf_area(kg, ls->Ng, -ls->D, ls->t);
+ if(has_motion && area != 0.0f) {
+ /* scale the PDF.
+ * area = the area the sample was taken from
+ * area_pre = the are from which pdf_triangles was calculated from */
+ triangle_world_space_vertices(kg, object, prim, -1.0f, V);
+ const float area_pre = triangle_area(V[0], V[1], V[2]);
+ ls->pdf = ls->pdf * area_pre / area;
+ }
+ ls->u = u;
+ ls->v = v;
+ }
}
/* Light Distribution */
@@ -876,10 +1068,7 @@ ccl_device_noinline bool light_sample(KernelGlobals *kg,
int object = __float_as_int(l.w);
int shader_flag = __float_as_int(l.z);
- triangle_light_sample(kg, prim, object, randu, randv, time, ls);
- /* compute incoming direction, distance and pdf */
- ls->D = normalize_len(ls->P - P, &ls->t);
- ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t);
+ triangle_light_sample(kg, prim, object, randu, randv, time, ls, P);
ls->shader |= shader_flag;
return (ls->pdf > 0.0f);
}
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index 9d52834ffcc..d454cce6e30 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -142,7 +142,7 @@ ccl_device_inline void kernel_write_denoising_shadow(KernelGlobals *kg, ccl_glob
ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
ShaderData *sd,
- ccl_global PathState *state,
+ ccl_addr_space PathState *state,
PathRadiance *L)
{
#ifdef __DENOISING_FEATURES__
@@ -194,6 +194,36 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
#endif /* __DENOISING_FEATURES__ */
}
+#ifdef __KERNEL_DEBUG__
+ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg,
+ ccl_global float *buffer,
+ PathRadiance *L,
+ int sample)
+{
+ int flag = kernel_data.film.pass_flag;
+ if(flag & PASS_BVH_TRAVERSED_NODES) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_nodes,
+ sample,
+ L->debug_data.num_bvh_traversed_nodes);
+ }
+ if(flag & PASS_BVH_TRAVERSED_INSTANCES) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_instances,
+ sample,
+ L->debug_data.num_bvh_traversed_instances);
+ }
+ if(flag & PASS_BVH_INTERSECTIONS) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_intersections,
+ sample,
+ L->debug_data.num_bvh_intersections);
+ }
+ if(flag & PASS_RAY_BOUNCES) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_ray_bounces,
+ sample,
+ L->debug_data.num_ray_bounces);
+ }
+}
+#endif /* __KERNEL_DEBUG__ */
+
ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L,
ShaderData *sd, int sample, ccl_addr_space PathState *state, float3 throughput)
{
@@ -230,7 +260,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
}
if(flag & PASS_NORMAL) {
- float3 normal = sd->N;
+ float3 normal = shader_bsdf_average_normal(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
@@ -334,10 +364,12 @@ ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, ccl_global f
}
ccl_device_inline void kernel_write_result(KernelGlobals *kg, ccl_global float *buffer,
- int sample, PathRadiance *L, float alpha, bool is_shadow_catcher)
+ int sample, PathRadiance *L, bool is_shadow_catcher)
{
if(L) {
float3 L_sum;
+ float alpha = 1.0f - L->transparent;
+
#ifdef __SHADOW_TRICKS__
if(is_shadow_catcher) {
L_sum = path_radiance_sum_shadowcatcher(kg, L, &alpha);
@@ -389,6 +421,11 @@ ccl_device_inline void kernel_write_result(KernelGlobals *kg, ccl_global float *
sample, L->denoising_depth);
}
#endif /* __DENOISING_FEATURES__ */
+
+
+#ifdef __KERNEL_DEBUG__
+ kernel_write_debug_passes(kg, buffer, L, sample);
+#endif
}
else {
kernel_write_pass_float4(buffer, sample, make_float4(0.0f, 0.0f, 0.0f, 0.0f));
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index fc093ad8319..3319e2c2435 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -48,10 +48,6 @@
#include "kernel/kernel_path_volume.h"
#include "kernel/kernel_path_subsurface.h"
-#ifdef __KERNEL_DEBUG__
-# include "kernel/kernel_debug.h"
-#endif
-
CCL_NAMESPACE_BEGIN
ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
@@ -59,14 +55,13 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
ShaderData *emission_sd,
PathRadiance *L,
ccl_addr_space PathState *state,
- RNG *rng,
float3 throughput,
float3 ao_alpha)
{
/* todo: solve correlation */
float bsdf_u, bsdf_v;
- path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float ao_factor = kernel_data.background.ao_factor;
float3 ao_N;
@@ -89,7 +84,7 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
light_ray.dP = sd->dP;
light_ray.dD = differential3_zero();
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &ao_shadow)) {
path_radiance_accum_ao(L, state, throughput, ao_alpha, ao_bsdf, ao_shadow);
}
else {
@@ -100,10 +95,11 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
#ifndef __SPLIT_KERNEL__
+#if defined(__BRANCHED_PATH__) || defined(__BAKING__)
+
ccl_device void kernel_path_indirect(KernelGlobals *kg,
ShaderData *sd,
ShaderData *emission_sd,
- RNG *rng,
Ray *ray,
float3 throughput,
int num_samples,
@@ -202,7 +198,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* direct light sampling */
kernel_branched_path_volume_connect_light(kg,
- rng,
sd,
emission_sd,
throughput,
@@ -215,8 +210,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* indirect sample. if we use distance sampling and take just
* one sample for direct and indirect light, we could share
* this computation, but makes code a bit complex */
- float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
- float rscatter = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
+ float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE);
+ float rscatter = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE);
result = kernel_volume_decoupled_scatter(kg,
state,
@@ -235,7 +230,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
if(result == VOLUME_PATH_SCATTERED) {
if(kernel_path_volume_bounce(kg,
- rng,
sd,
&throughput,
state,
@@ -257,13 +251,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
{
/* integrate along volume segment with distance sampling */
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, state, sd, &volume_ray, L, &throughput, rng, heterogeneous);
+ kg, state, sd, &volume_ray, L, &throughput, heterogeneous);
# ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
kernel_path_volume_connect_light(kg,
- rng,
sd,
emission_sd,
throughput,
@@ -272,7 +265,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* indirect light bounce */
if(kernel_path_volume_bounce(kg,
- rng,
sd,
&throughput,
state,
@@ -311,15 +303,19 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
sd,
&isect,
ray);
- float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
- shader_eval_surface(kg, sd, rng, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
+ float rbsdf = path_state_rng_1D_for_decision(kg, state, PRNG_BSDF);
+ shader_eval_surface(kg, sd, state, rbsdf, state->flag);
#ifdef __BRANCHED_PATH__
shader_merge_closures(sd);
#endif /* __BRANCHED_PATH__ */
#ifdef __SHADOW_TRICKS__
- if(!(sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
- state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ if(!(sd->object_flag & SD_OBJECT_SHADOW_CATCHER) &&
+ (state->flag & PATH_RAY_SHADOW_CATCHER))
+ {
+ /* Only update transparency after shadow catcher bounce. */
+ L->shadow_transparency *=
+ average(shader_bsdf_transparency(kg, sd));
}
#endif /* __SHADOW_TRICKS__ */
@@ -350,7 +346,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
* mainly due to the mixed in MIS that we use. gives too many unneeded
* shader evaluations, only need emission if we are going to terminate */
float probability =
- path_state_terminate_probability(kg,
+ path_state_continuation_probability(kg,
state,
throughput*num_samples);
@@ -358,7 +354,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
break;
}
else if(probability != 1.0f) {
- float terminate = path_state_rng_1D_for_decision(kg, rng, state, PRNG_TERMINATE);
+ float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE);
if(terminate >= probability)
break;
@@ -371,7 +367,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
- kernel_path_ao(kg, sd, emission_sd, L, state, rng, throughput, make_float3(0.0f, 0.0f, 0.0f));
+ kernel_path_ao(kg, sd, emission_sd, L, state, throughput, make_float3(0.0f, 0.0f, 0.0f));
}
#endif /* __AO__ */
@@ -387,11 +383,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
- uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
+ uint lcg_state = lcg_state_init(state, 0x68bc21eb);
float bssrdf_u, bssrdf_v;
path_state_rng_2D(kg,
- rng,
state,
PRNG_BSDF_U,
&bssrdf_u, &bssrdf_v);
@@ -412,7 +407,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
int all = (kernel_data.integrator.sample_all_lights_indirect) ||
(state->flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(kg,
- rng,
sd,
emission_sd,
state,
@@ -423,23 +417,23 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
}
#endif /* defined(__EMISSION__) */
- if(!kernel_path_surface_bounce(kg, rng, sd, &throughput, state, L, ray))
+ if(!kernel_path_surface_bounce(kg, sd, &throughput, state, L, ray))
break;
}
}
+#endif /* defined(__BRANCHED_PATH__) || defined(__BAKING__) */
-ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
- RNG *rng,
- int sample,
- Ray ray,
- ccl_global float *buffer,
- PathRadiance *L,
- bool *is_shadow_catcher)
+ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
+ uint rng_hash,
+ int sample,
+ Ray ray,
+ ccl_global float *buffer,
+ PathRadiance *L,
+ bool *is_shadow_catcher)
{
/* initialize */
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float L_transparent = 0.0f;
path_radiance_init(L, kernel_data.film.use_light_pass);
@@ -449,12 +443,7 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
ShaderData emission_sd;
PathState state;
- path_state_init(kg, &emission_sd, &state, rng, sample, &ray);
-
-#ifdef __KERNEL_DEBUG__
- DebugData debug_data;
- debug_data_init(&debug_data);
-#endif /* __KERNEL_DEBUG__ */
+ path_state_init(kg, &emission_sd, &state, rng_hash, sample, &ray);
#ifdef __SUBSURFACE__
SubsurfaceIndirectRays ss_indirect;
@@ -481,7 +470,7 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d);
+ lcg_state = lcg_state_init(&state, 0x51633e2d);
}
if(state.bounce > kernel_data.integrator.ao_bounces) {
@@ -496,11 +485,11 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
#ifdef __KERNEL_DEBUG__
if(state.flag & PATH_RAY_CAMERA) {
- debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
- debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
- debug_data.num_bvh_intersections += isect.num_intersections;
+ L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
+ L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
+ L->debug_data.num_bvh_intersections += isect.num_intersections;
}
- debug_data.num_ray_bounces++;
+ L->debug_data.num_ray_bounces++;
#endif /* __KERNEL_DEBUG__ */
#ifdef __LAMP_MIS__
@@ -561,15 +550,15 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
int all = false;
/* direct light sampling */
- kernel_branched_path_volume_connect_light(kg, rng, &sd,
+ kernel_branched_path_volume_connect_light(kg, &sd,
&emission_sd, throughput, &state, L, all,
&volume_ray, &volume_segment);
/* indirect sample. if we use distance sampling and take just
* one sample for direct and indirect light, we could share
* this computation, but makes code a bit complex */
- float rphase = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_PHASE);
- float rscatter = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_SCATTER_DISTANCE);
+ float rphase = path_state_rng_1D_for_decision(kg, &state, PRNG_PHASE);
+ float rscatter = path_state_rng_1D_for_decision(kg, &state, PRNG_SCATTER_DISTANCE);
result = kernel_volume_decoupled_scatter(kg,
&state, &volume_ray, &sd, &throughput,
@@ -580,7 +569,7 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
kernel_volume_decoupled_free(kg, &volume_segment);
if(result == VOLUME_PATH_SCATTERED) {
- if(kernel_path_volume_bounce(kg, rng, &sd, &throughput, &state, L, &ray))
+ if(kernel_path_volume_bounce(kg, &sd, &throughput, &state, L, &ray))
continue;
else
break;
@@ -594,15 +583,15 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
{
/* integrate along volume segment with distance sampling */
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, &state, &sd, &volume_ray, L, &throughput, rng, heterogeneous);
+ kg, &state, &sd, &volume_ray, L, &throughput, heterogeneous);
# ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
- kernel_path_volume_connect_light(kg, rng, &sd, &emission_sd, throughput, &state, L);
+ kernel_path_volume_connect_light(kg, &sd, &emission_sd, throughput, &state, L);
/* indirect light bounce */
- if(kernel_path_volume_bounce(kg, rng, &sd, &throughput, &state, L, &ray))
+ if(kernel_path_volume_bounce(kg, &sd, &throughput, &state, L, &ray))
continue;
else
break;
@@ -615,7 +604,7 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
if(!hit) {
/* eval background shader if nothing hit */
if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) {
- L_transparent += average(throughput);
+ L->transparent += average(throughput);
#ifdef __PASSES__
if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
@@ -637,21 +626,26 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
/* setup shading */
shader_setup_from_ray(kg, &sd, &isect, &ray);
- float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF);
- shader_eval_surface(kg, &sd, rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+ float rbsdf = path_state_rng_1D_for_decision(kg, &state, PRNG_BSDF);
+ shader_eval_surface(kg, &sd, &state, rbsdf, state.flag);
#ifdef __SHADOW_TRICKS__
if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
if(state.flag & PATH_RAY_CAMERA) {
- state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY | PATH_RAY_STORE_SHADOW_INFO);
- state.catcher_object = sd.object;
+ state.flag |= (PATH_RAY_SHADOW_CATCHER |
+ PATH_RAY_STORE_SHADOW_INFO);
if(!kernel_data.background.transparent) {
- L->shadow_color = indirect_background(kg, &emission_sd, &state, &ray);
+ L->shadow_background_color =
+ indirect_background(kg, &emission_sd, &state, &ray);
}
+ L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L);
+ L->shadow_throughput = average(throughput);
}
}
- else {
- state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ else if(state.flag & PATH_RAY_SHADOW_CATCHER) {
+ /* Only update transparency after shadow catcher bounce. */
+ L->shadow_transparency *=
+ average(shader_bsdf_transparency(kg, &sd));
}
#endif /* __SHADOW_TRICKS__ */
@@ -670,7 +664,7 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
holdout_weight = shader_holdout_eval(kg, &sd);
}
/* any throughput is ok, should all be identical here */
- L_transparent += average(holdout_weight*throughput);
+ L->transparent += average(holdout_weight*throughput);
}
if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) {
@@ -705,13 +699,13 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
/* path termination. this is a strange place to put the termination, it's
* mainly due to the mixed in MIS that we use. gives too many unneeded
* shader evaluations, only need emission if we are going to terminate */
- float probability = path_state_terminate_probability(kg, &state, throughput);
+ float probability = path_state_continuation_probability(kg, &state, throughput);
if(probability == 0.0f) {
break;
}
else if(probability != 1.0f) {
- float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE);
+ float terminate = path_state_rng_1D_for_decision(kg, &state, PRNG_TERMINATE);
if(terminate >= probability)
break;
@@ -723,7 +717,7 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
- kernel_path_ao(kg, &sd, &emission_sd, L, &state, rng, throughput, shader_bsdf_alpha(kg, &sd));
+ kernel_path_ao(kg, &sd, &emission_sd, L, &state, throughput, shader_bsdf_alpha(kg, &sd));
}
#endif /* __AO__ */
@@ -736,7 +730,6 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
&emission_sd,
L,
&state,
- rng,
&ray,
&throughput,
&ss_indirect))
@@ -747,10 +740,10 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
#endif /* __SUBSURFACE__ */
/* direct lighting */
- kernel_path_surface_connect_light(kg, rng, &sd, &emission_sd, throughput, &state, L);
+ kernel_path_surface_connect_light(kg, &sd, &emission_sd, throughput, &state, L);
/* compute direct lighting and next bounce */
- if(!kernel_path_surface_bounce(kg, rng, &sd, &throughput, &state, L, &ray))
+ if(!kernel_path_surface_bounce(kg, &sd, &throughput, &state, L, &ray))
break;
}
@@ -775,14 +768,8 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
#endif /* __SUBSURFACE__ */
#ifdef __SHADOW_TRICKS__
- *is_shadow_catcher = (state.flag & PATH_RAY_SHADOW_CATCHER);
+ *is_shadow_catcher = (state.flag & PATH_RAY_SHADOW_CATCHER) != 0;
#endif /* __SHADOW_TRICKS__ */
-
-#ifdef __KERNEL_DEBUG__
- kernel_write_debug_passes(kg, buffer, &state, &debug_data, sample);
-#endif /* __KERNEL_DEBUG__ */
-
- return 1.0f - L_transparent;
}
ccl_device void kernel_path_trace(KernelGlobals *kg,
@@ -797,24 +784,22 @@ ccl_device void kernel_path_trace(KernelGlobals *kg,
buffer += index*pass_stride;
/* initialize random numbers and ray */
- RNG rng;
+ uint rng_hash;
Ray ray;
- kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray);
+ kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng_hash, &ray);
/* integrate */
PathRadiance L;
bool is_shadow_catcher;
if(ray.t != 0.0f) {
- float alpha = kernel_path_integrate(kg, &rng, sample, ray, buffer, &L, &is_shadow_catcher);
- kernel_write_result(kg, buffer, sample, &L, alpha, is_shadow_catcher);
+ kernel_path_integrate(kg, rng_hash, sample, ray, buffer, &L, &is_shadow_catcher);
+ kernel_write_result(kg, buffer, sample, &L, is_shadow_catcher);
}
else {
- kernel_write_result(kg, buffer, sample, NULL, 0.0f, false);
+ kernel_write_result(kg, buffer, sample, NULL, false);
}
-
- path_rng_end(kg, rng_state, rng);
}
#endif /* __SPLIT_KERNEL__ */
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
index 10816d3e5d1..dde40674ee6 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -23,7 +23,6 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
ShaderData *emission_sd,
PathRadiance *L,
ccl_addr_space PathState *state,
- RNG *rng,
float3 throughput)
{
int num_samples = kernel_data.integrator.ao_samples;
@@ -35,7 +34,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
for(int j = 0; j < num_samples; j++) {
float bsdf_u, bsdf_v;
- path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float3 ao_D;
float ao_pdf;
@@ -55,7 +54,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
light_ray.dP = sd->dP;
light_ray.dD = differential3_zero();
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &ao_shadow)) {
path_radiance_accum_ao(L, state, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow);
}
else {
@@ -69,7 +68,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
/* bounce off surface and integrate indirect light */
ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg,
- RNG *rng, ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd,
+ ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd,
float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L)
{
float sum_sample_weight = 0.0f;
@@ -113,15 +112,18 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
num_samples = ceil_to_int(num_samples_adjust*num_samples);
float num_samples_inv = num_samples_adjust/num_samples;
- RNG bsdf_rng = cmj_hash(*rng, i);
for(int j = 0; j < num_samples; j++) {
PathState ps = *state;
float3 tp = throughput;
Ray bsdf_ray;
+#ifdef __SHADOW_TRICKS__
+ float shadow_transparency = L->shadow_transparency;
+#endif
+
+ ps.rng_hash = cmj_hash(state->rng_hash, i);
if(!kernel_branched_path_surface_bounce(kg,
- &bsdf_rng,
sd,
sc,
j,
@@ -135,10 +137,11 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
continue;
}
+ ps.rng_hash = state->rng_hash;
+
kernel_path_indirect(kg,
indirect_sd,
emission_sd,
- rng,
&bsdf_ray,
tp*num_samples_inv,
num_samples,
@@ -149,6 +152,10 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
* for the next samples */
path_radiance_sum_indirect(L);
path_radiance_reset_indirect(L);
+
+#ifdef __SHADOW_TRICKS__
+ L->shadow_transparency = shadow_transparency;
+#endif
}
}
}
@@ -160,7 +167,6 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
ShaderData *emission_sd,
PathRadiance *L,
PathState *state,
- RNG *rng,
Ray *ray,
float3 throughput)
{
@@ -171,17 +177,17 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
continue;
/* set up random number generator */
- uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
+ uint lcg_state = lcg_state_init(state, 0x68bc21eb);
int num_samples = kernel_data.integrator.subsurface_samples;
float num_samples_inv = 1.0f/num_samples;
- RNG bssrdf_rng = cmj_hash(*rng, i);
+ uint bssrdf_rng_hash = cmj_hash(state->rng_hash, i);
/* do subsurface scatter step with copy of shader data, this will
* replace the BSSRDF with a diffuse BSDF closure */
for(int j = 0; j < num_samples; j++) {
SubsurfaceIntersection ss_isect;
float bssrdf_u, bssrdf_v;
- path_branched_rng_2D(kg, &bssrdf_rng, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ path_branched_rng_2D(kg, bssrdf_rng_hash, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
int num_hits = subsurface_scatter_multi_intersect(kg,
&ss_isect,
sd,
@@ -234,7 +240,6 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
(state->flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(
kg,
- rng,
&bssrdf_sd,
emission_sd,
&hit_state,
@@ -248,7 +253,6 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
/* indirect light */
kernel_branched_path_surface_indirect_light(
kg,
- rng,
&bssrdf_sd,
indirect_sd,
emission_sd,
@@ -262,17 +266,16 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
}
#endif /* __SUBSURFACE__ */
-ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
- RNG *rng,
- int sample,
- Ray ray,
- ccl_global float *buffer,
- PathRadiance *L,
- bool *is_shadow_catcher)
+ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
+ uint rng_hash,
+ int sample,
+ Ray ray,
+ ccl_global float *buffer,
+ PathRadiance *L,
+ bool *is_shadow_catcher)
{
/* initialize */
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float L_transparent = 0.0f;
path_radiance_init(L, kernel_data.film.use_light_pass);
@@ -282,12 +285,7 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
ShaderData emission_sd, indirect_sd;
PathState state;
- path_state_init(kg, &emission_sd, &state, rng, sample, &ray);
-
-#ifdef __KERNEL_DEBUG__
- DebugData debug_data;
- debug_data_init(&debug_data);
-#endif /* __KERNEL_DEBUG__ */
+ path_state_init(kg, &emission_sd, &state, rng_hash, sample, &ray);
/* Main Loop
* Here we only handle transparency intersections from the camera ray.
@@ -310,7 +308,7 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d);
+ lcg_state = lcg_state_init(&state, 0x51633e2d);
}
bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
@@ -319,10 +317,10 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
#endif /* __HAIR__ */
#ifdef __KERNEL_DEBUG__
- debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
- debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
- debug_data.num_bvh_intersections += isect.num_intersections;
- debug_data.num_ray_bounces++;
+ L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
+ L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
+ L->debug_data.num_bvh_intersections += isect.num_intersections;
+ L->debug_data.num_ray_bounces++;
#endif /* __KERNEL_DEBUG__ */
#ifdef __VOLUME__
@@ -353,7 +351,7 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
int all = kernel_data.integrator.sample_all_lights_direct;
- kernel_branched_path_volume_connect_light(kg, rng, &sd,
+ kernel_branched_path_volume_connect_light(kg, &sd,
&emission_sd, throughput, &state, L, all,
&volume_ray, &volume_segment);
@@ -372,8 +370,8 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
/* scatter sample. if we use distance sampling and take just one
* sample for direct and indirect light, we could share this
* computation, but makes code a bit complex */
- float rphase = path_state_rng_1D_for_decision(kg, rng, &ps, PRNG_PHASE);
- float rscatter = path_state_rng_1D_for_decision(kg, rng, &ps, PRNG_SCATTER_DISTANCE);
+ float rphase = path_state_rng_1D_for_decision(kg, &ps, PRNG_PHASE);
+ float rscatter = path_state_rng_1D_for_decision(kg, &ps, PRNG_SCATTER_DISTANCE);
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
&ps, &pray, &sd, &tp, rphase, rscatter, &volume_segment, NULL, false);
@@ -382,7 +380,6 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
kernel_assert(result == VOLUME_PATH_SCATTERED);
if(kernel_path_volume_bounce(kg,
- rng,
&sd,
&tp,
&ps,
@@ -392,7 +389,6 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
kernel_path_indirect(kg,
&indirect_sd,
&emission_sd,
- rng,
&pray,
tp*num_samples_inv,
num_samples,
@@ -431,16 +427,15 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
path_state_branch(&ps, j, num_samples);
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, &ps, &sd, &volume_ray, L, &tp, rng, heterogeneous);
+ kg, &ps, &sd, &volume_ray, L, &tp, heterogeneous);
#ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* todo: support equiangular, MIS and all light sampling.
* alternatively get decoupled ray marching working on the GPU */
- kernel_path_volume_connect_light(kg, rng, &sd, &emission_sd, tp, &state, L);
+ kernel_path_volume_connect_light(kg, &sd, &emission_sd, tp, &state, L);
if(kernel_path_volume_bounce(kg,
- rng,
&sd,
&tp,
&ps,
@@ -450,7 +445,6 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
kernel_path_indirect(kg,
&indirect_sd,
&emission_sd,
- rng,
&pray,
tp,
num_samples,
@@ -475,7 +469,7 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
if(!hit) {
/* eval background shader if nothing hit */
if(kernel_data.background.transparent) {
- L_transparent += average(throughput);
+ L->transparent += average(throughput);
#ifdef __PASSES__
if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
@@ -494,21 +488,24 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
/* setup shading */
shader_setup_from_ray(kg, &sd, &isect, &ray);
- shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, &sd, &state, 0.0f, state.flag);
shader_merge_closures(&sd);
#ifdef __SHADOW_TRICKS__
if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
- if(state.flag & PATH_RAY_CAMERA) {
- state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY | PATH_RAY_STORE_SHADOW_INFO);
- state.catcher_object = sd.object;
- if(!kernel_data.background.transparent) {
- L->shadow_color = indirect_background(kg, &emission_sd, &state, &ray);
- }
+ state.flag |= (PATH_RAY_SHADOW_CATCHER |
+ PATH_RAY_STORE_SHADOW_INFO);
+ if(!kernel_data.background.transparent) {
+ L->shadow_background_color =
+ indirect_background(kg, &emission_sd, &state, &ray);
}
+ L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L);
+ L->shadow_throughput = average(throughput);
}
- else {
- state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ else if(state.flag & PATH_RAY_SHADOW_CATCHER) {
+ /* Only update transparency after shadow catcher bounce. */
+ L->shadow_transparency *=
+ average(shader_bsdf_transparency(kg, &sd));
}
#endif /* __SHADOW_TRICKS__ */
@@ -524,7 +521,7 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
holdout_weight = shader_holdout_eval(kg, &sd);
}
/* any throughput is ok, should all be identical here */
- L_transparent += average(holdout_weight*throughput);
+ L->transparent += average(holdout_weight*throughput);
}
if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) {
break;
@@ -548,13 +545,13 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
/* path termination. this is a strange place to put the termination, it's
* mainly due to the mixed in MIS that we use. gives too many unneeded
* shader evaluations, only need emission if we are going to terminate */
- float probability = path_state_terminate_probability(kg, &state, throughput);
+ float probability = path_state_continuation_probability(kg, &state, throughput);
if(probability == 0.0f) {
break;
}
else if(probability != 1.0f) {
- float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE);
+ float terminate = path_state_rng_1D_for_decision(kg, &state, PRNG_TERMINATE);
if(terminate >= probability)
break;
@@ -568,7 +565,7 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
- kernel_branched_path_ao(kg, &sd, &emission_sd, L, &state, rng, throughput);
+ kernel_branched_path_ao(kg, &sd, &emission_sd, L, &state, throughput);
}
#endif /* __AO__ */
@@ -576,7 +573,7 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
/* bssrdf scatter to a different location on the same object */
if(sd.flag & SD_BSSRDF) {
kernel_branched_path_subsurface_scatter(kg, &sd, &indirect_sd, &emission_sd,
- L, &state, rng, &ray, throughput);
+ L, &state, &ray, throughput);
}
#endif /* __SUBSURFACE__ */
@@ -588,13 +585,13 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
if(kernel_data.integrator.use_direct_light) {
int all = (kernel_data.integrator.sample_all_lights_direct) ||
(state.flag & PATH_RAY_SHADOW_CATCHER);
- kernel_branched_path_surface_connect_light(kg, rng,
+ kernel_branched_path_surface_connect_light(kg,
&sd, &emission_sd, &hit_state, throughput, 1.0f, L, all);
}
#endif /* __EMISSION__ */
/* indirect light */
- kernel_branched_path_surface_indirect_light(kg, rng,
+ kernel_branched_path_surface_indirect_light(kg,
&sd, &indirect_sd, &emission_sd, throughput, 1.0f, &hit_state, L);
/* continue in case of transparency */
@@ -625,14 +622,8 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
}
#ifdef __SHADOW_TRICKS__
- *is_shadow_catcher = (state.flag & PATH_RAY_SHADOW_CATCHER);
+ *is_shadow_catcher = (state.flag & PATH_RAY_SHADOW_CATCHER) != 0;
#endif /* __SHADOW_TRICKS__ */
-
-#ifdef __KERNEL_DEBUG__
- kernel_write_debug_passes(kg, buffer, &state, &debug_data, sample);
-#endif /* __KERNEL_DEBUG__ */
-
- return 1.0f - L_transparent;
}
ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
@@ -647,24 +638,22 @@ ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
buffer += index*pass_stride;
/* initialize random numbers and ray */
- RNG rng;
+ uint rng_hash;
Ray ray;
- kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray);
+ kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng_hash, &ray);
/* integrate */
PathRadiance L;
bool is_shadow_catcher;
if(ray.t != 0.0f) {
- float alpha = kernel_branched_path_integrate(kg, &rng, sample, ray, buffer, &L, &is_shadow_catcher);
- kernel_write_result(kg, buffer, sample, &L, alpha, is_shadow_catcher);
+ kernel_branched_path_integrate(kg, rng_hash, sample, ray, buffer, &L, &is_shadow_catcher);
+ kernel_write_result(kg, buffer, sample, &L, is_shadow_catcher);
}
else {
- kernel_write_result(kg, buffer, sample, NULL, 0.0f, false);
+ kernel_write_result(kg, buffer, sample, NULL, false);
}
-
- path_rng_end(kg, rng_state, rng);
}
#endif /* __SPLIT_KERNEL__ */
diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h
index 82f83deb595..54dd278a185 100644
--- a/intern/cycles/kernel/kernel_path_common.h
+++ b/intern/cycles/kernel/kernel_path_common.h
@@ -22,7 +22,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
ccl_global uint *rng_state,
int sample,
int x, int y,
- RNG *rng,
+ uint *rng_hash,
ccl_addr_space Ray *ray)
{
float filter_u;
@@ -34,20 +34,20 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
*rng_state = hash_int_2d(x, y);
}
- path_rng_init(kg, rng_state, sample, num_samples, rng, x, y, &filter_u, &filter_v);
+ path_rng_init(kg, rng_state, sample, num_samples, rng_hash, x, y, &filter_u, &filter_v);
/* sample camera ray */
float lens_u = 0.0f, lens_v = 0.0f;
if(kernel_data.cam.aperturesize > 0.0f)
- path_rng_2D(kg, rng, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v);
+ path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v);
float time = 0.0f;
#ifdef __CAMERA_MOTION__
if(kernel_data.cam.shuttertime != -1.0f)
- time = path_rng_1D(kg, rng, sample, num_samples, PRNG_TIME);
+ time = path_rng_1D(kg, *rng_hash, sample, num_samples, PRNG_TIME);
#endif
camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, ray);
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index 0fa77d9e8bd..b539224db31 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -19,12 +19,13 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void path_state_init(KernelGlobals *kg,
ShaderData *stack_sd,
ccl_addr_space PathState *state,
- RNG *rng,
+ uint rng_hash,
int sample,
ccl_addr_space Ray *ray)
{
state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP;
+ state->rng_hash = rng_hash;
state->rng_offset = PRNG_BASE_NUM;
state->sample = sample;
state->num_samples = kernel_data.integrator.aa_samples;
@@ -58,16 +59,12 @@ ccl_device_inline void path_state_init(KernelGlobals *kg,
/* 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);
+ state->rng_congruential = lcg_init(rng_hash + sample*0x51633e2d);
}
else {
state->volume_stack[0].shader = SHADER_NONE;
}
#endif
-
-#ifdef __SHADOW_TRICKS__
- state->catcher_object = OBJECT_NONE;
-#endif
}
ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathState *state, int label)
@@ -139,9 +136,11 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
/* random number generator next bounce */
state->rng_offset += PRNG_BOUNCE_NUM;
+#ifdef __DENOISING_FEATURES__
if((state->denoising_feature_weight == 0.0f) && !(state->flag & PATH_RAY_SHADOW_CATCHER)) {
state->flag &= ~PATH_RAY_STORE_SHADOW_INFO;
}
+#endif
}
ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *state)
@@ -158,17 +157,26 @@ ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *s
return flag;
}
-ccl_device_inline float path_state_terminate_probability(KernelGlobals *kg, ccl_addr_space PathState *state, const float3 throughput)
+ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg, ccl_addr_space PathState *state, const float3 throughput)
{
if(state->flag & PATH_RAY_TRANSPARENT) {
- /* transparent rays treated separately */
- if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce)
+ /* Transparent rays are treated separately with own max bounces. */
+ if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce) {
return 0.0f;
- else if(state->transparent_bounce <= kernel_data.integrator.transparent_min_bounce)
+ }
+ /* Do at least one bounce without RR. */
+ else if(state->transparent_bounce <= 1) {
return 1.0f;
+ }
+#ifdef __SHADOW_TRICKS__
+ /* Exception for shadow catcher not working correctly with RR. */
+ else if((state->flag & PATH_RAY_SHADOW_CATCHER) && (state->transparent_bounce <= 8)) {
+ return 1.0f;
+ }
+#endif
}
else {
- /* other rays */
+ /* Test max bounces for various ray types. */
if((state->bounce >= kernel_data.integrator.max_bounce) ||
(state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) ||
(state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) ||
@@ -179,13 +187,21 @@ ccl_device_inline float path_state_terminate_probability(KernelGlobals *kg, ccl_
{
return 0.0f;
}
- else if(state->bounce <= kernel_data.integrator.min_bounce) {
+ /* Do at least one bounce without RR. */
+ else if(state->bounce <= 1) {
return 1.0f;
}
+#ifdef __SHADOW_TRICKS__
+ /* Exception for shadow catcher not working correctly with RR. */
+ else if((state->flag & PATH_RAY_SHADOW_CATCHER) && (state->bounce <= 3)) {
+ return 1.0f;
+ }
+#endif
}
- /* probalistic termination */
- return average(throughput); /* todo: try using max here */
+ /* Probalistic termination: use sqrt() to roughly match typical view
+ * transform and do path termination a bit later on average. */
+ return sqrtf(max3(fabs(throughput)));
}
/* TODO(DingTo): Find more meaningful name for this */
diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h
index 10b568ac3dd..9bccc9201e0 100644
--- a/intern/cycles/kernel/kernel_path_subsurface.h
+++ b/intern/cycles/kernel/kernel_path_subsurface.h
@@ -28,7 +28,6 @@ bool kernel_path_subsurface_scatter(
ShaderData *emission_sd,
PathRadiance *L,
ccl_addr_space PathState *state,
- RNG *rng,
ccl_addr_space Ray *ray,
ccl_addr_space float3 *throughput,
ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
@@ -47,11 +46,11 @@ bool kernel_path_subsurface_scatter(
*/
kernel_assert(!ss_indirect->tracing);
- uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
+ uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
SubsurfaceIntersection ss_isect;
float bssrdf_u, bssrdf_v;
- path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ path_state_rng_2D(kg, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
int num_hits = subsurface_scatter_multi_intersect(kg,
&ss_isect,
sd,
@@ -94,10 +93,9 @@ bool kernel_path_subsurface_scatter(
hit_L->direct_throughput = L->direct_throughput;
path_radiance_copy_indirect(hit_L, L);
- kernel_path_surface_connect_light(kg, rng, sd, emission_sd, *hit_tp, state, hit_L);
+ kernel_path_surface_connect_light(kg, sd, emission_sd, *hit_tp, state, hit_L);
if(kernel_path_surface_bounce(kg,
- rng,
sd,
hit_tp,
hit_state,
diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h
index dcb577e176f..6c3a444e48a 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -20,7 +20,6 @@ CCL_NAMESPACE_BEGIN
/* branched path tracing: connect path directly to position on one or more lights and add it to L */
ccl_device_noinline void kernel_branched_path_surface_connect_light(
KernelGlobals *kg,
- RNG *rng,
ShaderData *sd,
ShaderData *emission_sd,
ccl_addr_space PathState *state,
@@ -50,12 +49,12 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i));
float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
- RNG lamp_rng = cmj_hash(*rng, i);
+ uint lamp_rng_hash = cmj_hash(state->rng_hash, i);
for(int j = 0; j < num_samples; j++) {
float light_u, light_v;
- path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_branched_rng_light_termination(kg, &lamp_rng, state, j, num_samples);
+ path_branched_rng_2D(kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_branched_rng_light_termination(kg, lamp_rng_hash, state, j, num_samples);
LightSample ls;
if(lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
@@ -68,7 +67,7 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
/* accumulate */
path_radiance_accum_light(L, state, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
}
@@ -86,10 +85,10 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
float num_samples_inv = num_samples_adjust/num_samples;
for(int j = 0; j < num_samples; j++) {
- float light_t = path_branched_rng_1D(kg, rng, state, j, num_samples, PRNG_LIGHT);
+ float light_t = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT);
float light_u, light_v;
- path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_branched_rng_light_termination(kg, rng, state, j, num_samples);
+ path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
/* only sample triangle lights */
if(kernel_data.integrator.num_all_lights)
@@ -105,7 +104,7 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
/* accumulate */
path_radiance_accum_light(L, state, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
}
@@ -119,10 +118,10 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
}
else {
/* sample one light at random */
- float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
- path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_state_rng_light_termination(kg, rng, state);
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_state_rng_light_termination(kg, state);
LightSample ls;
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
@@ -131,7 +130,7 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
/* accumulate */
path_radiance_accum_light(L, state, throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, is_lamp);
}
@@ -147,7 +146,6 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
/* branched path tracing: bounce off or through surface to with new direction stored in ray */
ccl_device bool kernel_branched_path_surface_bounce(
KernelGlobals *kg,
- RNG *rng,
ShaderData *sd,
const ShaderClosure *sc,
int sample,
@@ -164,7 +162,7 @@ ccl_device bool kernel_branched_path_surface_bounce(
float3 bsdf_omega_in;
differential3 bsdf_domega_in;
float bsdf_u, bsdf_v;
- path_branched_rng_2D(kg, rng, state, sample, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_branched_rng_2D(kg, state->rng_hash, state, sample, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
int label;
label = shader_bsdf_sample_closure(kg, sd, sc, bsdf_u, bsdf_v, &bsdf_eval,
@@ -217,7 +215,7 @@ ccl_device bool kernel_branched_path_surface_bounce(
#endif
/* path tracing: connect path directly to position on a light and add it to L */
-ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG *rng,
+ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg,
ShaderData *sd, ShaderData *emission_sd, float3 throughput, ccl_addr_space PathState *state,
PathRadiance *L)
{
@@ -228,7 +226,6 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_SHADOW_CATCHER) {
kernel_branched_path_surface_connect_light(kg,
- rng,
sd,
emission_sd,
state,
@@ -241,9 +238,9 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
#endif
/* sample illumination from lights to find path contribution */
- float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
- path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
Ray light_ray;
BsdfEval L_light;
@@ -255,12 +252,12 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
LightSample ls;
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
- float terminate = path_state_rng_light_termination(kg, rng, state);
+ float terminate = path_state_rng_light_termination(kg, state);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
/* accumulate */
path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
}
@@ -274,7 +271,6 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
/* path tracing: bounce off or through surface to with new direction stored in ray */
ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
- RNG *rng,
ShaderData *sd,
ccl_addr_space float3 *throughput,
ccl_addr_space PathState *state,
@@ -289,7 +285,7 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
float3 bsdf_omega_in;
differential3 bsdf_domega_in;
float bsdf_u, bsdf_v;
- path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
int label;
label = shader_bsdf_sample(kg, sd, bsdf_u, bsdf_v, &bsdf_eval,
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index dcedf51e479..c9c7f447c42 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -20,7 +20,6 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void kernel_path_volume_connect_light(
KernelGlobals *kg,
- RNG *rng,
ShaderData *sd,
ShaderData *emission_sd,
float3 throughput,
@@ -32,9 +31,9 @@ ccl_device_inline void kernel_path_volume_connect_light(
return;
/* sample illumination from lights to find path contribution */
- float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
- path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
Ray light_ray;
BsdfEval L_light;
@@ -48,12 +47,12 @@ ccl_device_inline void kernel_path_volume_connect_light(
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls))
{
- float terminate = path_state_rng_light_termination(kg, rng, state);
+ float terminate = path_state_rng_light_termination(kg, state);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
/* accumulate */
path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
}
@@ -69,7 +68,6 @@ ccl_device
#endif
bool kernel_path_volume_bounce(
KernelGlobals *kg,
- RNG *rng,
ShaderData *sd,
ccl_addr_space float3 *throughput,
ccl_addr_space PathState *state,
@@ -82,7 +80,7 @@ bool kernel_path_volume_bounce(
float3 phase_omega_in;
differential3 phase_domega_in;
float phase_u, phase_v;
- path_state_rng_2D(kg, rng, state, PRNG_PHASE_U, &phase_u, &phase_v);
+ path_state_rng_2D(kg, state, PRNG_PHASE_U, &phase_u, &phase_v);
int label;
label = shader_volume_phase_sample(kg, sd, phase_u, phase_v, &phase_eval,
@@ -120,7 +118,6 @@ bool kernel_path_volume_bounce(
#ifndef __SPLIT_KERNEL__
ccl_device void kernel_branched_path_volume_connect_light(
KernelGlobals *kg,
- RNG *rng,
ShaderData *sd,
ShaderData *emission_sd,
float3 throughput,
@@ -150,12 +147,12 @@ ccl_device void kernel_branched_path_volume_connect_light(
int num_samples = light_select_num_samples(kg, i);
float num_samples_inv = 1.0f/(num_samples*kernel_data.integrator.num_all_lights);
- RNG lamp_rng = cmj_hash(*rng, i);
+ uint lamp_rng_hash = cmj_hash(state->rng_hash, i);
for(int j = 0; j < num_samples; j++) {
/* sample random position on given light */
float light_u, light_v;
- path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+ path_branched_rng_2D(kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
@@ -163,8 +160,8 @@ ccl_device void kernel_branched_path_volume_connect_light(
float3 tp = throughput;
/* sample position on volume segment */
- float rphase = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_PHASE);
- float rscatter = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_SCATTER_DISTANCE);
+ float rphase = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE);
+ float rscatter = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
@@ -177,12 +174,12 @@ ccl_device void kernel_branched_path_volume_connect_light(
if(kernel_data.integrator.pdf_triangles != 0.0f)
ls.pdf *= 2.0f;
- float terminate = path_branched_rng_light_termination(kg, rng, state, j, num_samples);
+ float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
/* accumulate */
path_radiance_accum_light(L, state, tp*num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
}
@@ -198,9 +195,9 @@ ccl_device void kernel_branched_path_volume_connect_light(
for(int j = 0; j < num_samples; j++) {
/* sample random position on random triangle */
- float light_t = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_LIGHT);
+ float light_t = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT);
float light_u, light_v;
- path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+ path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
/* only sample triangle lights */
if(kernel_data.integrator.num_all_lights)
@@ -212,8 +209,8 @@ ccl_device void kernel_branched_path_volume_connect_light(
float3 tp = throughput;
/* sample position on volume segment */
- float rphase = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_PHASE);
- float rscatter = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_SCATTER_DISTANCE);
+ float rphase = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE);
+ float rscatter = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
@@ -226,12 +223,12 @@ ccl_device void kernel_branched_path_volume_connect_light(
if(kernel_data.integrator.num_all_lights)
ls.pdf *= 2.0f;
- float terminate = path_branched_rng_light_termination(kg, rng, state, j, num_samples);
+ float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
/* accumulate */
path_radiance_accum_light(L, state, tp*num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
}
@@ -242,9 +239,9 @@ ccl_device void kernel_branched_path_volume_connect_light(
}
else {
/* sample random position on random light */
- float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
- path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
@@ -252,8 +249,8 @@ ccl_device void kernel_branched_path_volume_connect_light(
float3 tp = throughput;
/* sample position on volume segment */
- float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
- float rscatter = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
+ float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE);
+ float rscatter = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE);
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
@@ -264,12 +261,12 @@ ccl_device void kernel_branched_path_volume_connect_light(
/* todo: split up light_sample so we don't have to call it again with new position */
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
/* sample random light */
- float terminate = path_state_rng_light_termination(kg, rng, state);
+ float terminate = path_state_rng_light_termination(kg, state);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
/* accumulate */
path_radiance_accum_light(L, state, tp, &L_light, shadow, 1.0f, is_lamp);
}
diff --git a/intern/cycles/kernel/kernel_queues.h b/intern/cycles/kernel/kernel_queues.h
index 96bc636d5ac..e32d4bbbc1b 100644
--- a/intern/cycles/kernel/kernel_queues.h
+++ b/intern/cycles/kernel/kernel_queues.h
@@ -128,6 +128,21 @@ ccl_device unsigned int get_global_queue_index(
return my_gqidx;
}
+ccl_device int dequeue_ray_index(
+ int queue_number,
+ ccl_global int *queues,
+ int queue_size,
+ ccl_global int *queue_index)
+{
+ int index = atomic_fetch_and_dec_uint32((ccl_global uint*)&queue_index[queue_number])-1;
+
+ if(index < 0) {
+ return QUEUE_EMPTY_SLOT;
+ }
+
+ return queues[index + queue_number * queue_size];
+}
+
CCL_NAMESPACE_END
#endif // __KERNEL_QUEUE_H__
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index e8a912ccc0b..221d92f5de1 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -18,6 +18,16 @@
CCL_NAMESPACE_BEGIN
+/* Pseudo random numbers, uncomment this for debugging correlations. Only run
+ * this single threaded on a CPU for repeatable resutls. */
+//#define __DEBUG_CORRELATION__
+
+
+/* High Dimensional Sobol.
+ *
+ * Multidimensional sobol with generator matrices. Dimension 0 and 1 are equal
+ * to classic Van der Corput and Sobol sequences. */
+
#ifdef __SOBOL__
/* Skip initial numbers that are not as well distributed, especially the
@@ -26,47 +36,6 @@ CCL_NAMESPACE_BEGIN
*/
#define SOBOL_SKIP 64
-/* High Dimensional Sobol. */
-
-/* Van der Corput radical inverse. */
-ccl_device uint van_der_corput(uint bits)
-{
- bits = (bits << 16) | (bits >> 16);
- bits = ((bits & 0x00ff00ff) << 8) | ((bits & 0xff00ff00) >> 8);
- bits = ((bits & 0x0f0f0f0f) << 4) | ((bits & 0xf0f0f0f0) >> 4);
- bits = ((bits & 0x33333333) << 2) | ((bits & 0xcccccccc) >> 2);
- bits = ((bits & 0x55555555) << 1) | ((bits & 0xaaaaaaaa) >> 1);
- return bits;
-}
-
-/* Sobol radical inverse. */
-ccl_device uint sobol(uint i)
-{
- uint r = 0;
- for(uint v = 1U << 31; i; i >>= 1, v ^= v >> 1) {
- if(i & 1) {
- r ^= v;
- }
- }
- return r;
-}
-
-/* Inverse of sobol radical inverse. */
-ccl_device uint sobol_inverse(uint i)
-{
- const uint msb = 1U << 31;
- uint r = 0;
- for(uint v = 1; i; i <<= 1, v ^= v << 1) {
- if(i & msb) {
- r ^= v;
- }
- }
- return r;
-}
-
-/* Multidimensional sobol with generator matrices
- * dimension 0 and 1 are equal to van_der_corput() and sobol() respectively.
- */
ccl_device uint sobol_dimension(KernelGlobals *kg, int index, int dimension)
{
uint result = 0;
@@ -79,50 +48,31 @@ ccl_device uint sobol_dimension(KernelGlobals *kg, int index, int dimension)
return result;
}
-/* Lookup index and x/y coordinate, assumes m is a power of two. */
-ccl_device uint sobol_lookup(const uint m,
- const uint frame,
- const uint ex,
- const uint ey,
- uint *x, uint *y)
-{
- /* Shift is constant per frame. */
- const uint shift = frame << (m << 1);
- const uint sobol_shift = sobol(shift);
- /* Van der Corput is its own inverse. */
- const uint lower = van_der_corput(ex << (32 - m));
- /* Need to compensate for ey difference and shift. */
- const uint sobol_lower = sobol(lower);
- const uint mask = ~-(1 << m) << (32 - m); /* Only m upper bits. */
- const uint delta = ((ey << (32 - m)) ^ sobol_lower ^ sobol_shift) & mask;
- /* Only use m upper bits for the index (m is a power of two). */
- const uint sobol_result = delta | (delta >> m);
- const uint upper = sobol_inverse(sobol_result);
- const uint index = shift | upper | lower;
- *x = van_der_corput(index);
- *y = sobol_shift ^ sobol_result ^ sobol_lower;
- return index;
-}
+#endif /* __SOBOL__ */
+
ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
- RNG *rng,
+ uint rng_hash,
int sample, int num_samples,
int dimension)
{
+#ifdef __DEBUG_CORRELATION__
+ return (float)drand48();
+#endif
+
#ifdef __CMJ__
- if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) {
+# ifdef __SOBOL__
+ if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
+# endif
+ {
/* Correlated multi-jitter. */
- int p = *rng + dimension;
+ int p = rng_hash + dimension;
return cmj_sample_1D(sample, num_samples, p);
}
#endif
-#ifdef __SOBOL_FULL_SCREEN__
- uint result = sobol_dimension(kg, *rng, dimension);
- float r = (float)result * (1.0f/(float)0xFFFFFFFF);
- return r;
-#else
- /* Compute sobol sequence value using direction vectors. */
+#ifdef __SOBOL__
+ /* Sobol sequence value using direction vectors. */
uint result = sobol_dimension(kg, sample + SOBOL_SKIP, dimension);
float r = (float)result * (1.0f/(float)0xFFFFFFFF);
@@ -132,7 +82,7 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
/* Hash rng with dimension to solve correlation issues.
* See T38710, T50116.
*/
- RNG tmp_rng = cmj_hash_simple(dimension, *rng);
+ uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
shift = tmp_rng * (1.0f/(float)0xFFFFFFFF);
return r + shift - floorf(r + shift);
@@ -140,128 +90,60 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
}
ccl_device_forceinline void path_rng_2D(KernelGlobals *kg,
- RNG *rng,
+ uint rng_hash,
int sample, int num_samples,
int dimension,
float *fx, float *fy)
{
+#ifdef __DEBUG_CORRELATION__
+ *fx = (float)drand48();
+ *fy = (float)drand48();
+ return;
+#endif
+
#ifdef __CMJ__
- if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) {
+# ifdef __SOBOL__
+ if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
+# endif
+ {
/* Correlated multi-jitter. */
- int p = *rng + dimension;
+ int p = rng_hash + dimension;
cmj_sample_2D(sample, num_samples, p, fx, fy);
+ return;
}
- else
#endif
- {
- /* Sobol. */
- *fx = path_rng_1D(kg, rng, sample, num_samples, dimension);
- *fy = path_rng_1D(kg, rng, sample, num_samples, dimension + 1);
- }
+
+#ifdef __SOBOL__
+ /* Sobol. */
+ *fx = path_rng_1D(kg, rng_hash, sample, num_samples, dimension);
+ *fy = path_rng_1D(kg, rng_hash, sample, num_samples, dimension + 1);
+#endif
}
ccl_device_inline void path_rng_init(KernelGlobals *kg,
ccl_global uint *rng_state,
int sample, int num_samples,
- RNG *rng,
+ uint *rng_hash,
int x, int y,
float *fx, float *fy)
{
-#ifdef __SOBOL_FULL_SCREEN__
- uint px, py;
- uint bits = 16; /* limits us to 65536x65536 and 65536 samples */
- uint size = 1 << bits;
- uint frame = sample;
-
- *rng = sobol_lookup(bits, frame, x, y, &px, &py);
-
- *rng ^= kernel_data.integrator.seed;
-
- if(sample == 0) {
- *fx = 0.5f;
- *fy = 0.5f;
- }
- else {
- *fx = size * (float)px * (1.0f/(float)0xFFFFFFFF) - x;
- *fy = size * (float)py * (1.0f/(float)0xFFFFFFFF) - y;
- }
-#else
- *rng = *rng_state;
-
- *rng ^= kernel_data.integrator.seed;
-
- if(sample == 0) {
- *fx = 0.5f;
- *fy = 0.5f;
- }
- else {
- path_rng_2D(kg, rng, sample, num_samples, PRNG_FILTER_U, fx, fy);
- }
-#endif
-}
-
-ccl_device void path_rng_end(KernelGlobals *kg,
- ccl_global uint *rng_state,
- RNG rng)
-{
- /* nothing to do */
-}
-
-#else /* __SOBOL__ */
-
-/* Linear Congruential Generator */
-
-ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
- RNG *rng,
- int sample, int num_samples,
- int dimension)
-{
- /* implicit mod 2^32 */
- *rng = (1103515245*(*rng) + 12345);
- return (float)*rng * (1.0f/(float)0xFFFFFFFF);
-}
-
-ccl_device_inline void path_rng_2D(KernelGlobals *kg,
- RNG *rng,
- int sample, int num_samples,
- int dimension,
- float *fx, float *fy)
-{
- *fx = path_rng_1D(kg, rng, sample, num_samples, dimension);
- *fy = path_rng_1D(kg, rng, sample, num_samples, dimension + 1);
-}
-
-ccl_device void path_rng_init(KernelGlobals *kg,
- ccl_global uint *rng_state,
- int sample, int num_samples,
- RNG *rng,
- int x, int y,
- float *fx, float *fy)
-{
/* load state */
- *rng = *rng_state;
+ *rng_hash = *rng_state;
+ *rng_hash ^= kernel_data.integrator.seed;
- *rng ^= kernel_data.integrator.seed;
+#ifdef __DEBUG_CORRELATION__
+ srand48(*rng_hash + sample);
+#endif
if(sample == 0) {
*fx = 0.5f;
*fy = 0.5f;
}
else {
- path_rng_2D(kg, rng, sample, num_samples, PRNG_FILTER_U, fx, fy);
+ path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_FILTER_U, fx, fy);
}
}
-ccl_device void path_rng_end(KernelGlobals *kg,
- ccl_global uint *rng_state,
- RNG rng)
-{
- /* store state for next sample */
- *rng_state = rng;
-}
-
-#endif /* __SOBOL__ */
-
/* Linear Congruential Generator */
ccl_device uint lcg_step_uint(uint *rng)
@@ -295,19 +177,17 @@ ccl_device uint lcg_init(uint seed)
*/
ccl_device_inline float path_state_rng_1D(KernelGlobals *kg,
- RNG *rng,
const ccl_addr_space PathState *state,
int dimension)
{
return path_rng_1D(kg,
- rng,
+ state->rng_hash,
state->sample, state->num_samples,
state->rng_offset + dimension);
}
ccl_device_inline float path_state_rng_1D_for_decision(
KernelGlobals *kg,
- RNG *rng,
const ccl_addr_space PathState *state,
int dimension)
{
@@ -320,19 +200,18 @@ ccl_device_inline float path_state_rng_1D_for_decision(
* the same decision. */
const int rng_offset = state->rng_offset + state->transparent_bounce * PRNG_BOUNCE_NUM;
return path_rng_1D(kg,
- rng,
+ state->rng_hash,
state->sample, state->num_samples,
rng_offset + dimension);
}
ccl_device_inline void path_state_rng_2D(KernelGlobals *kg,
- RNG *rng,
const ccl_addr_space PathState *state,
int dimension,
float *fx, float *fy)
{
path_rng_2D(kg,
- rng,
+ state->rng_hash,
state->sample, state->num_samples,
state->rng_offset + dimension,
fx, fy);
@@ -340,14 +219,14 @@ ccl_device_inline void path_state_rng_2D(KernelGlobals *kg,
ccl_device_inline float path_branched_rng_1D(
KernelGlobals *kg,
- RNG *rng,
+ uint rng_hash,
const ccl_addr_space PathState *state,
int branch,
int num_branches,
int dimension)
{
return path_rng_1D(kg,
- rng,
+ rng_hash,
state->sample * num_branches + branch,
state->num_samples * num_branches,
state->rng_offset + dimension);
@@ -355,7 +234,7 @@ ccl_device_inline float path_branched_rng_1D(
ccl_device_inline float path_branched_rng_1D_for_decision(
KernelGlobals *kg,
- RNG *rng,
+ uint rng_hash,
const ccl_addr_space PathState *state,
int branch,
int num_branches,
@@ -363,7 +242,7 @@ ccl_device_inline float path_branched_rng_1D_for_decision(
{
const int rng_offset = state->rng_offset + state->transparent_bounce * PRNG_BOUNCE_NUM;
return path_rng_1D(kg,
- rng,
+ rng_hash,
state->sample * num_branches + branch,
state->num_samples * num_branches,
rng_offset + dimension);
@@ -371,7 +250,7 @@ ccl_device_inline float path_branched_rng_1D_for_decision(
ccl_device_inline void path_branched_rng_2D(
KernelGlobals *kg,
- RNG *rng,
+ uint rng_hash,
const ccl_addr_space PathState *state,
int branch,
int num_branches,
@@ -379,7 +258,7 @@ ccl_device_inline void path_branched_rng_2D(
float *fx, float *fy)
{
path_rng_2D(kg,
- rng,
+ rng_hash,
state->sample * num_branches + branch,
state->num_samples * num_branches,
state->rng_offset + dimension,
@@ -391,25 +270,24 @@ ccl_device_inline void path_branched_rng_2D(
*/
ccl_device_inline float path_state_rng_light_termination(
KernelGlobals *kg,
- RNG *rng,
const ccl_addr_space PathState *state)
{
if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
- return path_state_rng_1D_for_decision(kg, rng, state, PRNG_LIGHT_TERMINATE);
+ return path_state_rng_1D_for_decision(kg, state, PRNG_LIGHT_TERMINATE);
}
return 0.0f;
}
ccl_device_inline float path_branched_rng_light_termination(
KernelGlobals *kg,
- RNG *rng,
+ uint rng_hash,
const ccl_addr_space PathState *state,
int branch,
int num_branches)
{
if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
return path_branched_rng_1D_for_decision(kg,
- rng,
+ rng_hash,
state,
branch,
num_branches,
@@ -429,14 +307,19 @@ ccl_device_inline void path_state_branch(ccl_addr_space PathState *state,
state->num_samples = state->num_samples*num_branches;
}
-ccl_device_inline uint lcg_state_init(RNG *rng,
- int rng_offset,
- int sample,
+ccl_device_inline uint lcg_state_init(PathState *state,
uint scramble)
{
- return lcg_init(*rng + rng_offset + sample*scramble);
+ return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble);
}
+ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space PathState *state,
+ uint scramble)
+{
+ return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble);
+}
+
+
ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng)
{
/* Implicit mod 2^32 */
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index c66f52255f0..dd64f5b05ba 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -83,7 +83,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
sd->shader = __float_as_int(curvedata.z);
- sd->P = bvh_curve_refine(kg, sd, isect, ray);
+ sd->P = curve_refine(kg, sd, isect, ray);
}
else
#endif
@@ -669,7 +669,7 @@ ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughn
}
}
-ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
+ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, const ShaderData *sd)
{
if(sd->flag & SD_HAS_ONLY_VOLUME)
return make_float3(1.0f, 1.0f, 1.0f);
@@ -677,7 +677,7 @@ ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ const ShaderClosure *sc = &sd->closure[i];
if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl
eval += sc->weight;
@@ -764,6 +764,19 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd)
return eval;
}
+ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd)
+{
+ float3 N = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type))
+ N += sc->N*average(sc->weight);
+ }
+
+ return (is_zero(N))? sd->N : normalize(N);
+}
+
ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N_)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -783,12 +796,7 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
}
}
- if(is_zero(N))
- N = sd->N;
- else
- N = normalize(N);
-
- *N_ = N;
+ *N_ = (is_zero(N))? sd->N : normalize(N);
return eval;
}
@@ -863,8 +871,8 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
/* Surface Evaluation */
-ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
- ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx)
+ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
+ ccl_addr_space PathState *state, float randb, int path_flag)
{
sd->num_closure = 0;
sd->num_closure_extra = 0;
@@ -872,7 +880,7 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
#ifdef __OSL__
if(kg->osl)
- OSLShader::eval_surface(kg, sd, state, path_flag, ctx);
+ OSLShader::eval_surface(kg, sd, state, path_flag);
else
#endif
{
@@ -887,15 +895,15 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
#endif
}
- if(rng && (sd->flag & SD_BSDF_NEEDS_LCG)) {
- sd->lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0xb4bc3953);
+ if(sd->flag & SD_BSDF_NEEDS_LCG) {
+ sd->lcg_state = lcg_state_init_addrspace(state, 0xb4bc3953);
}
}
/* Background Evaluation */
ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
- ccl_addr_space PathState *state, int path_flag, ShaderContext ctx)
+ ccl_addr_space PathState *state, int path_flag)
{
sd->num_closure = 0;
sd->num_closure_extra = 0;
@@ -904,7 +912,7 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
#ifdef __SVM__
#ifdef __OSL__
if(kg->osl) {
- OSLShader::eval_background(kg, sd, state, path_flag, ctx);
+ OSLShader::eval_background(kg, sd, state, path_flag);
}
else
#endif
@@ -1039,8 +1047,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
ShaderData *sd,
ccl_addr_space PathState *state,
ccl_addr_space VolumeStack *stack,
- int path_flag,
- ShaderContext ctx)
+ int path_flag)
{
/* reset closures once at the start, we will be accumulating the closures
* for all volumes in the stack into a single array of closures */
@@ -1073,7 +1080,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
#ifdef __SVM__
# ifdef __OSL__
if(kg->osl) {
- OSLShader::eval_volume(kg, sd, state, path_flag, ctx);
+ OSLShader::eval_volume(kg, sd, state, path_flag);
}
else
# endif
@@ -1092,7 +1099,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
/* Displacement Evaluation */
-ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, ShaderContext ctx)
+ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state)
{
sd->num_closure = 0;
sd->num_closure_extra = 0;
@@ -1102,7 +1109,7 @@ ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_
#ifdef __SVM__
# ifdef __OSL__
if(kg->osl)
- OSLShader::eval_displacement(kg, sd, ctx);
+ OSLShader::eval_displacement(kg, sd);
else
# endif
{
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index fab5946970d..22e085e94da 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -49,11 +49,9 @@ ccl_device_forceinline bool shadow_handle_transparent_isect(
path_state_modify_bounce(state, true);
shader_eval_surface(kg,
shadow_sd,
- NULL,
state,
0.0f,
- PATH_RAY_SHADOW,
- SHADER_CONTEXT_SHADOW);
+ PATH_RAY_SHADOW);
path_state_modify_bounce(state, false);
*throughput *= shader_bsdf_transparency(kg, shadow_sd);
}
@@ -72,13 +70,14 @@ ccl_device_forceinline bool shadow_handle_transparent_isect(
ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
+ const uint visibility,
Ray *ray,
Intersection *isect,
float3 *shadow)
{
const bool blocked = scene_intersect(kg,
*ray,
- PATH_RAY_SHADOW_OPAQUE,
+ visibility & PATH_RAY_SHADOW_OPAQUE,
isect,
NULL,
0.0f, 0.0f);
@@ -120,15 +119,49 @@ ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
# define SHADOW_STACK_MAX_HITS 64
+# ifdef __VOLUME__
+struct VolumeState {
+# ifdef __SPLIT_KERNEL__
+# else
+ PathState ps;
+# endif
+};
+
+/* Get PathState ready for use for volume stack evaluation. */
+ccl_device_inline PathState *shadow_blocked_volume_path_state(
+ KernelGlobals *kg,
+ VolumeState *volume_state,
+ ccl_addr_space PathState *state,
+ ShaderData *sd,
+ Ray *ray)
+{
+# ifdef __SPLIT_KERNEL__
+ ccl_addr_space PathState *ps =
+ &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
+# else
+ PathState *ps = &volume_state->ps;
+# endif
+ *ps = *state;
+ /* We are checking for shadow on the "other" side of the surface, so need
+ * to discard volume we are currently at.
+ */
+ if(dot(sd->Ng, ray->D) < 0.0f) {
+ kernel_volume_stack_enter_exit(kg, sd, ps->volume_stack);
+ }
+ return ps;
+}
+#endif // __VOLUME__
+
/* Actual logic with traversal loop implementation which is free from device
* specific tweaks.
*
* Note that hits array should be as big as max_hits+1.
*/
ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
- const int skip_object,
+ const uint visibility,
Ray *ray,
Intersection *hits,
uint max_hits,
@@ -141,9 +174,12 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
const bool blocked = scene_intersect_shadow_all(kg,
ray,
hits,
- skip_object,
+ visibility,
max_hits,
&num_hits);
+# ifdef __VOLUME__
+ VolumeState volume_state;
+# endif
/* If no opaque surface found but we did find transparent hits,
* shade them.
*/
@@ -154,13 +190,11 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
int bounce = state->transparent_bounce;
Intersection *isect = hits;
# ifdef __VOLUME__
-# ifdef __SPLIT_KERNEL__
- ccl_addr_space PathState *ps = &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
-# else
- PathState ps_object;
- PathState *ps = &ps_object;
-# endif
- *ps = *state;
+ PathState *ps = shadow_blocked_volume_path_state(kg,
+ &volume_state,
+ state,
+ sd,
+ ray);
# endif
sort_intersections(hits, num_hits);
for(int hit = 0; hit < num_hits; hit++, isect++) {
@@ -205,8 +239,13 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
}
# ifdef __VOLUME__
if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* Apply attenuation from current volume shader/ */
- kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+ /* Apply attenuation from current volume shader. */
+ PathState *ps = shadow_blocked_volume_path_state(kg,
+ &volume_state,
+ state,
+ sd,
+ ray);
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, shadow);
}
# endif
return blocked;
@@ -216,9 +255,10 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
* loop to help readability of the actual logic.
*/
ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
- const int skip_object,
+ const uint visibility,
Ray *ray,
uint max_hits,
float3 *shadow)
@@ -251,9 +291,10 @@ ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
# endif /* __KERNEL_GPU__ */
/* Invoke actual traversal. */
return shadow_blocked_transparent_all_loop(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
hits,
max_hits,
@@ -276,27 +317,29 @@ ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
*/
ccl_device bool shadow_blocked_transparent_stepped_loop(
KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
- const int skip_object,
+ const uint visibility,
Ray *ray,
Intersection *isect,
const bool blocked,
const bool is_transparent_isect,
float3 *shadow)
{
- if((blocked && is_transparent_isect) || skip_object != OBJECT_NONE) {
+# ifdef __VOLUME__
+ VolumeState volume_state;
+# endif
+ if(blocked && is_transparent_isect) {
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
float3 Pend = ray->P + ray->D*ray->t;
int bounce = state->transparent_bounce;
# ifdef __VOLUME__
-# ifdef __SPLIT_KERNEL__
- ccl_addr_space PathState *ps = &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
-# else
- PathState ps_object;
- PathState *ps = &ps_object;
-# endif
- *ps = *state;
+ PathState *ps = shadow_blocked_volume_path_state(kg,
+ &volume_state,
+ state,
+ sd,
+ ray);
# endif
for(;;) {
if(bounce >= kernel_data.integrator.transparent_max_bounce) {
@@ -304,30 +347,13 @@ ccl_device bool shadow_blocked_transparent_stepped_loop(
}
if(!scene_intersect(kg,
*ray,
- PATH_RAY_SHADOW_TRANSPARENT,
+ visibility & PATH_RAY_SHADOW_TRANSPARENT,
isect,
NULL,
0.0f, 0.0f))
{
break;
}
-#ifdef __SHADOW_TRICKS__
- if(skip_object != OBJECT_NONE) {
- const int isect_object = (isect->object == PRIM_NONE)
- ? kernel_tex_fetch(__prim_object, isect->prim)
- : isect->object;
- if(isect_object == skip_object) {
- shader_setup_from_ray(kg, shadow_sd, isect, ray);
- /* Move ray forward. */
- ray->P = ray_offset(shadow_sd->P, -shadow_sd->Ng);
- if(ray->t != FLT_MAX) {
- ray->D = normalize_len(Pend - ray->P, &ray->t);
- }
- bounce++;
- continue;
- }
- }
-#endif
if(!shader_transparent_shadow(kg, isect)) {
return true;
}
@@ -363,7 +389,12 @@ ccl_device bool shadow_blocked_transparent_stepped_loop(
# ifdef __VOLUME__
if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
/* Apply attenuation from current volume shader. */
- kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+ PathState *ps = shadow_blocked_volume_path_state(kg,
+ &volume_state,
+ state,
+ sd,
+ ray);
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, shadow);
}
# endif
return blocked;
@@ -371,33 +402,28 @@ ccl_device bool shadow_blocked_transparent_stepped_loop(
ccl_device bool shadow_blocked_transparent_stepped(
KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
- const int skip_object,
+ const uint visibility,
Ray *ray,
Intersection *isect,
float3 *shadow)
{
- bool blocked, is_transparent_isect;
- if(skip_object == OBJECT_NONE) {
- blocked = scene_intersect(kg,
- *ray,
- PATH_RAY_SHADOW_OPAQUE,
- isect,
- NULL,
- 0.0f, 0.0f);
- is_transparent_isect = blocked
- ? shader_transparent_shadow(kg, isect)
- : false;
- }
- else {
- blocked = false;
- is_transparent_isect = false;
- }
+ bool blocked = scene_intersect(kg,
+ *ray,
+ visibility & PATH_RAY_SHADOW_OPAQUE,
+ isect,
+ NULL,
+ 0.0f, 0.0f);
+ bool is_transparent_isect = blocked
+ ? shader_transparent_shadow(kg, isect)
+ : false;
return shadow_blocked_transparent_stepped_loop(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
isect,
blocked,
@@ -409,6 +435,7 @@ ccl_device bool shadow_blocked_transparent_stepped(
#endif /* __TRANSPARENT_SHADOWS__ */
ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
Ray *ray_input,
@@ -422,25 +449,24 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
return false;
}
#ifdef __SHADOW_TRICKS__
- const int skip_object = state->catcher_object;
+ const uint visibility = (state->flag & PATH_RAY_SHADOW_CATCHER)
+ ? PATH_RAY_SHADOW_NON_CATCHER
+ : PATH_RAY_SHADOW;
#else
- const int skip_object = OBJECT_NONE;
+ const uint visibility = PATH_RAY_SHADOW;
#endif
/* Do actual shadow shading. */
/* First of all, we check if integrator requires transparent shadows.
* if not, we use simplest and fastest ever way to calculate occlusion.
- *
- * NOTE: We can't do quick opaque test here if we are on shadow-catcher
- * path because we don't want catcher object to be casting shadow here.
*/
#ifdef __TRANSPARENT_SHADOWS__
- if(!kernel_data.integrator.transparent_shadows &&
- skip_object == OBJECT_NONE)
+ if(!kernel_data.integrator.transparent_shadows)
#endif
{
return shadow_blocked_opaque(kg,
shadow_sd,
state,
+ visibility,
ray,
&isect,
shadow);
@@ -467,7 +493,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
*/
const bool blocked = scene_intersect(kg,
*ray,
- PATH_RAY_SHADOW_OPAQUE,
+ visibility & PATH_RAY_SHADOW_OPAQUE,
&isect,
NULL,
0.0f, 0.0f);
@@ -478,9 +504,10 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
max_hits + 1 >= SHADOW_STACK_MAX_HITS)
{
return shadow_blocked_transparent_stepped_loop(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
&isect,
blocked,
@@ -489,9 +516,10 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
}
# endif /* __KERNEL_GPU__ */
return shadow_blocked_transparent_all(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
max_hits,
shadow);
@@ -500,7 +528,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
return shadow_blocked_transparent_stepped(kg,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
&isect,
shadow);
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index 1026cde7b29..26ec6383b73 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -219,7 +219,7 @@ ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
if(bump || texture_blur > 0.0f) {
/* average color and normal at incoming point */
- shader_eval_surface(kg, sd, NULL, state, 0.0f, state_flag, SHADER_CONTEXT_SSS);
+ shader_eval_surface(kg, sd, state, 0.0f, state_flag);
float3 in_color = shader_bssrdf_sum(sd, (bump)? N: NULL, NULL);
/* we simply divide out the average color and multiply with the average
@@ -243,7 +243,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
SubsurfaceIntersection *ss_isect,
ShaderData *sd,
ShaderClosure *sc,
- RNG *lcg_state,
+ uint *lcg_state,
float disk_u,
float disk_v,
bool all)
@@ -418,7 +418,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
}
/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
-ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_global PathState *state,
+ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state,
int state_flag, ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index cb1a3f40dee..5eab28a2953 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -82,115 +82,110 @@ KERNEL_TEX(uint, texture_uint, __sobol_directions)
# if __CUDA_ARCH__ < 300
/* full-float image */
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_000)
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_001)
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_002)
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_003)
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_004)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_008)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_016)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_024)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_032)
KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_000)
-KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_001)
-KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_002)
-KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_003)
-KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_004)
-
-/* image */
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_005)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_006)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_007)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_008)
+KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_008)
+KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_016)
+KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_024)
+KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_032)
+
+/* image
+ * These texture names are encoded to their flattened slots as
+ * ImageManager::type_index_to_flattened_slot() returns them. */
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_001)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_009)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_010)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_011)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_012)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_013)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_014)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_015)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_016)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_017)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_018)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_019)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_020)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_021)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_022)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_023)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_024)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_025)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_026)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_027)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_028)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_029)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_030)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_031)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_032)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_033)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_034)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_035)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_036)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_037)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_038)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_039)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_040)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_041)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_042)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_043)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_044)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_045)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_046)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_047)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_048)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_049)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_050)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_051)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_052)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_053)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_054)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_055)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_056)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_057)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_058)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_059)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_060)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_061)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_062)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_063)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_064)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_065)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_066)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_067)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_068)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_069)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_070)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_071)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_072)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_073)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_074)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_075)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_076)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_077)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_078)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_079)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_080)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_081)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_082)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_083)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_084)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_085)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_086)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_087)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_088)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_089)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_097)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_105)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_113)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_121)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_129)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_137)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_145)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_153)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_161)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_169)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_177)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_185)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_193)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_201)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_209)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_217)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_225)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_233)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_241)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_249)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_257)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_265)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_273)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_281)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_289)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_297)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_305)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_313)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_321)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_329)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_337)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_345)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_353)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_361)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_369)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_377)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_385)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_393)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_401)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_409)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_417)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_425)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_433)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_441)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_449)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_457)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_465)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_473)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_481)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_489)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_497)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_505)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_513)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_521)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_529)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_537)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_545)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_553)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_561)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_569)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_577)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_585)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_593)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_601)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_609)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_617)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_625)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_633)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_641)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_649)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_657)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_665)
# else
/* bindless textures */
KERNEL_TEX(uint, texture_uint, __bindless_mapping)
-# endif
-#endif
-
-/* 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)
+# endif /* __CUDA_ARCH__ */
+#endif /* __KERNEL_CUDA__ */
#undef KERNEL_TEX
#undef KERNEL_IMAGE_TEX
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index dbeaffdfb24..8f65c00491c 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -130,12 +130,13 @@ CCL_NAMESPACE_BEGIN
# ifdef __KERNEL_OPENCL_APPLE__
# define __KERNEL_SHADING__
# define __KERNEL_ADV_SHADING__
+# define __PRINCIPLED__
# define __CMJ__
/* TODO(sergey): Currently experimental section is ignored here,
* this is because megakernel in device_opencl does not support
* custom cflags depending on the scene features.
*/
-# endif /* __KERNEL_OPENCL_NVIDIA__ */
+# endif /* __KERNEL_OPENCL_APPLE__ */
# ifdef __KERNEL_OPENCL_AMD__
# define __CL_USE_NATIVE__
@@ -154,6 +155,7 @@ CCL_NAMESPACE_BEGIN
# define __CL_USE_NATIVE__
# define __KERNEL_SHADING__
# define __KERNEL_ADV_SHADING__
+# define __PRINCIPLED__
# define __CMJ__
# endif /* __KERNEL_OPENCL_INTEL_CPU__ */
@@ -236,10 +238,9 @@ CCL_NAMESPACE_BEGIN
#ifdef __NO_PRINCIPLED__
# undef __PRINCIPLED__
#endif
-
-/* Random Numbers */
-
-typedef uint RNG;
+#ifdef __NO_DENOISING__
+# undef __DENOISING_FEATURES__
+#endif
/* Shader Evaluation */
@@ -325,24 +326,28 @@ enum PathRayFlag {
PATH_RAY_SINGULAR = (1 << 5),
PATH_RAY_TRANSPARENT = (1 << 6),
- PATH_RAY_SHADOW_OPAQUE = (1 << 7),
- PATH_RAY_SHADOW_TRANSPARENT = (1 << 8),
- PATH_RAY_SHADOW = (PATH_RAY_SHADOW_OPAQUE|PATH_RAY_SHADOW_TRANSPARENT),
+ PATH_RAY_SHADOW_OPAQUE_NON_CATCHER = (1 << 7),
+ PATH_RAY_SHADOW_OPAQUE_CATCHER = (1 << 8),
+ PATH_RAY_SHADOW_OPAQUE = (PATH_RAY_SHADOW_OPAQUE_NON_CATCHER|PATH_RAY_SHADOW_OPAQUE_CATCHER),
+ PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER = (1 << 9),
+ PATH_RAY_SHADOW_TRANSPARENT_CATCHER = (1 << 10),
+ PATH_RAY_SHADOW_TRANSPARENT = (PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER|PATH_RAY_SHADOW_TRANSPARENT_CATCHER),
+ PATH_RAY_SHADOW_NON_CATCHER = (PATH_RAY_SHADOW_OPAQUE_NON_CATCHER|PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER),
+ PATH_RAY_SHADOW = (PATH_RAY_SHADOW_OPAQUE|PATH_RAY_SHADOW_TRANSPARENT),
- PATH_RAY_CURVE = (1 << 9), /* visibility flag to define curve segments */
- PATH_RAY_VOLUME_SCATTER = (1 << 10), /* volume scattering */
+ PATH_RAY_CURVE = (1 << 11), /* visibility flag to define curve segments */
+ PATH_RAY_VOLUME_SCATTER = (1 << 12), /* volume scattering */
/* Special flag to tag unaligned BVH nodes. */
- PATH_RAY_NODE_UNALIGNED = (1 << 11),
+ PATH_RAY_NODE_UNALIGNED = (1 << 13),
- PATH_RAY_ALL_VISIBILITY = ((1 << 12)-1),
+ PATH_RAY_ALL_VISIBILITY = ((1 << 14)-1),
- PATH_RAY_MIS_SKIP = (1 << 12),
- PATH_RAY_DIFFUSE_ANCESTOR = (1 << 13),
- PATH_RAY_SINGLE_PASS_DONE = (1 << 14),
- PATH_RAY_SHADOW_CATCHER = (1 << 15),
- PATH_RAY_SHADOW_CATCHER_ONLY = (1 << 16),
- PATH_RAY_STORE_SHADOW_INFO = (1 << 17),
+ PATH_RAY_MIS_SKIP = (1 << 15),
+ PATH_RAY_DIFFUSE_ANCESTOR = (1 << 16),
+ PATH_RAY_SINGLE_PASS_DONE = (1 << 17),
+ PATH_RAY_SHADOW_CATCHER = (1 << 18),
+ PATH_RAY_STORE_SHADOW_INFO = (1 << 19),
};
/* Closure Label */
@@ -459,11 +464,24 @@ typedef enum DenoiseFlag {
DENOISING_CLEAN_ALL_PASSES = (1 << 8)-1,
} DenoiseFlag;
+#ifdef __KERNEL_DEBUG__
+/* NOTE: This is a runtime-only struct, alignment is not
+ * really important here.
+ */
+typedef struct DebugData {
+ int num_bvh_traversed_nodes;
+ int num_bvh_traversed_instances;
+ int num_bvh_intersections;
+ int num_ray_bounces;
+} DebugData;
+#endif
+
typedef ccl_addr_space struct PathRadiance {
#ifdef __PASSES__
int use_light_pass;
#endif
+ float transparent;
float3 emission;
#ifdef __PASSES__
float3 background;
@@ -512,7 +530,16 @@ typedef ccl_addr_space struct PathRadiance {
float3 path_total_shaded;
/* Color of the background on which shadow is alpha-overed. */
- float3 shadow_color;
+ float3 shadow_background_color;
+
+ /* Path radiance sum and throughput at the moment when ray hits shadow
+ * catcher object.
+ */
+ float3 shadow_radiance_sum;
+ float shadow_throughput;
+
+ /* Accumulated transparency along the path after shadow catcher bounce. */
+ float shadow_transparency;
#endif
#ifdef __DENOISING_FEATURES__
@@ -520,6 +547,10 @@ typedef ccl_addr_space struct PathRadiance {
float3 denoising_albedo;
float denoising_depth;
#endif /* __DENOISING_FEATURES__ */
+
+#ifdef __KERNEL_DEBUG__
+ DebugData debug_data;
+#endif /* __KERNEL_DEBUG__ */
} PathRadiance;
typedef struct BsdfEval {
@@ -771,20 +802,6 @@ typedef ccl_addr_space struct ccl_align(16) ShaderClosure {
float data[10]; /* pad to 80 bytes */
} ShaderClosure;
-/* Shader Context
- *
- * For OSL we recycle a fixed number of contexts for speed */
-
-typedef enum ShaderContext {
- SHADER_CONTEXT_MAIN = 0,
- SHADER_CONTEXT_INDIRECT = 1,
- SHADER_CONTEXT_EMISSION = 2,
- SHADER_CONTEXT_SHADOW = 3,
- SHADER_CONTEXT_SSS = 4,
- SHADER_CONTEXT_VOLUME = 5,
- SHADER_CONTEXT_NUM = 6
-} ShaderContext;
-
/* Shader Data
*
* Main shader state at a point on the surface or in a volume. All coordinates
@@ -847,7 +864,7 @@ enum ShaderDataFlag {
SD_VOLUME_MIS = (1 << 23),
/* Use cubic interpolation for voxels. */
SD_VOLUME_CUBIC = (1 << 24),
- /* Has data connected to the displacement input. */
+ /* Has data connected to the displacement input or uses bump map. */
SD_HAS_BUMP = (1 << 25),
/* Has true displacement. */
SD_HAS_DISPLACEMENT = (1 << 26),
@@ -988,6 +1005,7 @@ typedef struct PathState {
int flag;
/* random number generator state */
+ uint rng_hash; /* per pixel hash */
int rng_offset; /* dimension offset */
int sample; /* path sample number */
int num_samples; /* total number of times this path will be sampled */
@@ -1013,13 +1031,9 @@ typedef struct PathState {
/* volume rendering */
#ifdef __VOLUME__
int volume_bounce;
- RNG rng_congruential;
+ uint rng_congruential;
VolumeStack volume_stack[VOLUME_STACK_SIZE];
#endif
-
-#ifdef __SHADOW_TRICKS__
- int catcher_object;
-#endif
} PathState;
/* Subsurface */
@@ -1225,7 +1239,6 @@ typedef struct KernelIntegrator {
int portal_offset;
/* bounces */
- int min_bounce;
int max_bounce;
int max_diffuse_bounce;
@@ -1236,7 +1249,6 @@ typedef struct KernelIntegrator {
int ao_bounces;
/* transparent */
- int transparent_min_bounce;
int transparent_max_bounce;
int transparent_shadows;
@@ -1279,7 +1291,7 @@ typedef struct KernelIntegrator {
float light_inv_rr_threshold;
int start_sample;
- int pad1, pad2, pad3;
+ int pad1;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);
@@ -1333,18 +1345,6 @@ typedef struct KernelData {
} 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 {
- int num_bvh_traversed_nodes;
- int num_bvh_traversed_instances;
- int num_bvh_intersections;
- int num_ray_bounces;
-} DebugData;
-#endif
-
/* Declarations required for split kernel */
/* Macro for queues */
@@ -1387,6 +1387,8 @@ enum QueueNumber {
#ifdef __BRANCHED_PATH__
/* All rays moving to next iteration of the indirect loop for light */
QUEUE_LIGHT_INDIRECT_ITER,
+ /* Queue of all inactive rays. These are candidates for sharing work of indirect loops */
+ QUEUE_INACTIVE_RAYS,
# ifdef __VOLUME__
/* All rays moving to next iteration of the indirect loop for volumes */
QUEUE_VOLUME_INDIRECT_ITER,
@@ -1429,6 +1431,9 @@ enum RayState {
RAY_BRANCHED_VOLUME_INDIRECT = (1 << 5),
RAY_BRANCHED_SUBSURFACE_INDIRECT = (1 << 6),
RAY_BRANCHED_INDIRECT = (RAY_BRANCHED_LIGHT_INDIRECT | RAY_BRANCHED_VOLUME_INDIRECT | RAY_BRANCHED_SUBSURFACE_INDIRECT),
+
+ /* Ray is evaluating an iteration of an indirect loop for another thread */
+ RAY_BRANCHED_INDIRECT_SHARED = (1 << 7),
};
#define ASSIGN_RAY_STATE(ray_state, ray_index, state) (ray_state[ray_index] = ((ray_state[ray_index] & RAY_FLAG_MASK) | state))
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 9c0878249d4..42094a9c3f8 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -43,7 +43,7 @@ ccl_device_inline bool volume_shader_extinction_sample(KernelGlobals *kg,
float3 *extinction)
{
sd->P = P;
- shader_eval_volume(kg, sd, state, state->volume_stack, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
+ shader_eval_volume(kg, sd, state, state->volume_stack, PATH_RAY_SHADOW);
if(!(sd->flag & (SD_ABSORPTION|SD_SCATTER)))
return false;
@@ -69,7 +69,7 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals *kg,
VolumeShaderCoefficients *coeff)
{
sd->P = P;
- shader_eval_volume(kg, sd, state, state->volume_stack, state->flag, SHADER_CONTEXT_VOLUME);
+ shader_eval_volume(kg, sd, state, state->volume_stack, state->flag);
if(!(sd->flag & (SD_ABSORPTION|SD_SCATTER|SD_EMISSION)))
return false;
@@ -360,7 +360,6 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
ShaderData *sd,
PathRadiance *L,
ccl_addr_space float3 *throughput,
- RNG *rng,
bool probalistic_scatter)
{
VolumeShaderCoefficients coeff;
@@ -380,13 +379,13 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
/* pick random color channel, we use the Veach one-sample
* model with balance heuristic for the channels */
- float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
+ float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE);
int channel = (int)(rphase*3.0f);
sd->randb_closure = rphase*3.0f - channel;
/* decide if we will hit or miss */
bool scatter = true;
- float xi = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
+ float xi = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE);
if(probalistic_scatter) {
float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
@@ -468,8 +467,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
Ray *ray,
ShaderData *sd,
PathRadiance *L,
- ccl_addr_space float3 *throughput,
- RNG *rng)
+ ccl_addr_space float3 *throughput)
{
float3 tp = *throughput;
const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
@@ -485,8 +483,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
/* pick random color channel, we use the Veach one-sample
* model with balance heuristic for the channels */
- float xi = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
- float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
+ float xi = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE);
+ float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE);
int channel = (int)(rphase*3.0f);
sd->randb_closure = rphase*3.0f - channel;
bool has_scatter = false;
@@ -610,15 +608,14 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(
Ray *ray,
PathRadiance *L,
ccl_addr_space float3 *throughput,
- RNG *rng,
bool heterogeneous)
{
shader_setup_from_volume(kg, sd, ray);
if(heterogeneous)
- return kernel_volume_integrate_heterogeneous_distance(kg, state, ray, sd, L, throughput, rng);
+ return kernel_volume_integrate_heterogeneous_distance(kg, state, ray, sd, L, throughput);
else
- return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, rng, true);
+ return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, true);
}
#ifndef __SPLIT_KERNEL__
@@ -660,6 +657,7 @@ typedef struct VolumeSegment {
* but the entire segment is needed to do always scattering, rather than probabilistically
* hitting or missing the volume. if we don't know the transmittance at the end of the
* volume we can't generate stratified distance samples up to that transmittance */
+#ifdef __VOLUME_DECOUPLED__
ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *state,
Ray *ray, ShaderData *sd, VolumeSegment *segment, bool heterogeneous)
{
@@ -829,6 +827,7 @@ ccl_device void kernel_volume_decoupled_free(KernelGlobals *kg, VolumeSegment *s
#endif
}
}
+#endif /* __VOLUME_DECOUPLED__ */
/* scattering for homogeneous and heterogeneous volumes, using decoupled ray
* marching.
diff --git a/intern/cycles/kernel/kernels/cpu/filter_cpu.h b/intern/cycles/kernel/kernels/cpu/filter_cpu.h
index ffd34c293fc..2ed713299fd 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_cpu.h
+++ b/intern/cycles/kernel/kernels/cpu/filter_cpu.h
@@ -107,8 +107,6 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_construct_gramian)(int dx,
int dy,
float *difference_image,
float *buffer,
- float *color_pass,
- float *variance_pass,
float *transform,
int *rank,
float *XtWX,
diff --git a/intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h
index 261176846b1..8dc1a8d583c 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h
+++ b/intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h
@@ -213,8 +213,6 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_construct_gramian)(int dx,
int dy,
float *difference_image,
float *buffer,
- float *color_pass,
- float *variance_pass,
float *transform,
int *rank,
float *XtWX,
@@ -229,7 +227,7 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_construct_gramian)(int dx,
#ifdef KERNEL_STUB
STUB_ASSERT(KERNEL_ARCH, filter_nlm_construct_gramian);
#else
- kernel_filter_nlm_construct_gramian(dx, dy, difference_image, buffer, color_pass, variance_pass, transform, rank, XtWX, XtWY, load_int4(rect), load_int4(filter_rect), w, h, f, pass_stride);
+ kernel_filter_nlm_construct_gramian(dx, dy, difference_image, buffer, transform, rank, XtWX, XtWY, load_int4(rect), load_int4(filter_rect), w, h, f, pass_stride);
#endif
}
diff --git a/intern/cycles/kernel/kernels/cpu/filter_sse41.cpp b/intern/cycles/kernel/kernels/cpu/filter_sse41.cpp
index 1a7b2040da1..254025be4e2 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_sse41.cpp
+++ b/intern/cycles/kernel/kernels/cpu/filter_sse41.cpp
@@ -25,6 +25,7 @@
#else
/* SSE optimization disabled for now on 32 bit, see bug #36316 */
# if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+# define __KERNEL_SSE__
# define __KERNEL_SSE2__
# define __KERNEL_SSE3__
# define __KERNEL_SSSE3__
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
index 9895080d328..c8938534fe8 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
@@ -85,6 +85,7 @@ DECLARE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
DECLARE_SPLIT_KERNEL_FUNCTION(direct_lighting)
DECLARE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
DECLARE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
+DECLARE_SPLIT_KERNEL_FUNCTION(enqueue_inactive)
DECLARE_SPLIT_KERNEL_FUNCTION(next_iteration_setup)
DECLARE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
DECLARE_SPLIT_KERNEL_FUNCTION(buffer_update)
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
index 9b85a864153..d4315ee5ec4 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
@@ -53,6 +53,7 @@
# include "kernel/split/kernel_direct_lighting.h"
# include "kernel/split/kernel_shadow_blocked_ao.h"
# include "kernel/split/kernel_shadow_blocked_dl.h"
+# include "kernel/split/kernel_enqueue_inactive.h"
# include "kernel/split/kernel_next_iteration_setup.h"
# include "kernel/split/kernel_indirect_subsurface.h"
# include "kernel/split/kernel_buffer_update.h"
@@ -230,6 +231,7 @@ DEFINE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(enqueue_inactive, uint)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(next_iteration_setup, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(buffer_update, uint)
diff --git a/intern/cycles/kernel/kernels/cuda/filter.cu b/intern/cycles/kernel/kernels/cuda/filter.cu
index 2edbff08087..009c3fde9d5 100644
--- a/intern/cycles/kernel/kernels/cuda/filter.cu
+++ b/intern/cycles/kernel/kernels/cuda/filter.cu
@@ -207,8 +207,6 @@ CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
kernel_cuda_filter_nlm_construct_gramian(int dx, int dy,
const float *ccl_restrict difference_image,
const float *ccl_restrict buffer,
- float *color_pass,
- float *variance_pass,
float const* __restrict__ transform,
int *rank,
float *XtWX,
@@ -225,7 +223,6 @@ kernel_cuda_filter_nlm_construct_gramian(int dx, int dy,
dx, dy,
difference_image,
buffer,
- color_pass, variance_pass,
transform, rank,
XtWX, XtWY,
rect, filter_rect,
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_config.h b/intern/cycles/kernel/kernels/cuda/kernel_config.h
index 9fa39dc9ebb..7ae205b7e14 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel_config.h
+++ b/intern/cycles/kernel/kernels/cuda/kernel_config.h
@@ -81,8 +81,13 @@
# error "Unknown or unsupported CUDA architecture, can't determine launch bounds"
#endif
-/* compute number of threads per block and minimum blocks per multiprocessor
- * given the maximum number of registers per thread */
+/* For split kernel using all registers seems fastest for now, but this
+ * is unlikely to be optimal once we resolve other bottlenecks. */
+
+#define CUDA_KERNEL_SPLIT_MAX_REGISTERS CUDA_THREAD_MAX_REGISTERS
+
+/* Compute number of threads per block and minimum blocks per multiprocessor
+ * given the maximum number of registers per thread. */
#define CUDA_LAUNCH_BOUNDS(threads_block_width, thread_num_registers) \
__launch_bounds__( \
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_split.cu b/intern/cycles/kernel/kernels/cuda/kernel_split.cu
index 8b7f1a8d405..e97e87285a5 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel_split.cu
+++ b/intern/cycles/kernel/kernels/cuda/kernel_split.cu
@@ -39,6 +39,7 @@
#include "kernel/split/kernel_direct_lighting.h"
#include "kernel/split/kernel_shadow_blocked_ao.h"
#include "kernel/split/kernel_shadow_blocked_dl.h"
+#include "kernel/split/kernel_enqueue_inactive.h"
#include "kernel/split/kernel_next_iteration_setup.h"
#include "kernel/split/kernel_indirect_subsurface.h"
#include "kernel/split/kernel_buffer_update.h"
@@ -89,7 +90,7 @@ kernel_cuda_path_trace_data_init(
#define DEFINE_SPLIT_KERNEL_FUNCTION(name) \
extern "C" __global__ void \
- CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS) \
+ CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_SPLIT_MAX_REGISTERS) \
kernel_cuda_##name() \
{ \
kernel_##name(NULL); \
@@ -97,7 +98,7 @@ kernel_cuda_path_trace_data_init(
#define DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(name, type) \
extern "C" __global__ void \
- CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS) \
+ CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_SPLIT_MAX_REGISTERS) \
kernel_cuda_##name() \
{ \
ccl_local type locals; \
@@ -118,6 +119,7 @@ DEFINE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(enqueue_inactive, uint)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(next_iteration_setup, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(buffer_update, uint)
diff --git a/intern/cycles/kernel/kernels/opencl/filter.cl b/intern/cycles/kernel/kernels/opencl/filter.cl
index 0462ca6f9bc..ba53ba4b26f 100644
--- a/intern/cycles/kernel/kernels/opencl/filter.cl
+++ b/intern/cycles/kernel/kernels/opencl/filter.cl
@@ -207,8 +207,6 @@ __kernel void kernel_ocl_filter_nlm_construct_gramian(int dx,
int dy,
const ccl_global float *ccl_restrict difference_image,
const ccl_global float *ccl_restrict buffer,
- ccl_global float *color_pass,
- ccl_global float *variance_pass,
const ccl_global float *ccl_restrict transform,
ccl_global int *rank,
ccl_global float *XtWX,
@@ -227,7 +225,6 @@ __kernel void kernel_ocl_filter_nlm_construct_gramian(int dx,
dx, dy,
difference_image,
buffer,
- color_pass, variance_pass,
transform, rank,
XtWX, XtWY,
rect, filter_rect,
diff --git a/intern/cycles/kernel/kernels/opencl/kernel.cl b/intern/cycles/kernel/kernels/opencl/kernel.cl
index 078acc1631e..b7108f3d0f8 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel.cl
@@ -52,9 +52,7 @@ __kernel void kernel_ocl_path_trace(
ccl_global float *buffer,
ccl_global uint *rng_state,
-#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name,
-#include "kernel/kernel_textures.h"
+ KERNEL_BUFFER_PARAMS,
int sample,
int sx, int sy, int sw, int sh, int offset, int stride)
@@ -63,9 +61,8 @@ __kernel void kernel_ocl_path_trace(
kg->data = data;
-#define KERNEL_TEX(type, ttype, name) \
- kg->name = name;
-#include "kernel/kernel_textures.h"
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
+ kernel_set_buffer_info(kg);
int x = sx + ccl_global_id(0);
int y = sy + ccl_global_id(1);
@@ -82,9 +79,7 @@ __kernel void kernel_ocl_shader(
ccl_global float4 *output,
ccl_global float *output_luma,
-#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name,
-#include "kernel/kernel_textures.h"
+ KERNEL_BUFFER_PARAMS,
int type, int sx, int sw, int offset, int sample)
{
@@ -92,9 +87,8 @@ __kernel void kernel_ocl_shader(
kg->data = data;
-#define KERNEL_TEX(type, ttype, name) \
- kg->name = name;
-#include "kernel/kernel_textures.h"
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
+ kernel_set_buffer_info(kg);
int x = sx + ccl_global_id(0);
@@ -114,9 +108,7 @@ __kernel void kernel_ocl_bake(
ccl_global uint4 *input,
ccl_global float4 *output,
-#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name,
-#include "kernel/kernel_textures.h"
+ KERNEL_BUFFER_PARAMS,
int type, int filter, int sx, int sw, int offset, int sample)
{
@@ -124,9 +116,8 @@ __kernel void kernel_ocl_bake(
kg->data = data;
-#define KERNEL_TEX(type, ttype, name) \
- kg->name = name;
-#include "kernel/kernel_textures.h"
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
+ kernel_set_buffer_info(kg);
int x = sx + ccl_global_id(0);
@@ -144,9 +135,7 @@ __kernel void kernel_ocl_convert_to_byte(
ccl_global uchar4 *rgba,
ccl_global float *buffer,
-#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name,
-#include "kernel/kernel_textures.h"
+ KERNEL_BUFFER_PARAMS,
float sample_scale,
int sx, int sy, int sw, int sh, int offset, int stride)
@@ -155,9 +144,8 @@ __kernel void kernel_ocl_convert_to_byte(
kg->data = data;
-#define KERNEL_TEX(type, ttype, name) \
- kg->name = name;
-#include "kernel/kernel_textures.h"
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
+ kernel_set_buffer_info(kg);
int x = sx + ccl_global_id(0);
int y = sy + ccl_global_id(1);
@@ -171,9 +159,7 @@ __kernel void kernel_ocl_convert_to_half_float(
ccl_global uchar4 *rgba,
ccl_global float *buffer,
-#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name,
-#include "kernel/kernel_textures.h"
+ KERNEL_BUFFER_PARAMS,
float sample_scale,
int sx, int sy, int sw, int sh, int offset, int stride)
@@ -182,9 +168,8 @@ __kernel void kernel_ocl_convert_to_half_float(
kg->data = data;
-#define KERNEL_TEX(type, ttype, name) \
- kg->name = name;
-#include "kernel/kernel_textures.h"
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
+ kernel_set_buffer_info(kg);
int x = sx + ccl_global_id(0);
int y = sy + ccl_global_id(1);
@@ -193,7 +178,7 @@ __kernel void kernel_ocl_convert_to_half_float(
kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride);
}
-__kernel void kernel_ocl_zero_buffer(ccl_global float4 *buffer, ulong size, ulong offset)
+__kernel void kernel_ocl_zero_buffer(ccl_global float4 *buffer, uint64_t size, uint64_t offset)
{
size_t i = ccl_global_id(0) + ccl_global_id(1) * ccl_global_size(0);
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl b/intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl
index db65c91baf7..dcea2630aef 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl
@@ -18,10 +18,9 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_buffer_update.h"
-__kernel void kernel_ocl_path_trace_buffer_update(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- ccl_local unsigned int local_queue_atomics;
- kernel_buffer_update((KernelGlobals*)kg, &local_queue_atomics);
-}
+#define KERNEL_NAME buffer_update
+#define LOCALS_TYPE unsigned int
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+#undef LOCALS_TYPE
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl b/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl
index 8b85d362f8a..95b35e40a45 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl
@@ -25,11 +25,7 @@ __kernel void kernel_ocl_path_trace_data_init(
int num_elements,
ccl_global char *ray_state,
ccl_global uint *rng_state,
-
-#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name,
-#include "kernel/kernel_textures.h"
-
+ KERNEL_BUFFER_PARAMS,
int start_sample,
int end_sample,
int sx, int sy, int sw, int sh, int offset, int stride,
@@ -46,10 +42,7 @@ __kernel void kernel_ocl_path_trace_data_init(
num_elements,
ray_state,
rng_state,
-
-#define KERNEL_TEX(type, ttype, name) name,
-#include "kernel/kernel_textures.h"
-
+ KERNEL_BUFFER_ARGS,
start_sample,
end_sample,
sx, sy, sw, sh, offset, stride,
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl b/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl
index eb34f750881..ed64ae01aae 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl
@@ -18,10 +18,9 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_direct_lighting.h"
-__kernel void kernel_ocl_path_trace_direct_lighting(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- ccl_local unsigned int local_queue_atomics;
- kernel_direct_lighting((KernelGlobals*)kg, &local_queue_atomics);
-}
+#define KERNEL_NAME direct_lighting
+#define LOCALS_TYPE unsigned int
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+#undef LOCALS_TYPE
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl b/intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl
index 83ef5f5f3f2..8afaa686e28 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_do_volume.h"
-__kernel void kernel_ocl_path_trace_do_volume(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_do_volume((KernelGlobals*)kg);
-}
+#define KERNEL_NAME do_volume
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_enqueue_inactive.cl b/intern/cycles/kernel/kernels/opencl/kernel_enqueue_inactive.cl
new file mode 100644
index 00000000000..e68d4104a91
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_enqueue_inactive.cl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011-2017 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_enqueue_inactive.h"
+
+#define KERNEL_NAME enqueue_inactive
+#define LOCALS_TYPE unsigned int
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+#undef LOCALS_TYPE
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl b/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
index d071b39aa6f..9e1e57beba6 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
@@ -18,12 +18,9 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h"
-__kernel void kernel_ocl_path_trace_holdout_emission_blurring_pathtermination_ao(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- ccl_local BackgroundAOLocals locals;
- kernel_holdout_emission_blurring_pathtermination_ao(
- (KernelGlobals*)kg,
- &locals);
-}
+#define KERNEL_NAME holdout_emission_blurring_pathtermination_ao
+#define LOCALS_TYPE BackgroundAOLocals
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+#undef LOCALS_TYPE
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl b/intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl
index 8c213ff5cb2..192d01444ba 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_indirect_background.h"
-__kernel void kernel_ocl_path_trace_indirect_background(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_indirect_background((KernelGlobals*)kg);
-}
+#define KERNEL_NAME indirect_background
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl b/intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl
index 998ebc4c0c3..84938b889e5 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_indirect_subsurface.h"
-__kernel void kernel_ocl_path_trace_indirect_subsurface(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_indirect_subsurface((KernelGlobals*)kg);
-}
+#define KERNEL_NAME indirect_subsurface
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl b/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl
index 822d2287715..c314dc96c33 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_lamp_emission.h"
-__kernel void kernel_ocl_path_trace_lamp_emission(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_lamp_emission((KernelGlobals*)kg);
-}
+#define KERNEL_NAME lamp_emission
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl b/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl
index 6d207253a40..8b1332bf013 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl
@@ -18,10 +18,9 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_next_iteration_setup.h"
-__kernel void kernel_ocl_path_trace_next_iteration_setup(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- ccl_local unsigned int local_queue_atomics;
- kernel_next_iteration_setup((KernelGlobals*)kg, &local_queue_atomics);
-}
+#define KERNEL_NAME next_iteration_setup
+#define LOCALS_TYPE unsigned int
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+#undef LOCALS_TYPE
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_path_init.cl b/intern/cycles/kernel/kernels/opencl/kernel_path_init.cl
index bd9aa9538c8..fa210e747c0 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_path_init.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_path_init.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_path_init.h"
-__kernel void kernel_ocl_path_trace_path_init(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_path_init((KernelGlobals*)kg);
-}
+#define KERNEL_NAME path_init
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl b/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl
index 9be154e3d75..68ee6f1d536 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl
@@ -18,10 +18,9 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_queue_enqueue.h"
-__kernel void kernel_ocl_path_trace_queue_enqueue(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- ccl_local QueueEnqueueLocals locals;
- kernel_queue_enqueue((KernelGlobals*)kg, &locals);
-}
+#define KERNEL_NAME queue_enqueue
+#define LOCALS_TYPE QueueEnqueueLocals
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+#undef LOCALS_TYPE
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl b/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl
index eb4fb4d153a..10d09377ba9 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_scene_intersect.h"
-__kernel void kernel_ocl_path_trace_scene_intersect(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_scene_intersect((KernelGlobals*)kg);
-}
+#define KERNEL_NAME scene_intersect
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl b/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl
index 5bfb31b193a..40eaa561863 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_shader_eval.h"
-__kernel void kernel_ocl_path_trace_shader_eval(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_shader_eval((KernelGlobals*)kg);
-}
+#define KERNEL_NAME shader_eval
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl b/intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl
index 38bfd04ad4c..8c36100f762 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl
@@ -18,10 +18,9 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_shader_setup.h"
-__kernel void kernel_ocl_path_trace_shader_setup(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- ccl_local unsigned int local_queue_atomics;
- kernel_shader_setup((KernelGlobals*)kg, &local_queue_atomics);
-}
+#define KERNEL_NAME shader_setup
+#define LOCALS_TYPE unsigned int
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+#undef LOCALS_TYPE
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl b/intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl
index 6f722915d45..bcacaa4a054 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl
@@ -19,10 +19,9 @@
#include "kernel/split/kernel_shader_sort.h"
__attribute__((reqd_work_group_size(64, 1, 1)))
-__kernel void kernel_ocl_path_trace_shader_sort(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- ccl_local ShaderSortLocals locals;
- kernel_shader_sort((KernelGlobals*)kg, &locals);
-}
+#define KERNEL_NAME shader_sort
+#define LOCALS_TYPE ShaderSortLocals
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+#undef LOCALS_TYPE
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl
index 6a8ef81b32a..8de250a375c 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_shadow_blocked_ao.h"
-__kernel void kernel_ocl_path_trace_shadow_blocked_ao(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_shadow_blocked_ao((KernelGlobals*)kg);
-}
+#define KERNEL_NAME shadow_blocked_ao
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl
index b255cc5ef8b..29da77022ed 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_shadow_blocked_dl.h"
-__kernel void kernel_ocl_path_trace_shadow_blocked_dl(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_shadow_blocked_dl((KernelGlobals*)kg);
-}
+#define KERNEL_NAME shadow_blocked_dl
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_split.cl b/intern/cycles/kernel/kernels/opencl/kernel_split.cl
index 8de82db7afe..4cbda1bc2e7 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_split.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_split.cl
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#include "kernel/kernel_compat_opencl.h" // PRECOMPILED
+#include "kernel/split/kernel_split_common.h" // PRECOMPILED
+
#include "kernel/kernels/opencl/kernel_state_buffer_size.cl"
#include "kernel/kernels/opencl/kernel_data_init.cl"
#include "kernel/kernels/opencl/kernel_path_init.cl"
@@ -31,6 +34,7 @@
#include "kernel/kernels/opencl/kernel_direct_lighting.cl"
#include "kernel/kernels/opencl/kernel_shadow_blocked_ao.cl"
#include "kernel/kernels/opencl/kernel_shadow_blocked_dl.cl"
+#include "kernel/kernels/opencl/kernel_enqueue_inactive.cl"
#include "kernel/kernels/opencl/kernel_next_iteration_setup.cl"
#include "kernel/kernels/opencl/kernel_indirect_subsurface.cl"
#include "kernel/kernels/opencl/kernel_buffer_update.cl"
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_split_function.h b/intern/cycles/kernel/kernels/opencl/kernel_split_function.h
new file mode 100644
index 00000000000..591c3846ef2
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_split_function.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2011-2017 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.
+ */
+
+#define KERNEL_NAME_JOIN(a, b) a ## _ ## b
+#define KERNEL_NAME_EVAL(a, b) KERNEL_NAME_JOIN(a, b)
+
+__kernel void KERNEL_NAME_EVAL(kernel_ocl_path_trace, KERNEL_NAME)(
+ ccl_global char *kg_global,
+ ccl_constant KernelData *data,
+
+ ccl_global void *split_data_buffer,
+ ccl_global char *ray_state,
+ ccl_global uint *rng_state,
+
+ KERNEL_BUFFER_PARAMS,
+
+ ccl_global int *queue_index,
+ ccl_global char *use_queues_flag,
+ ccl_global unsigned int *work_pools,
+ ccl_global float *buffer
+ )
+{
+#ifdef LOCALS_TYPE
+ ccl_local LOCALS_TYPE locals;
+#endif
+
+ KernelGlobals *kg = (KernelGlobals*)kg_global;
+
+ if(ccl_local_id(0) + ccl_local_id(1) == 0) {
+ kg->data = data;
+
+ kernel_split_params.rng_state = rng_state;
+ kernel_split_params.queue_index = queue_index;
+ kernel_split_params.use_queues_flag = use_queues_flag;
+ kernel_split_params.work_pools = work_pools;
+ kernel_split_params.buffer = buffer;
+
+ split_data_init(kg, &kernel_split_state, ccl_global_size(0)*ccl_global_size(1), split_data_buffer, ray_state);
+
+ }
+
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
+
+ KERNEL_NAME_EVAL(kernel, KERNEL_NAME)(
+ kg
+#ifdef LOCALS_TYPE
+ , &locals
+#endif
+ );
+}
+
+#undef KERNEL_NAME_JOIN
+#undef KERNEL_NAME_EVAL
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl b/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl
index 99b74a1802b..2b3be38df84 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl
@@ -18,9 +18,7 @@
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_subsurface_scatter.h"
-__kernel void kernel_ocl_path_trace_subsurface_scatter(
- ccl_global char *kg,
- ccl_constant KernelData *data)
-{
- kernel_subsurface_scatter((KernelGlobals*)kg);
-}
+#define KERNEL_NAME subsurface_scatter
+#include "kernel/kernels/opencl/kernel_split_function.h"
+#undef KERNEL_NAME
+
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index 188c3960a5f..27a96720c1e 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -191,7 +191,7 @@ class PrincipledBSSRDFClosure : public CBSSRDFClosure {
public:
void setup(ShaderData *sd, int path_flag, float3 weight)
{
- alloc(sd, path_flag, weight * albedo, CLOSURE_BSSRDF_PRINCIPLED_ID);
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_PRINCIPLED_ID);
}
};
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 5b66793a05d..14c5c1c3db5 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -156,7 +156,7 @@ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refra
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction)
BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, unused),
+ CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.N),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness1),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness2),
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
@@ -164,7 +164,7 @@ BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY
BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection)
BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, HairBsdf, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, unused),
+ CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, params.N),
CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness1),
CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness2),
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
@@ -191,7 +191,7 @@ BSDF_CLOSURE_CLASS_END(PrincipledSheen, principled_sheen)
class PrincipledClearcoatClosure : public CBSDFClosure {
public:
MicrofacetBsdf params;
- float clearcoat, clearcoat_gloss;
+ float clearcoat, clearcoat_roughness;
MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
{
@@ -202,8 +202,8 @@ public:
bsdf->ior = 1.5f;
- bsdf->alpha_x = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
- bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
+ bsdf->alpha_x = clearcoat_roughness;
+ bsdf->alpha_y = clearcoat_roughness;
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
bsdf->extra->clearcoat = clearcoat;
@@ -217,7 +217,7 @@ public:
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- sd->flag |= (bsdf) ? bsdf_microfacet_ggx_clearcoat_setup(bsdf) : 0;
+ sd->flag |= (bsdf) ? bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd) : 0;
}
};
@@ -226,7 +226,7 @@ ClosureParam *closure_bsdf_principled_clearcoat_params()
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(PrincipledClearcoatClosure, params.N),
CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat),
- CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_gloss),
+ CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_roughness),
CLOSURE_STRING_KEYPARAM(PrincipledClearcoatClosure, label, "label"),
CLOSURE_FINISH_PARAM(PrincipledClearcoatClosure)
};
@@ -389,7 +389,7 @@ public:
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- sd->flag |= (bsdf) ? bsdf_microfacet_ggx_fresnel_setup(bsdf) : 0;
+ sd->flag |= (bsdf) ? bsdf_microfacet_ggx_fresnel_setup(bsdf, sd) : 0;
}
};
@@ -413,7 +413,7 @@ public:
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- sd->flag |= (bsdf) ? bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf) : 0;
+ sd->flag |= (bsdf) ? bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd) : 0;
}
};
@@ -566,7 +566,7 @@ public:
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_fresnel_setup(bsdf) : 0;
+ sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd) : 0;
}
};
@@ -590,7 +590,7 @@ public:
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf) : 0;
+ sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd) : 0;
}
};
@@ -618,7 +618,7 @@ public:
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf) : 0;
+ sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd) : 0;
}
};
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
index 02c083a83f8..9585d9f4825 100644
--- a/intern/cycles/kernel/osl/osl_globals.h
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -86,7 +86,7 @@ struct OSLThreadData {
OSL::ShaderGlobals globals;
OSL::PerThreadInfo *osl_thread_info;
OSLTraceData tracedata;
- OSL::ShadingContext *context[SHADER_CONTEXT_NUM];
+ OSL::ShadingContext *context;
OIIO::TextureSystem::Perthread *oiio_thread_info;
};
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index b767c60c617..8ad2e12b067 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -824,7 +824,7 @@ bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *
bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg, bool derivatives, ustring object_name,
TypeDesc type, ustring name, void *val)
{
- if(sg->renderstate == NULL)
+ if(sg == NULL || sg->renderstate == NULL)
return false;
ShaderData *sd = (ShaderData *)(sg->renderstate);
@@ -1197,8 +1197,9 @@ bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
tracedata->init = true;
tracedata->sd.osl_globals = sd->osl_globals;
- /* raytrace */
- return scene_intersect(sd->osl_globals, ray, PATH_RAY_ALL_VISIBILITY, &tracedata->isect, NULL, 0.0f, 0.0f);
+ /* Raytrace, leaving out shadow opaque to avoid early exit. */
+ uint visibility = PATH_RAY_ALL_VISIBILITY - PATH_RAY_SHADOW_OPAQUE;
+ return scene_intersect(sd->osl_globals, ray, visibility, &tracedata->isect, NULL, 0.0f, 0.0f);
}
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 13b19d86eca..9a37e0987aa 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -57,9 +57,7 @@ void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OS
tdata->globals.tracedata = &tdata->tracedata;
tdata->globals.flipHandedness = false;
tdata->osl_thread_info = ss->create_thread_info();
-
- for(int i = 0; i < SHADER_CONTEXT_NUM; i++)
- tdata->context[i] = ss->get_context(tdata->osl_thread_info);
+ tdata->context = ss->get_context(tdata->osl_thread_info);
tdata->oiio_thread_info = osl_globals->ts->get_perthread_info();
@@ -74,9 +72,7 @@ void OSLShader::thread_free(KernelGlobals *kg)
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
OSLThreadData *tdata = kg->osl_tdata;
-
- for(int i = 0; i < SHADER_CONTEXT_NUM; i++)
- ss->release_context(tdata->context[i]);
+ ss->release_context(tdata->context);
ss->destroy_thread_info(tdata->osl_thread_info);
@@ -173,7 +169,7 @@ static void flatten_surface_closure_tree(ShaderData *sd,
}
}
-void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx)
+void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
{
/* setup shader globals from shader data */
OSLThreadData *tdata = kg->osl_tdata;
@@ -182,7 +178,7 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state
/* execute shader for this point */
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *octx = tdata->context[(int)ctx];
+ OSL::ShadingContext *octx = tdata->context;
int shader = sd->shader & SHADER_MASK;
/* automatic bump shader */
@@ -274,7 +270,7 @@ static void flatten_background_closure_tree(ShaderData *sd,
}
}
-void OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx)
+void OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
{
/* setup shader globals from shader data */
OSLThreadData *tdata = kg->osl_tdata;
@@ -283,7 +279,7 @@ void OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *st
/* execute shader for this point */
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *octx = tdata->context[(int)ctx];
+ OSL::ShadingContext *octx = tdata->context;
if(kg->osl->background_state) {
ss->execute(octx, *(kg->osl->background_state), *globals);
@@ -329,7 +325,7 @@ static void flatten_volume_closure_tree(ShaderData *sd,
}
}
-void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx)
+void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
{
/* setup shader globals from shader data */
OSLThreadData *tdata = kg->osl_tdata;
@@ -338,7 +334,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state,
/* execute shader */
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *octx = tdata->context[(int)ctx];
+ OSL::ShadingContext *octx = tdata->context;
int shader = sd->shader & SHADER_MASK;
if(kg->osl->volume_state[shader]) {
@@ -352,7 +348,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state,
/* Displacement */
-void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx)
+void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
{
/* setup shader globals from shader data */
OSLThreadData *tdata = kg->osl_tdata;
@@ -364,7 +360,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderConte
/* execute shader */
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *octx = tdata->context[(int)ctx];
+ OSL::ShadingContext *octx = tdata->context;
int shader = sd->shader & SHADER_MASK;
if(kg->osl->displacement_state[shader]) {
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 32121e940b4..f7020d1223d 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -53,10 +53,10 @@ public:
static void thread_free(KernelGlobals *kg);
/* eval */
- static void eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
- static void eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
- static void eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
- static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx);
+ static void eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
+ static void eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
+ static void eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
+ static void eval_displacement(KernelGlobals *kg, ShaderData *sd);
/* attributes */
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeDescriptor *desc);
diff --git a/intern/cycles/kernel/shaders/node_principled_bsdf.osl b/intern/cycles/kernel/shaders/node_principled_bsdf.osl
index 57f40789d49..6870d479af3 100644
--- a/intern/cycles/kernel/shaders/node_principled_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_principled_bsdf.osl
@@ -32,7 +32,7 @@ shader node_principled_bsdf(
float Sheen = 0.0,
float SheenTint = 0.5,
float Clearcoat = 0.0,
- float ClearcoatGloss = 1.0,
+ float ClearcoatRoughness = 0.03,
float IOR = 1.45,
float Transmission = 0.0,
float TransmissionRoughness = 0.0,
@@ -57,8 +57,8 @@ shader node_principled_bsdf(
if (diffuse_weight > 1e-5) {
if (Subsurface > 1e-5) {
- color Albedo = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
- BSDF = bssrdf_principled(Normal, Subsurface * SubsurfaceRadius, 0.0, Albedo, Roughness);
+ color mixed_ss_base_color = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
+ BSDF = mixed_ss_base_color * bssrdf_principled(Normal, Subsurface * SubsurfaceRadius, 0.0, SubsurfaceColor, Roughness);
} else {
BSDF = BaseColor * principled_diffuse(Normal, Roughness);
}
@@ -76,8 +76,8 @@ shader node_principled_bsdf(
float aspect = sqrt(1.0 - Anisotropic * 0.9);
float r2 = Roughness * Roughness;
- float alpha_x = max(0.001, r2 / aspect);
- float alpha_y = max(0.001, r2 * aspect);
+ float alpha_x = r2 / aspect;
+ float alpha_y = r2 * aspect;
color tmp_col = color(1.0, 1.0, 1.0) * (1.0 - SpecularTint) + m_ctint * SpecularTint;
@@ -114,7 +114,7 @@ shader node_principled_bsdf(
}
if (Clearcoat > 1e-5) {
- BSDF = BSDF + principled_clearcoat(ClearcoatNormal, Clearcoat, ClearcoatGloss);
+ BSDF = BSDF + principled_clearcoat(ClearcoatNormal, Clearcoat, ClearcoatRoughness * ClearcoatRoughness);
}
}
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 289d1091b0a..c91d2918687 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -546,7 +546,7 @@ closure color holdout() BUILTIN;
closure color ambient_occlusion() BUILTIN;
closure color principled_diffuse(normal N, float roughness) BUILTIN;
closure color principled_sheen(normal N) BUILTIN;
-closure color principled_clearcoat(normal N, float clearcoat, float clearcoat_gloss) BUILTIN;
+closure color principled_clearcoat(normal N, float clearcoat, float clearcoat_roughness) BUILTIN;
// BSSRDF
closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN;
diff --git a/intern/cycles/kernel/split/kernel_branched.h b/intern/cycles/kernel/split/kernel_branched.h
index dc74a2ada53..9fe4ec18e9e 100644
--- a/intern/cycles/kernel/split/kernel_branched.h
+++ b/intern/cycles/kernel/split/kernel_branched.h
@@ -63,17 +63,53 @@ ccl_device_inline void kernel_split_branched_path_indirect_loop_end(KernelGlobal
REMOVE_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT);
}
+ccl_device_inline bool kernel_split_branched_indirect_start_shared(KernelGlobals *kg, int ray_index)
+{
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+
+ int inactive_ray = dequeue_ray_index(QUEUE_INACTIVE_RAYS,
+ kernel_split_state.queue_data, kernel_split_params.queue_size, kernel_split_params.queue_index);
+
+ if(!IS_STATE(ray_state, inactive_ray, RAY_INACTIVE)) {
+ return false;
+ }
+
+#define SPLIT_DATA_ENTRY(type, name, num) \
+ kernel_split_state.name[inactive_ray] = kernel_split_state.name[ray_index];
+ SPLIT_DATA_ENTRIES_BRANCHED_SHARED
+#undef SPLIT_DATA_ENTRY
+
+ kernel_split_state.branched_state[inactive_ray].shared_sample_count = 0;
+ kernel_split_state.branched_state[inactive_ray].original_ray = ray_index;
+ kernel_split_state.branched_state[inactive_ray].waiting_on_shared_samples = false;
+
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ PathRadiance *inactive_L = &kernel_split_state.path_radiance[inactive_ray];
+
+ path_radiance_init(inactive_L, kernel_data.film.use_light_pass);
+ inactive_L->direct_throughput = L->direct_throughput;
+ path_radiance_copy_indirect(inactive_L, L);
+
+ ray_state[inactive_ray] = RAY_REGENERATED;
+ ADD_RAY_FLAG(ray_state, inactive_ray, RAY_BRANCHED_INDIRECT_SHARED);
+ ADD_RAY_FLAG(ray_state, inactive_ray, IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT));
+
+ atomic_fetch_and_inc_uint32((ccl_global uint*)&kernel_split_state.branched_state[ray_index].shared_sample_count);
+
+ return true;
+}
+
/* bounce off surface and integrate indirect light */
ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(KernelGlobals *kg,
int ray_index,
float num_samples_adjust,
ShaderData *saved_sd,
- bool reset_path_state)
+ bool reset_path_state,
+ bool wait_for_shared)
{
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
ShaderData *sd = saved_sd;
- RNG rng = kernel_split_state.rng[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
float3 throughput = branched_state->throughput;
ccl_global PathState *ps = &kernel_split_state.path_state[ray_index];
@@ -120,20 +156,20 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(
num_samples = ceil_to_int(num_samples_adjust*num_samples);
float num_samples_inv = num_samples_adjust/num_samples;
- RNG bsdf_rng = cmj_hash(rng, i);
for(int j = branched_state->next_sample; j < num_samples; j++) {
if(reset_path_state) {
*ps = branched_state->path_state;
}
+ ps->rng_hash = cmj_hash(branched_state->path_state.rng_hash, i);
+
ccl_global float3 *tp = &kernel_split_state.throughput[ray_index];
*tp = throughput;
ccl_global Ray *bsdf_ray = &kernel_split_state.ray[ray_index];
if(!kernel_branched_path_surface_bounce(kg,
- &bsdf_rng,
sd,
sc,
j,
@@ -147,6 +183,8 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(
continue;
}
+ ps->rng_hash = branched_state->path_state.rng_hash;
+
/* update state for next iteration */
branched_state->next_closure = i;
branched_state->next_sample = j+1;
@@ -155,12 +193,25 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(
/* start the indirect path */
*tp *= num_samples_inv;
+ if(kernel_split_branched_indirect_start_shared(kg, ray_index)) {
+ continue;
+ }
+
return true;
}
branched_state->next_sample = 0;
}
+ branched_state->next_closure = sd->num_closure;
+
+ if(wait_for_shared) {
+ branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
+ if(branched_state->waiting_on_shared_samples) {
+ return true;
+ }
+ }
+
return false;
}
diff --git a/intern/cycles/kernel/split/kernel_buffer_update.h b/intern/cycles/kernel/split/kernel_buffer_update.h
index 4c1fdd2d69c..3b61319e349 100644
--- a/intern/cycles/kernel/split/kernel_buffer_update.h
+++ b/intern/cycles/kernel/split/kernel_buffer_update.h
@@ -75,57 +75,34 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
if(ray_index != QUEUE_EMPTY_SLOT) {
#endif
- ccl_global uint *rng_state = kernel_split_params.rng_state;
int stride = kernel_split_params.stride;
ccl_global char *ray_state = kernel_split_state.ray_state;
-#ifdef __KERNEL_DEBUG__
- DebugData *debug_data = &kernel_split_state.debug_data[ray_index];
-#endif
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
- ccl_global float *L_transparent = &kernel_split_state.L_transparent[ray_index];
- RNG rng = kernel_split_state.rng[ray_index];
- ccl_global float *buffer = kernel_split_params.buffer;
-
- unsigned int work_index;
- ccl_global uint *initial_rng;
-
- unsigned int sample;
- unsigned int tile_x;
- unsigned int tile_y;
- unsigned int pixel_x;
- unsigned int pixel_y;
-
- work_index = kernel_split_state.work_array[ray_index];
- sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
- get_work_pixel_tile_position(kg, &pixel_x, &pixel_y,
- &tile_x, &tile_y,
- work_index,
- ray_index);
- initial_rng = rng_state;
-
- rng_state += kernel_split_params.offset + pixel_x + pixel_y*stride;
- buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
-#ifdef __KERNEL_DEBUG__
- kernel_write_debug_passes(kg, buffer, state, debug_data, sample);
-#endif
+ uint work_index = kernel_split_state.work_array[ray_index];
+ uint sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
+
+ uint tile_x, tile_y, pixel_x, pixel_y;
+ get_work_pixel_tile_position(kg, &pixel_x, &pixel_y, &tile_x, &tile_y, work_index, ray_index);
+
+ ccl_global float *buffer = kernel_split_params.buffer;
+ buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
/* accumulate result in output buffer */
bool is_shadow_catcher = (state->flag & PATH_RAY_SHADOW_CATCHER);
- kernel_write_result(kg, buffer, sample, L, 1.0f - (*L_transparent), is_shadow_catcher);
-
- path_rng_end(kg, rng_state, rng);
+ kernel_write_result(kg, buffer, sample, L, is_shadow_catcher);
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
}
if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
/* We have completed current work; So get next work */
+ uint work_index;
int valid_work = get_next_work(kg, &work_index, ray_index);
if(!valid_work) {
/* If work is invalid, this means no more work is available and the thread may exit */
@@ -135,32 +112,33 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
kernel_split_state.work_array[ray_index] = work_index;
/* Get the sample associated with the current work */
- sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
+ uint sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
/* Get pixel and tile position associated with current work */
+ uint tile_x, tile_y, pixel_x, pixel_y;
get_work_pixel_tile_position(kg, &pixel_x, &pixel_y, &tile_x, &tile_y, work_index, ray_index);
/* Remap rng_state according to the current work */
- rng_state = initial_rng + kernel_split_params.offset + pixel_x + pixel_y*stride;
+ ccl_global uint *rng_state = kernel_split_params.rng_state;
+ rng_state += kernel_split_params.offset + pixel_x + pixel_y*stride;
+
/* Remap buffer according to the current work */
+ ccl_global float *buffer = kernel_split_params.buffer;
buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
/* Initialize random numbers and ray. */
- kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, &rng, ray);
+ uint rng_hash;
+ kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, &rng_hash, ray);
if(ray->t != 0.0f) {
- /* Initialize throughput, L_transparent, Ray, PathState;
+ /* Initialize throughput, path radiance, Ray, PathState;
* These rays proceed with path-iteration.
*/
*throughput = make_float3(1.0f, 1.0f, 1.0f);
- *L_transparent = 0.0f;
path_radiance_init(L, kernel_data.film.use_light_pass);
- path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, &rng, sample, ray);
+ path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, rng_hash, sample, ray);
#ifdef __SUBSURFACE__
kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
#endif
-#ifdef __KERNEL_DEBUG__
- debug_data_init(debug_data);
-#endif
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
enqueue_flag = 1;
}
@@ -169,13 +147,11 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
/* Accumulate result in output buffer. */
kernel_write_pass_float4(buffer, sample, L_rad);
- path_rng_end(kg, rng_state, rng);
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
}
}
}
- kernel_split_state.rng[ray_index] = rng;
#ifndef __COMPUTE_DEVICE_GPU__
}
diff --git a/intern/cycles/kernel/split/kernel_data_init.h b/intern/cycles/kernel/split/kernel_data_init.h
index e4545d66eff..2c042dfde6f 100644
--- a/intern/cycles/kernel/split/kernel_data_init.h
+++ b/intern/cycles/kernel/split/kernel_data_init.h
@@ -52,9 +52,7 @@ void KERNEL_FUNCTION_FULL_NAME(data_init)(
ccl_global uint *rng_state,
#ifdef __KERNEL_OPENCL__
-#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name,
-#include "kernel/kernel_textures.h"
+ KERNEL_BUFFER_PARAMS,
#endif
int start_sample,
@@ -100,9 +98,8 @@ void KERNEL_FUNCTION_FULL_NAME(data_init)(
split_data_init(kg, &kernel_split_state, num_elements, split_data_buffer, ray_state);
#ifdef __KERNEL_OPENCL__
-#define KERNEL_TEX(type, ttype, name) \
- kg->name = name;
-#include "kernel/kernel_textures.h"
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
+ kernel_set_buffer_info(kg);
#endif
int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
@@ -127,14 +124,25 @@ void KERNEL_FUNCTION_FULL_NAME(data_init)(
/* zero the tiles pixels and initialize rng_state if this is the first sample */
if(start_sample == 0) {
- parallel_for(kg, i, sw * sh * kernel_data.film.pass_stride) {
- int pixel = i / kernel_data.film.pass_stride;
- int pass = i % kernel_data.film.pass_stride;
+ int pass_stride = kernel_data.film.pass_stride;
+
+#ifdef __KERNEL_CPU__
+ for(int y = sy; y < sy + sh; y++) {
+ int index = offset + y * stride;
+ memset(buffer + (sx + index) * pass_stride, 0, sizeof(float) * pass_stride * sw);
+ for(int x = sx; x < sx + sw; x++) {
+ rng_state[index + x] = hash_int_2d(x, y);
+ }
+ }
+#else
+ parallel_for(kg, i, sw * sh * pass_stride) {
+ int pixel = i / pass_stride;
+ int pass = i % pass_stride;
int x = sx + pixel % sw;
int y = sy + pixel / sw;
- int index = (offset + x + y*stride) * kernel_data.film.pass_stride + pass;
+ int index = (offset + x + y*stride) * pass_stride + pass;
*(buffer + index) = 0.0f;
}
@@ -146,6 +154,7 @@ void KERNEL_FUNCTION_FULL_NAME(data_init)(
int index = (offset + x + y*stride);
*(rng_state + index) = hash_int_2d(x, y);
}
+#endif
}
#endif /* KERENL_STUB */
diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h
index 3336c968a44..8e3f7555550 100644
--- a/intern/cycles/kernel/split/kernel_direct_lighting.h
+++ b/intern/cycles/kernel/split/kernel_direct_lighting.h
@@ -62,8 +62,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
/* direct lighting */
#ifdef __EMISSION__
- RNG rng = kernel_split_state.rng[ray_index];
-
bool flag = (kernel_data.integrator.use_direct_light &&
(sd->flag & SD_BSDF_HAS_EVAL));
@@ -83,10 +81,10 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
if(flag) {
/* Sample illumination from lights to find path contribution. */
- float light_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
- path_state_rng_2D(kg, &rng, state, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_state_rng_light_termination(kg, &rng, state);
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_state_rng_light_termination(kg, state);
LightSample ls;
if(light_sample(kg,
@@ -115,7 +113,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
}
}
}
- kernel_split_state.rng[ray_index] = rng;
#endif /* __EMISSION__ */
}
diff --git a/intern/cycles/kernel/split/kernel_do_volume.h b/intern/cycles/kernel/split/kernel_do_volume.h
index 694b777f429..478d83d633e 100644
--- a/intern/cycles/kernel/split/kernel_do_volume.h
+++ b/intern/cycles/kernel/split/kernel_do_volume.h
@@ -30,7 +30,6 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
ShaderData *sd = &kernel_split_state.sd[ray_index];
- RNG rng = kernel_split_state.rng[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
@@ -58,15 +57,15 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K
/* integrate along volume segment with distance sampling */
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, ps, sd, &volume_ray, L, tp, &rng, heterogeneous);
+ kg, ps, sd, &volume_ray, L, tp, heterogeneous);
# ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
- kernel_path_volume_connect_light(kg, &rng, sd, emission_sd, *tp, &branched_state->path_state, L);
+ kernel_path_volume_connect_light(kg, sd, emission_sd, *tp, &branched_state->path_state, L);
/* indirect light bounce */
- if(!kernel_path_volume_bounce(kg, &rng, sd, tp, ps, L, pray)) {
+ if(!kernel_path_volume_bounce(kg, sd, tp, ps, L, pray)) {
continue;
}
@@ -75,11 +74,30 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K
branched_state->next_sample = j+1;
branched_state->num_samples = num_samples;
+ /* Attempting to share too many samples is slow for volumes as it causes us to
+ * loop here more and have many calls to kernel_volume_integrate which evaluates
+ * shaders. The many expensive shader evaluations cause the work load to become
+ * unbalanced and many threads to become idle in this kernel. Limiting the
+ * number of shared samples here helps quite a lot.
+ */
+ if(branched_state->shared_sample_count < 2) {
+ if(kernel_split_branched_indirect_start_shared(kg, ray_index)) {
+ continue;
+ }
+ }
+
return true;
}
# endif
}
+ branched_state->next_sample = num_samples;
+
+ branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
+ if(branched_state->waiting_on_shared_samples) {
+ return true;
+ }
+
kernel_split_branched_path_indirect_loop_end(kg, ray_index);
/* todo: avoid this calculation using decoupled ray marching */
@@ -122,7 +140,6 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- RNG rng = kernel_split_state.rng[ray_index];
ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
ShaderData *sd = &kernel_split_state.sd[ray_index];
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
@@ -146,15 +163,15 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
{
/* integrate along volume segment with distance sampling */
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous);
+ kg, state, sd, &volume_ray, L, throughput, heterogeneous);
# ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
- kernel_path_volume_connect_light(kg, &rng, sd, emission_sd, *throughput, state, L);
+ kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
/* indirect light bounce */
- if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray)) {
+ if(kernel_path_volume_bounce(kg, sd, throughput, state, L, ray)) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
}
else {
@@ -175,8 +192,6 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
}
# endif /* __BRANCHED_PATH__ */
}
-
- kernel_split_state.rng[ray_index] = rng;
}
# ifdef __BRANCHED_PATH__
diff --git a/intern/cycles/kernel/split/kernel_enqueue_inactive.h b/intern/cycles/kernel/split/kernel_enqueue_inactive.h
new file mode 100644
index 00000000000..496355bbc3a
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_enqueue_inactive.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011-2017 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
+
+ccl_device void kernel_enqueue_inactive(KernelGlobals *kg,
+ ccl_local_param unsigned int *local_queue_atomics)
+{
+#ifdef __BRANCHED_PATH__
+ /* Enqeueue RAY_INACTIVE rays into QUEUE_INACTIVE_RAYS queue. */
+ if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ *local_queue_atomics = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+
+ char enqueue_flag = 0;
+ if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_INACTIVE)) {
+ enqueue_flag = 1;
+ }
+
+ enqueue_ray_index_local(ray_index,
+ QUEUE_INACTIVE_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ local_queue_atomics,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
+#endif /* __BRANCHED_PATH__ */
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
index 670a557f084..253b78526e7 100644
--- a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
+++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
@@ -92,29 +92,19 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
int stride = kernel_split_params.stride;
- unsigned int work_index;
- unsigned int pixel_x;
- unsigned int pixel_y;
-
- unsigned int tile_x;
- unsigned int tile_y;
- unsigned int sample;
-
- RNG rng = kernel_split_state.rng[ray_index];
ccl_global PathState *state = 0x0;
float3 throughput;
+ uint sample;
ccl_global char *ray_state = kernel_split_state.ray_state;
ShaderData *sd = &kernel_split_state.sd[ray_index];
ccl_global float *buffer = kernel_split_params.buffer;
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
-
- throughput = kernel_split_state.throughput[ray_index];
- state = &kernel_split_state.path_state[ray_index];
-
- work_index = kernel_split_state.work_array[ray_index];
+ uint work_index = kernel_split_state.work_array[ray_index];
sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
+
+ uint pixel_x, pixel_y, tile_x, tile_y;
get_work_pixel_tile_position(kg, &pixel_x, &pixel_y,
&tile_x, &tile_y,
work_index,
@@ -122,20 +112,31 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
buffer += (kernel_split_params.offset + pixel_x + pixel_y * stride) * kernel_data.film.pass_stride;
+ throughput = kernel_split_state.throughput[ray_index];
+ state = &kernel_split_state.path_state[ray_index];
+
#ifdef __SHADOW_TRICKS__
if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
if(state->flag & PATH_RAY_CAMERA) {
- state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY | PATH_RAY_STORE_SHADOW_INFO);
- state->catcher_object = sd->object;
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ state->flag |= (PATH_RAY_SHADOW_CATCHER |
+ PATH_RAY_STORE_SHADOW_INFO);
if(!kernel_data.background.transparent) {
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- L->shadow_color = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray);
+ L->shadow_background_color = indirect_background(
+ kg,
+ &kernel_split_state.sd_DL_shadow[ray_index],
+ state,
+ ray);
}
+ L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L);
+ L->shadow_throughput = average(throughput);
}
}
- else {
- state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ else if(state->flag & PATH_RAY_SHADOW_CATCHER) {
+ /* Only update transparency after shadow catcher bounce. */
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ L->shadow_transparency *= average(shader_bsdf_transparency(kg, sd));
}
#endif /* __SHADOW_TRICKS__ */
@@ -154,7 +155,8 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
holdout_weight = shader_holdout_eval(kg, sd);
}
/* any throughput is ok, should all be identical here */
- kernel_split_state.L_transparent[ray_index] += average(holdout_weight*throughput);
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ L->transparent += average(holdout_weight*throughput);
}
if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
kernel_split_path_end(kg, ray_index);
@@ -216,19 +218,19 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
* shader evaluations, only need emission if we are going to terminate.
*/
#ifndef __BRANCHED_PATH__
- float probability = path_state_terminate_probability(kg, state, throughput);
+ float probability = path_state_continuation_probability(kg, state, throughput);
#else
float probability = 1.0f;
if(!kernel_data.integrator.branched) {
- probability = path_state_terminate_probability(kg, state, throughput);
+ probability = path_state_continuation_probability(kg, state, throughput);
}
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
int num_samples = kernel_split_state.branched_state[ray_index].num_samples;
- probability = path_state_terminate_probability(kg, state, throughput*num_samples);
+ probability = path_state_continuation_probability(kg, state, throughput*num_samples);
}
else if(state->flag & PATH_RAY_TRANSPARENT) {
- probability = path_state_terminate_probability(kg, state, throughput);
+ probability = path_state_continuation_probability(kg, state, throughput);
}
#endif
@@ -238,7 +240,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
if(probability != 1.0f) {
- float terminate = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_TERMINATE);
+ float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE);
if(terminate >= probability) {
kernel_split_path_end(kg, ray_index);
}
@@ -260,8 +262,6 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
}
#endif /* __AO__ */
- kernel_split_state.rng[ray_index] = rng;
-
#ifndef __COMPUTE_DEVICE_GPU__
}
#endif
diff --git a/intern/cycles/kernel/split/kernel_indirect_background.h b/intern/cycles/kernel/split/kernel_indirect_background.h
index f0ebb90f60a..04d5769ef0d 100644
--- a/intern/cycles/kernel/split/kernel_indirect_background.h
+++ b/intern/cycles/kernel/split/kernel_indirect_background.h
@@ -54,12 +54,11 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg)
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
- ccl_global float *L_transparent = &kernel_split_state.L_transparent[ray_index];
if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
/* eval background shader if nothing hit */
if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) {
- *L_transparent = (*L_transparent) + average((*throughput));
+ L->transparent += average((*throughput));
#ifdef __PASSES__
if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
#endif
diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
index 71017fed19e..4e0c966cca9 100644
--- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h
+++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
@@ -126,7 +126,6 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
if(active) {
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- RNG rng = kernel_split_state.rng[ray_index];
ShaderData *sd = &kernel_split_state.sd[ray_index];
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
@@ -135,7 +134,7 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
#endif
/* Compute direct lighting and next bounce. */
- if(!kernel_path_surface_bounce(kg, &rng, sd, throughput, state, L, ray)) {
+ if(!kernel_path_surface_bounce(kg, sd, throughput, state, L, ray)) {
kernel_split_path_end(kg, ray_index);
}
#ifdef __BRANCHED_PATH__
@@ -147,6 +146,7 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
ray_index,
1.0f,
&kernel_split_state.branched_state[ray_index].sd,
+ true,
true))
{
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
@@ -156,8 +156,6 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
}
}
#endif /* __BRANCHED_PATH__ */
-
- kernel_split_state.rng[ray_index] = rng;
}
/* Enqueue RAY_UPDATE_BUFFER rays. */
@@ -193,6 +191,7 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
ray_index,
1.0f,
&kernel_split_state.branched_state[ray_index].sd,
+ true,
true))
{
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
diff --git a/intern/cycles/kernel/split/kernel_path_init.h b/intern/cycles/kernel/split/kernel_path_init.h
index a7ecde7c80d..c75931855b2 100644
--- a/intern/cycles/kernel/split/kernel_path_init.h
+++ b/intern/cycles/kernel/split/kernel_path_init.h
@@ -29,13 +29,7 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
*/
kernel_split_state.ray_state[ray_index] = RAY_ACTIVE;
- unsigned int my_sample;
- unsigned int pixel_x;
- unsigned int pixel_y;
- unsigned int tile_x;
- unsigned int tile_y;
-
- unsigned int work_index = 0;
+ uint work_index = 0;
/* Get work. */
if(!get_next_work(kg, &work_index, ray_index)) {
/* No more work, mark ray as inactive */
@@ -45,9 +39,10 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
}
/* Get the sample associated with the work. */
- my_sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
+ uint sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
/* Get pixel and tile position associated with the work. */
+ uint pixel_x, pixel_y, tile_x, tile_y;
get_work_pixel_tile_position(kg, &pixel_x, &pixel_y,
&tile_x, &tile_y,
work_index,
@@ -60,46 +55,38 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
ccl_global float *buffer = kernel_split_params.buffer;
buffer += (kernel_split_params.offset + pixel_x + pixel_y * kernel_split_params.stride) * kernel_data.film.pass_stride;
- RNG rng = kernel_split_state.rng[ray_index];
-
/* Initialize random numbers and ray. */
+ uint rng_hash;
kernel_path_trace_setup(kg,
rng_state,
- my_sample,
+ sample,
pixel_x, pixel_y,
- &rng,
+ &rng_hash,
&kernel_split_state.ray[ray_index]);
if(kernel_split_state.ray[ray_index].t != 0.0f) {
- /* Initialize throughput, L_transparent, Ray, PathState;
+ /* Initialize throughput, path radiance, Ray, PathState;
* These rays proceed with path-iteration.
*/
kernel_split_state.throughput[ray_index] = make_float3(1.0f, 1.0f, 1.0f);
- kernel_split_state.L_transparent[ray_index] = 0.0f;
path_radiance_init(&kernel_split_state.path_radiance[ray_index], kernel_data.film.use_light_pass);
path_state_init(kg,
&kernel_split_state.sd_DL_shadow[ray_index],
&kernel_split_state.path_state[ray_index],
- &rng,
- my_sample,
+ rng_hash,
+ sample,
&kernel_split_state.ray[ray_index]);
#ifdef __SUBSURFACE__
kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
#endif
-
-#ifdef __KERNEL_DEBUG__
- debug_data_init(&kernel_split_state.debug_data[ray_index]);
-#endif
}
else {
/* These rays do not participate in path-iteration. */
float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
/* Accumulate result in output buffer. */
- kernel_write_pass_float4(buffer, my_sample, L_rad);
- path_rng_end(kg, rng_state, kernel_split_state.rng[ray_index]);
+ kernel_write_pass_float4(buffer, sample, L_rad);
ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE);
}
- kernel_split_state.rng[ray_index] = rng;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_queue_enqueue.h b/intern/cycles/kernel/split/kernel_queue_enqueue.h
index e2e841f36d3..66ce2dfb6f1 100644
--- a/intern/cycles/kernel/split/kernel_queue_enqueue.h
+++ b/intern/cycles/kernel/split/kernel_queue_enqueue.h
@@ -51,7 +51,8 @@ ccl_device void kernel_queue_enqueue(KernelGlobals *kg,
int queue_number = -1;
if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND) ||
- IS_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER)) {
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) {
queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
}
else if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) ||
diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h
index 5dc94caec85..d0afd39ef29 100644
--- a/intern/cycles/kernel/split/kernel_scene_intersect.h
+++ b/intern/cycles/kernel/split/kernel_scene_intersect.h
@@ -43,15 +43,22 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
}
/* All regenerated rays become active here */
- if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED))
- ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE);
+ if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED)) {
+#ifdef __BRANCHED_PATH__
+ if(kernel_split_state.branched_state[ray_index].waiting_on_shared_samples) {
+ kernel_split_path_end(kg, ray_index);
+ }
+ else
+#endif /* __BRANCHED_PATH__ */
+ {
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE);
+ }
+ }
- if(!IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE))
+ if(!IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
return;
+ }
-#ifdef __KERNEL_DEBUG__
- DebugData *debug_data = &kernel_split_state.debug_data[ray_index];
-#endif
Intersection isect;
PathState state = kernel_split_state.path_state[ray_index];
Ray ray = kernel_split_state.ray[ray_index];
@@ -67,7 +74,6 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
#ifdef __HAIR__
float difl = 0.0f, extmax = 0.0f;
uint lcg_state = 0;
- RNG rng = kernel_split_state.rng[ray_index];
if(kernel_data.bvh.have_curves) {
if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
@@ -77,7 +83,7 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(&rng, state.rng_offset, state.sample, 0x51633e2d);
+ lcg_state = lcg_state_init(&state, 0x51633e2d);
}
bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
@@ -87,12 +93,14 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
kernel_split_state.isect[ray_index] = isect;
#ifdef __KERNEL_DEBUG__
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+
if(state.flag & PATH_RAY_CAMERA) {
- debug_data->num_bvh_traversed_nodes += isect.num_traversed_nodes;
- debug_data->num_bvh_traversed_instances += isect.num_traversed_instances;
- debug_data->num_bvh_intersections += isect.num_intersections;
+ L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
+ L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
+ L->debug_data.num_bvh_intersections += isect.num_intersections;
}
- debug_data->num_ray_bounces++;
+ L->debug_data.num_ray_bounces++;
#endif
if(!hit) {
diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h
index 2801b32f285..eac29dcd0d1 100644
--- a/intern/cycles/kernel/split/kernel_shader_eval.h
+++ b/intern/cycles/kernel/split/kernel_shader_eval.h
@@ -48,30 +48,22 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg)
ccl_global char *ray_state = kernel_split_state.ray_state;
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- RNG rng = kernel_split_state.rng[ray_index];
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
#ifndef __BRANCHED_PATH__
- float rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF);
- shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
+ float rbsdf = path_state_rng_1D_for_decision(kg, state, PRNG_BSDF);
+ shader_eval_surface(kg, &kernel_split_state.sd[ray_index], state, rbsdf, state->flag);
#else
- ShaderContext ctx = SHADER_CONTEXT_MAIN;
float rbsdf = 0.0f;
if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
- rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF);
+ rbsdf = path_state_rng_1D_for_decision(kg, state, PRNG_BSDF);
}
- if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
- ctx = SHADER_CONTEXT_INDIRECT;
- }
-
- shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, ctx);
+ shader_eval_surface(kg, &kernel_split_state.sd[ray_index], state, rbsdf, state->flag);
shader_merge_closures(&kernel_split_state.sd[ray_index]);
#endif /* __BRANCHED_PATH__ */
-
- kernel_split_state.rng[ray_index] = rng;
}
}
diff --git a/intern/cycles/kernel/split/kernel_shader_sort.h b/intern/cycles/kernel/split/kernel_shader_sort.h
index 297decb0bc2..5a55b680695 100644
--- a/intern/cycles/kernel/split/kernel_shader_sort.h
+++ b/intern/cycles/kernel/split/kernel_shader_sort.h
@@ -39,7 +39,7 @@ ccl_device void kernel_shader_sort(KernelGlobals *kg,
ccl_local ushort *local_index = &locals->local_index[0];
/* copy to local memory */
- for (uint i = 0; i < SHADER_SORT_BLOCK_SIZE; i += SHADER_SORT_LOCAL_SIZE) {
+ for(uint i = 0; i < SHADER_SORT_BLOCK_SIZE; i += SHADER_SORT_LOCAL_SIZE) {
uint idx = offset + i + lid;
uint add = input + idx;
uint value = (~0);
@@ -59,9 +59,9 @@ ccl_device void kernel_shader_sort(KernelGlobals *kg,
# ifdef __KERNEL_OPENCL__
/* bitonic sort */
- for (uint length = 1; length < SHADER_SORT_BLOCK_SIZE; length <<= 1) {
- for (uint inc = length; inc > 0; inc >>= 1) {
- for (uint ii = 0; ii < SHADER_SORT_BLOCK_SIZE; ii += SHADER_SORT_LOCAL_SIZE) {
+ for(uint length = 1; length < SHADER_SORT_BLOCK_SIZE; length <<= 1) {
+ for(uint inc = length; inc > 0; inc >>= 1) {
+ for(uint ii = 0; ii < SHADER_SORT_BLOCK_SIZE; ii += SHADER_SORT_LOCAL_SIZE) {
uint i = lid + ii;
bool direction = ((i & (length << 1)) != 0);
uint j = i ^ inc;
@@ -81,7 +81,7 @@ ccl_device void kernel_shader_sort(KernelGlobals *kg,
# endif /* __KERNEL_OPENCL__ */
/* copy to destination */
- for (uint i = 0; i < SHADER_SORT_BLOCK_SIZE; i += SHADER_SORT_LOCAL_SIZE) {
+ for(uint i = 0; i < SHADER_SORT_BLOCK_SIZE; i += SHADER_SORT_LOCAL_SIZE) {
uint idx = offset + i + lid;
uint lidx = local_index[i + lid];
uint outi = output + idx;
diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h b/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h
index 474286285a9..79aa2c9435b 100644
--- a/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h
+++ b/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h
@@ -37,21 +37,18 @@ ccl_device void kernel_shadow_blocked_ao(KernelGlobals *kg)
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- RNG rng = kernel_split_state.rng[ray_index];
float3 throughput = kernel_split_state.throughput[ray_index];
#ifdef __BRANCHED_PATH__
if(!kernel_data.integrator.branched || IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
#endif
- kernel_path_ao(kg, sd, emission_sd, L, state, &rng, throughput, shader_bsdf_alpha(kg, sd));
+ kernel_path_ao(kg, sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, sd));
#ifdef __BRANCHED_PATH__
}
else {
- kernel_branched_path_ao(kg, sd, emission_sd, L, state, &rng, throughput);
+ kernel_branched_path_ao(kg, sd, emission_sd, L, state, throughput);
}
#endif
-
- kernel_split_state.rng[ray_index] = rng;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
index 386fbbc4d09..b52f9a5eb81 100644
--- a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
+++ b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
@@ -29,6 +29,14 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
kernel_split_state.queue_data, kernel_split_params.queue_size, 1);
}
+#ifdef __BRANCHED_PATH__
+ /* TODO(mai): move this somewhere else? */
+ if(thread_index == 0) {
+ /* Clear QUEUE_INACTIVE_RAYS before next kernel. */
+ kernel_split_params.queue_index[QUEUE_INACTIVE_RAYS] = 0;
+ }
+#endif /* __BRANCHED_PATH__ */
+
if(ray_index == QUEUE_EMPTY_SLOT)
return;
@@ -37,7 +45,6 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ShaderData *sd = &kernel_split_state.sd[ray_index];
float3 throughput = kernel_split_state.throughput[ray_index];
- RNG rng = kernel_split_state.rng[ray_index];
BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
@@ -67,7 +74,6 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
if(use_branched) {
kernel_branched_path_surface_connect_light(kg,
- &rng,
sd,
emission_sd,
state,
@@ -83,10 +89,11 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
float3 shadow;
if(!shadow_blocked(kg,
- emission_sd,
- state,
- &ray,
- &shadow))
+ sd,
+ emission_sd,
+ state,
+ &ray,
+ &shadow))
{
/* accumulate */
path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
@@ -95,8 +102,6 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
path_radiance_accum_total_light(L, state, throughput, &L_light);
}
}
-
- kernel_split_state.rng[ray_index] = rng;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_split_common.h b/intern/cycles/kernel/split/kernel_split_common.h
index 57f070d51e0..08f0124b529 100644
--- a/intern/cycles/kernel/split/kernel_split_common.h
+++ b/intern/cycles/kernel/split/kernel_split_common.h
@@ -56,7 +56,20 @@ ccl_device_inline void kernel_split_path_end(KernelGlobals *kg, int ray_index)
ccl_global char *ray_state = kernel_split_state.ray_state;
#ifdef __BRANCHED_PATH__
- if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT)) {
+ if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT_SHARED)) {
+ int orig_ray = kernel_split_state.branched_state[ray_index].original_ray;
+
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ PathRadiance *orig_ray_L = &kernel_split_state.path_radiance[orig_ray];
+
+ path_radiance_sum_indirect(L);
+ path_radiance_accum_sample(orig_ray_L, L, 1);
+
+ atomic_fetch_and_dec_uint32((ccl_global uint*)&kernel_split_state.branched_state[orig_ray].shared_sample_count);
+
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
+ }
+ else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT)) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_LIGHT_INDIRECT_NEXT_ITER);
}
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_VOLUME_INDIRECT)) {
diff --git a/intern/cycles/kernel/split/kernel_split_data_types.h b/intern/cycles/kernel/split/kernel_split_data_types.h
index bb1aca2acbf..3eae884d479 100644
--- a/intern/cycles/kernel/split/kernel_split_data_types.h
+++ b/intern/cycles/kernel/split/kernel_split_data_types.h
@@ -56,14 +56,6 @@ typedef struct SplitParams {
/* SPLIT_DATA_ENTRY(type, name, num) */
-#if defined(WITH_CYCLES_DEBUG) || defined(__KERNEL_DEBUG__)
-/* DebugData memory */
-# define SPLIT_DATA_DEBUG_ENTRIES \
- SPLIT_DATA_ENTRY(DebugData, debug_data, 1)
-#else
-# define SPLIT_DATA_DEBUG_ENTRIES
-#endif /* DEBUG */
-
#ifdef __BRANCHED_PATH__
typedef ccl_global struct SplitBranchedState {
@@ -95,6 +87,10 @@ typedef ccl_global struct SplitBranchedState {
VolumeStack volume_stack[VOLUME_STACK_SIZE];
# endif /* __VOLUME__ */
#endif /*__SUBSURFACE__ */
+
+ int shared_sample_count; /* number of branched samples shared with other threads */
+ int original_ray; /* index of original ray when sharing branched samples */
+ bool waiting_on_shared_samples;
} SplitBranchedState;
#define SPLIT_DATA_BRANCHED_ENTRIES \
@@ -118,9 +114,7 @@ typedef ccl_global struct SplitBranchedState {
#endif /* __VOLUME__ */
#define SPLIT_DATA_ENTRIES \
- SPLIT_DATA_ENTRY(ccl_global RNG, rng, 1) \
SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
- SPLIT_DATA_ENTRY(ccl_global float, L_transparent, 1) \
SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
SPLIT_DATA_ENTRY(ccl_global Ray, ray, 1) \
SPLIT_DATA_ENTRY(ccl_global PathState, path_state, 1) \
@@ -135,7 +129,22 @@ typedef ccl_global struct SplitBranchedState {
SPLIT_DATA_SUBSURFACE_ENTRIES \
SPLIT_DATA_VOLUME_ENTRIES \
SPLIT_DATA_BRANCHED_ENTRIES \
- SPLIT_DATA_DEBUG_ENTRIES \
+
+/* entries to be copied to inactive rays when sharing branched samples (TODO: which are actually needed?) */
+#define SPLIT_DATA_ENTRIES_BRANCHED_SHARED \
+ SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
+ SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Ray, ray, 1) \
+ SPLIT_DATA_ENTRY(ccl_global PathState, path_state, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Intersection, isect, 1) \
+ SPLIT_DATA_ENTRY(ccl_global BsdfEval, bsdf_eval, 1) \
+ SPLIT_DATA_ENTRY(ccl_global int, is_lamp, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Ray, light_ray, 1) \
+ SPLIT_DATA_ENTRY(ShaderData, sd, 1) \
+ SPLIT_DATA_ENTRY(ShaderData, sd_DL_shadow, 1) \
+ SPLIT_DATA_SUBSURFACE_ENTRIES \
+ SPLIT_DATA_VOLUME_ENTRIES \
+ SPLIT_DATA_BRANCHED_ENTRIES \
/* struct that holds pointers to data in the shared state buffer */
typedef struct SplitData {
diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
index 1dffe1b179e..a487e53df5c 100644
--- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h
+++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
@@ -38,7 +38,6 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
ShaderData *sd = &branched_state->sd;
- RNG rng = kernel_split_state.rng[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
@@ -52,14 +51,12 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
if(branched_state->ss_next_sample == 0 && branched_state->next_hit == 0 &&
branched_state->next_closure == 0 && branched_state->next_sample == 0)
{
- branched_state->lcg_state = lcg_state_init(&rng,
- branched_state->path_state.rng_offset,
- branched_state->path_state.sample,
- 0x68bc21eb);
+ branched_state->lcg_state = lcg_state_init_addrspace(&branched_state->path_state,
+ 0x68bc21eb);
}
int num_samples = kernel_data.integrator.subsurface_samples;
float num_samples_inv = 1.0f/num_samples;
- RNG bssrdf_rng = cmj_hash(rng, i);
+ uint bssrdf_rng_hash = cmj_hash(branched_state->path_state.rng_hash, i);
/* do subsurface scatter step with copy of shader data, this will
* replace the BSSRDF with a diffuse BSDF closure */
@@ -67,7 +64,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
ccl_global SubsurfaceIntersection *ss_isect = &branched_state->ss_isect;
float bssrdf_u, bssrdf_v;
path_branched_rng_2D(kg,
- &bssrdf_rng,
+ bssrdf_rng_hash,
&branched_state->path_state,
j,
num_samples,
@@ -77,7 +74,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
/* intersection is expensive so avoid doing multiple times for the same input */
if(branched_state->next_hit == 0 && branched_state->next_closure == 0 && branched_state->next_sample == 0) {
- RNG lcg_state = branched_state->lcg_state;
+ uint lcg_state = branched_state->lcg_state;
SubsurfaceIntersection ss_isect_private;
branched_state->num_hits = subsurface_scatter_multi_intersect(kg,
@@ -152,7 +149,6 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
int all = (kernel_data.integrator.sample_all_lights_direct) ||
(branched_state->path_state.flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(kg,
- &rng,
bssrdf_sd,
emission_sd,
hit_state,
@@ -169,6 +165,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
ray_index,
num_samples_inv,
bssrdf_sd,
+ false,
false))
{
branched_state->ss_next_closure = i;
@@ -187,6 +184,13 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
branched_state->ss_next_sample = 0;
}
+ branched_state->ss_next_closure = sd->num_closure;
+
+ branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
+ if(branched_state->waiting_on_shared_samples) {
+ return true;
+ }
+
kernel_split_branched_path_indirect_loop_end(kg, ray_index);
return false;
@@ -221,7 +225,6 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- RNG rng = kernel_split_state.rng[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
ccl_global SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
@@ -238,7 +241,6 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
emission_sd,
L,
state,
- &rng,
ray,
throughput,
ss_indirect))
@@ -256,22 +258,20 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
- uint lcg_state = lcg_state_init(&rng, state->rng_offset, state->sample, 0x68bc21eb);
-
+ uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
float bssrdf_u, bssrdf_v;
path_state_rng_2D(kg,
- &rng,
- state,
- PRNG_BSDF_U,
- &bssrdf_u, &bssrdf_v);
+ state,
+ PRNG_BSDF_U,
+ &bssrdf_u, &bssrdf_v);
subsurface_scatter_step(kg,
- sd,
- state,
- state->flag,
- sc,
- &lcg_state,
- bssrdf_u, bssrdf_v,
- false);
+ sd,
+ state,
+ state->flag,
+ sc,
+ &lcg_state,
+ bssrdf_u, bssrdf_v,
+ false);
}
}
else {
@@ -283,7 +283,6 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
}
#endif
}
- kernel_split_state.rng[ray_index] = rng;
}
# ifdef __BRANCHED_PATH__
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index f04f765686e..4268813b263 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -79,13 +79,13 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#ifdef __PRINCIPLED__
case CLOSURE_BSDF_PRINCIPLED_ID: {
uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset,
- sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset, eta_offset, transmission_offset,
+ sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset, eta_offset, transmission_offset,
anisotropic_rotation_offset, transmission_roughness_offset;
uint4 data_node2 = read_node(kg, offset);
float3 T = stack_load_float3(stack, data_node.y);
decode_node_uchar4(data_node.z, &specular_offset, &roughness_offset, &specular_tint_offset, &anisotropic_offset);
- decode_node_uchar4(data_node.w, &sheen_offset, &sheen_tint_offset, &clearcoat_offset, &clearcoat_gloss_offset);
+ decode_node_uchar4(data_node.w, &sheen_offset, &sheen_tint_offset, &clearcoat_offset, &clearcoat_roughness_offset);
decode_node_uchar4(data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &transmission_roughness_offset);
// get Disney principled parameters
@@ -98,7 +98,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float sheen = stack_load_float(stack, sheen_offset);
float sheen_tint = stack_load_float(stack, sheen_tint_offset);
float clearcoat = stack_load_float(stack, clearcoat_offset);
- float clearcoat_gloss = stack_load_float(stack, clearcoat_gloss_offset);
+ float clearcoat_roughness = stack_load_float(stack, clearcoat_roughness_offset);
float transmission = stack_load_float(stack, transmission_offset);
float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
float transmission_roughness = stack_load_float(stack, transmission_roughness_offset);
@@ -141,8 +141,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float3 weight = sd->svm_closure_weight * mix_weight;
#ifdef __SUBSURFACE__
- float3 albedo = subsurface_color * subsurface + base_color * (1.0f - subsurface);
- float3 subsurf_weight = weight * albedo * diffuse_weight;
+ float3 mixed_ss_base_color = subsurface_color * subsurface + base_color * (1.0f - subsurface);
+ float3 subsurf_weight = weight * mixed_ss_base_color * diffuse_weight;
float subsurf_sample_weight = fabsf(average(subsurf_weight));
/* disable in case of diffuse ancestor, can't see it well then and
@@ -154,12 +154,12 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
/* need to set the base color in this case such that the
* rays get the correctly mixed color after transmitting
* the object */
- base_color = albedo;
+ base_color = mixed_ss_base_color;
}
/* diffuse */
- if(fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) {
- if(subsurface < CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
+ if(fabsf(average(mixed_ss_base_color)) > CLOSURE_WEIGHT_CUTOFF) {
+ if(subsurface <= CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
float3 diff_weight = weight * base_color * diffuse_weight;
PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
@@ -186,7 +186,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->sample_weight = subsurf_sample_weight;
bssrdf->radius = radius.x;
bssrdf->texture_blur = texture_blur;
- bssrdf->albedo = albedo.x;
+ bssrdf->albedo = subsurface_color.x;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
bssrdf->roughness = roughness;
@@ -200,7 +200,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->sample_weight = subsurf_sample_weight;
bssrdf->radius = radius.y;
bssrdf->texture_blur = texture_blur;
- bssrdf->albedo = albedo.y;
+ bssrdf->albedo = subsurface_color.y;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
bssrdf->roughness = roughness;
@@ -214,7 +214,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->sample_weight = subsurf_sample_weight;
bssrdf->radius = radius.z;
bssrdf->texture_blur = texture_blur;
- bssrdf->albedo = albedo.z;
+ bssrdf->albedo = subsurface_color.z;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
bssrdf->roughness = roughness;
@@ -280,8 +280,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
float r2 = roughness * roughness;
- bsdf->alpha_x = fmaxf(0.001f, r2 / aspect);
- bsdf->alpha_y = fmaxf(0.001f, r2 * aspect);
+ bsdf->alpha_x = r2 / aspect;
+ bsdf->alpha_y = r2 * aspect;
float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y + 0.1f * base_color.z; // luminance approx.
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
@@ -292,9 +292,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
/* setup bsdf */
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || roughness <= 0.075f) /* use single-scatter GGX */
- sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
else /* use multi-scatter GGX */
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
}
}
#ifdef __CAUSTICS_TRICKS__
@@ -332,7 +332,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->extra->cspec0 = cspec0;
/* setup bsdf */
- sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
}
}
@@ -377,7 +377,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->extra->cspec0 = cspec0;
/* setup bsdf */
- sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
}
}
}
@@ -398,14 +398,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->ior = 1.5f;
bsdf->extra = extra;
- bsdf->alpha_x = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
- bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
+ bsdf->alpha_x = clearcoat_roughness * clearcoat_roughness;
+ bsdf->alpha_y = clearcoat_roughness * clearcoat_roughness;
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
bsdf->extra->clearcoat = clearcoat;
/* setup bsdf */
- sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
}
}
#ifdef __CAUSTICS_TRICKS__
@@ -725,6 +725,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
HairBsdf *bsdf = (HairBsdf*)bsdf_alloc(sd, sizeof(HairBsdf), weight);
if(bsdf) {
+ bsdf->N = N;
bsdf->roughness1 = param1;
bsdf->roughness2 = param2;
bsdf->offset = -stack_load_float(stack, data_node.z);
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 8e45dbfa5ff..6d6e92e73f6 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -16,19 +16,6 @@
CCL_NAMESPACE_BEGIN
-/* Float4 textures on various devices. */
-#if defined(__KERNEL_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
-# else
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CUDA_KEPLER
-# endif
-#else
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_OPENCL
-#endif
-
ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb, uint use_alpha)
{
#ifdef __KERNEL_CPU__
@@ -50,94 +37,94 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
switch(id) {
case 0: r = kernel_tex_image_interp(__tex_image_float4_000, x, y); break;
- case 1: r = kernel_tex_image_interp(__tex_image_float4_001, x, y); break;
- case 2: r = kernel_tex_image_interp(__tex_image_float4_002, x, y); break;
- case 3: r = kernel_tex_image_interp(__tex_image_float4_003, x, y); break;
- case 4: r = kernel_tex_image_interp(__tex_image_float4_004, x, y); break;
- case 5: r = kernel_tex_image_interp(__tex_image_byte4_005, x, y); break;
- case 6: r = kernel_tex_image_interp(__tex_image_byte4_006, x, y); break;
- case 7: r = kernel_tex_image_interp(__tex_image_byte4_007, x, y); break;
- case 8: r = kernel_tex_image_interp(__tex_image_byte4_008, x, y); break;
+ case 8: r = kernel_tex_image_interp(__tex_image_float4_008, x, y); break;
+ case 16: r = kernel_tex_image_interp(__tex_image_float4_016, x, y); break;
+ case 24: r = kernel_tex_image_interp(__tex_image_float4_024, x, y); break;
+ case 32: r = kernel_tex_image_interp(__tex_image_float4_032, x, y); break;
+ case 1: r = kernel_tex_image_interp(__tex_image_byte4_001, x, y); break;
case 9: r = kernel_tex_image_interp(__tex_image_byte4_009, x, y); break;
- case 10: r = kernel_tex_image_interp(__tex_image_byte4_010, x, y); break;
- case 11: r = kernel_tex_image_interp(__tex_image_byte4_011, x, y); break;
- case 12: r = kernel_tex_image_interp(__tex_image_byte4_012, x, y); break;
- case 13: r = kernel_tex_image_interp(__tex_image_byte4_013, x, y); break;
- case 14: r = kernel_tex_image_interp(__tex_image_byte4_014, x, y); break;
- case 15: r = kernel_tex_image_interp(__tex_image_byte4_015, x, y); break;
- case 16: r = kernel_tex_image_interp(__tex_image_byte4_016, x, y); break;
case 17: r = kernel_tex_image_interp(__tex_image_byte4_017, x, y); break;
- case 18: r = kernel_tex_image_interp(__tex_image_byte4_018, x, y); break;
- case 19: r = kernel_tex_image_interp(__tex_image_byte4_019, x, y); break;
- case 20: r = kernel_tex_image_interp(__tex_image_byte4_020, x, y); break;
- case 21: r = kernel_tex_image_interp(__tex_image_byte4_021, x, y); break;
- case 22: r = kernel_tex_image_interp(__tex_image_byte4_022, x, y); break;
- case 23: r = kernel_tex_image_interp(__tex_image_byte4_023, x, y); break;
- case 24: r = kernel_tex_image_interp(__tex_image_byte4_024, x, y); break;
case 25: r = kernel_tex_image_interp(__tex_image_byte4_025, x, y); break;
- case 26: r = kernel_tex_image_interp(__tex_image_byte4_026, x, y); break;
- case 27: r = kernel_tex_image_interp(__tex_image_byte4_027, x, y); break;
- case 28: r = kernel_tex_image_interp(__tex_image_byte4_028, x, y); break;
- case 29: r = kernel_tex_image_interp(__tex_image_byte4_029, x, y); break;
- case 30: r = kernel_tex_image_interp(__tex_image_byte4_030, x, y); break;
- case 31: r = kernel_tex_image_interp(__tex_image_byte4_031, x, y); break;
- case 32: r = kernel_tex_image_interp(__tex_image_byte4_032, x, y); break;
case 33: r = kernel_tex_image_interp(__tex_image_byte4_033, x, y); break;
- case 34: r = kernel_tex_image_interp(__tex_image_byte4_034, x, y); break;
- case 35: r = kernel_tex_image_interp(__tex_image_byte4_035, x, y); break;
- case 36: r = kernel_tex_image_interp(__tex_image_byte4_036, x, y); break;
- case 37: r = kernel_tex_image_interp(__tex_image_byte4_037, x, y); break;
- case 38: r = kernel_tex_image_interp(__tex_image_byte4_038, x, y); break;
- case 39: r = kernel_tex_image_interp(__tex_image_byte4_039, x, y); break;
- case 40: r = kernel_tex_image_interp(__tex_image_byte4_040, x, y); break;
case 41: r = kernel_tex_image_interp(__tex_image_byte4_041, x, y); break;
- case 42: r = kernel_tex_image_interp(__tex_image_byte4_042, x, y); break;
- case 43: r = kernel_tex_image_interp(__tex_image_byte4_043, x, y); break;
- case 44: r = kernel_tex_image_interp(__tex_image_byte4_044, x, y); break;
- case 45: r = kernel_tex_image_interp(__tex_image_byte4_045, x, y); break;
- case 46: r = kernel_tex_image_interp(__tex_image_byte4_046, x, y); break;
- case 47: r = kernel_tex_image_interp(__tex_image_byte4_047, x, y); break;
- case 48: r = kernel_tex_image_interp(__tex_image_byte4_048, x, y); break;
case 49: r = kernel_tex_image_interp(__tex_image_byte4_049, x, y); break;
- case 50: r = kernel_tex_image_interp(__tex_image_byte4_050, x, y); break;
- case 51: r = kernel_tex_image_interp(__tex_image_byte4_051, x, y); break;
- case 52: r = kernel_tex_image_interp(__tex_image_byte4_052, x, y); break;
- case 53: r = kernel_tex_image_interp(__tex_image_byte4_053, x, y); break;
- case 54: r = kernel_tex_image_interp(__tex_image_byte4_054, x, y); break;
- case 55: r = kernel_tex_image_interp(__tex_image_byte4_055, x, y); break;
- case 56: r = kernel_tex_image_interp(__tex_image_byte4_056, x, y); break;
case 57: r = kernel_tex_image_interp(__tex_image_byte4_057, x, y); break;
- case 58: r = kernel_tex_image_interp(__tex_image_byte4_058, x, y); break;
- case 59: r = kernel_tex_image_interp(__tex_image_byte4_059, x, y); break;
- case 60: r = kernel_tex_image_interp(__tex_image_byte4_060, x, y); break;
- case 61: r = kernel_tex_image_interp(__tex_image_byte4_061, x, y); break;
- case 62: r = kernel_tex_image_interp(__tex_image_byte4_062, x, y); break;
- case 63: r = kernel_tex_image_interp(__tex_image_byte4_063, x, y); break;
- case 64: r = kernel_tex_image_interp(__tex_image_byte4_064, x, y); break;
case 65: r = kernel_tex_image_interp(__tex_image_byte4_065, x, y); break;
- case 66: r = kernel_tex_image_interp(__tex_image_byte4_066, x, y); break;
- case 67: r = kernel_tex_image_interp(__tex_image_byte4_067, x, y); break;
- case 68: r = kernel_tex_image_interp(__tex_image_byte4_068, x, y); break;
- case 69: r = kernel_tex_image_interp(__tex_image_byte4_069, x, y); break;
- case 70: r = kernel_tex_image_interp(__tex_image_byte4_070, x, y); break;
- case 71: r = kernel_tex_image_interp(__tex_image_byte4_071, x, y); break;
- case 72: r = kernel_tex_image_interp(__tex_image_byte4_072, x, y); break;
case 73: r = kernel_tex_image_interp(__tex_image_byte4_073, x, y); break;
- case 74: r = kernel_tex_image_interp(__tex_image_byte4_074, x, y); break;
- case 75: r = kernel_tex_image_interp(__tex_image_byte4_075, x, y); break;
- case 76: r = kernel_tex_image_interp(__tex_image_byte4_076, x, y); break;
- case 77: r = kernel_tex_image_interp(__tex_image_byte4_077, x, y); break;
- case 78: r = kernel_tex_image_interp(__tex_image_byte4_078, x, y); break;
- case 79: r = kernel_tex_image_interp(__tex_image_byte4_079, x, y); break;
- case 80: r = kernel_tex_image_interp(__tex_image_byte4_080, x, y); break;
case 81: r = kernel_tex_image_interp(__tex_image_byte4_081, x, y); break;
- case 82: r = kernel_tex_image_interp(__tex_image_byte4_082, x, y); break;
- case 83: r = kernel_tex_image_interp(__tex_image_byte4_083, x, y); break;
- case 84: r = kernel_tex_image_interp(__tex_image_byte4_084, x, y); break;
- case 85: r = kernel_tex_image_interp(__tex_image_byte4_085, x, y); break;
- case 86: r = kernel_tex_image_interp(__tex_image_byte4_086, x, y); break;
- case 87: r = kernel_tex_image_interp(__tex_image_byte4_087, x, y); break;
- case 88: r = kernel_tex_image_interp(__tex_image_byte4_088, x, y); break;
+ case 89: r = kernel_tex_image_interp(__tex_image_byte4_089, x, y); break;
+ case 97: r = kernel_tex_image_interp(__tex_image_byte4_097, x, y); break;
+ case 105: r = kernel_tex_image_interp(__tex_image_byte4_105, x, y); break;
+ case 113: r = kernel_tex_image_interp(__tex_image_byte4_113, x, y); break;
+ case 121: r = kernel_tex_image_interp(__tex_image_byte4_121, x, y); break;
+ case 129: r = kernel_tex_image_interp(__tex_image_byte4_129, x, y); break;
+ case 137: r = kernel_tex_image_interp(__tex_image_byte4_137, x, y); break;
+ case 145: r = kernel_tex_image_interp(__tex_image_byte4_145, x, y); break;
+ case 153: r = kernel_tex_image_interp(__tex_image_byte4_153, x, y); break;
+ case 161: r = kernel_tex_image_interp(__tex_image_byte4_161, x, y); break;
+ case 169: r = kernel_tex_image_interp(__tex_image_byte4_169, x, y); break;
+ case 177: r = kernel_tex_image_interp(__tex_image_byte4_177, x, y); break;
+ case 185: r = kernel_tex_image_interp(__tex_image_byte4_185, x, y); break;
+ case 193: r = kernel_tex_image_interp(__tex_image_byte4_193, x, y); break;
+ case 201: r = kernel_tex_image_interp(__tex_image_byte4_201, x, y); break;
+ case 209: r = kernel_tex_image_interp(__tex_image_byte4_209, x, y); break;
+ case 217: r = kernel_tex_image_interp(__tex_image_byte4_217, x, y); break;
+ case 225: r = kernel_tex_image_interp(__tex_image_byte4_225, x, y); break;
+ case 233: r = kernel_tex_image_interp(__tex_image_byte4_233, x, y); break;
+ case 241: r = kernel_tex_image_interp(__tex_image_byte4_241, x, y); break;
+ case 249: r = kernel_tex_image_interp(__tex_image_byte4_249, x, y); break;
+ case 257: r = kernel_tex_image_interp(__tex_image_byte4_257, x, y); break;
+ case 265: r = kernel_tex_image_interp(__tex_image_byte4_265, x, y); break;
+ case 273: r = kernel_tex_image_interp(__tex_image_byte4_273, x, y); break;
+ case 281: r = kernel_tex_image_interp(__tex_image_byte4_281, x, y); break;
+ case 289: r = kernel_tex_image_interp(__tex_image_byte4_289, x, y); break;
+ case 297: r = kernel_tex_image_interp(__tex_image_byte4_297, x, y); break;
+ case 305: r = kernel_tex_image_interp(__tex_image_byte4_305, x, y); break;
+ case 313: r = kernel_tex_image_interp(__tex_image_byte4_313, x, y); break;
+ case 321: r = kernel_tex_image_interp(__tex_image_byte4_321, x, y); break;
+ case 329: r = kernel_tex_image_interp(__tex_image_byte4_329, x, y); break;
+ case 337: r = kernel_tex_image_interp(__tex_image_byte4_337, x, y); break;
+ case 345: r = kernel_tex_image_interp(__tex_image_byte4_345, x, y); break;
+ case 353: r = kernel_tex_image_interp(__tex_image_byte4_353, x, y); break;
+ case 361: r = kernel_tex_image_interp(__tex_image_byte4_361, x, y); break;
+ case 369: r = kernel_tex_image_interp(__tex_image_byte4_369, x, y); break;
+ case 377: r = kernel_tex_image_interp(__tex_image_byte4_377, x, y); break;
+ case 385: r = kernel_tex_image_interp(__tex_image_byte4_385, x, y); break;
+ case 393: r = kernel_tex_image_interp(__tex_image_byte4_393, x, y); break;
+ case 401: r = kernel_tex_image_interp(__tex_image_byte4_401, x, y); break;
+ case 409: r = kernel_tex_image_interp(__tex_image_byte4_409, x, y); break;
+ case 417: r = kernel_tex_image_interp(__tex_image_byte4_417, x, y); break;
+ case 425: r = kernel_tex_image_interp(__tex_image_byte4_425, x, y); break;
+ case 433: r = kernel_tex_image_interp(__tex_image_byte4_433, x, y); break;
+ case 441: r = kernel_tex_image_interp(__tex_image_byte4_441, x, y); break;
+ case 449: r = kernel_tex_image_interp(__tex_image_byte4_449, x, y); break;
+ case 457: r = kernel_tex_image_interp(__tex_image_byte4_457, x, y); break;
+ case 465: r = kernel_tex_image_interp(__tex_image_byte4_465, x, y); break;
+ case 473: r = kernel_tex_image_interp(__tex_image_byte4_473, x, y); break;
+ case 481: r = kernel_tex_image_interp(__tex_image_byte4_481, x, y); break;
+ case 489: r = kernel_tex_image_interp(__tex_image_byte4_489, x, y); break;
+ case 497: r = kernel_tex_image_interp(__tex_image_byte4_497, x, y); break;
+ case 505: r = kernel_tex_image_interp(__tex_image_byte4_505, x, y); break;
+ case 513: r = kernel_tex_image_interp(__tex_image_byte4_513, x, y); break;
+ case 521: r = kernel_tex_image_interp(__tex_image_byte4_521, x, y); break;
+ case 529: r = kernel_tex_image_interp(__tex_image_byte4_529, x, y); break;
+ case 537: r = kernel_tex_image_interp(__tex_image_byte4_537, x, y); break;
+ case 545: r = kernel_tex_image_interp(__tex_image_byte4_545, x, y); break;
+ case 553: r = kernel_tex_image_interp(__tex_image_byte4_553, x, y); break;
+ case 561: r = kernel_tex_image_interp(__tex_image_byte4_561, x, y); break;
+ case 569: r = kernel_tex_image_interp(__tex_image_byte4_569, x, y); break;
+ case 577: r = kernel_tex_image_interp(__tex_image_byte4_577, x, y); break;
+ case 585: r = kernel_tex_image_interp(__tex_image_byte4_585, x, y); break;
+ case 593: r = kernel_tex_image_interp(__tex_image_byte4_593, x, y); break;
+ case 601: r = kernel_tex_image_interp(__tex_image_byte4_601, x, y); break;
+ case 609: r = kernel_tex_image_interp(__tex_image_byte4_609, x, y); break;
+ case 617: r = kernel_tex_image_interp(__tex_image_byte4_617, x, y); break;
+ case 625: r = kernel_tex_image_interp(__tex_image_byte4_625, x, y); break;
+ case 633: r = kernel_tex_image_interp(__tex_image_byte4_633, x, y); break;
+ case 641: r = kernel_tex_image_interp(__tex_image_byte4_641, x, y); break;
+ case 649: r = kernel_tex_image_interp(__tex_image_byte4_649, x, y); break;
+ case 657: r = kernel_tex_image_interp(__tex_image_byte4_657, x, y); break;
+ case 665: r = kernel_tex_image_interp(__tex_image_byte4_665, x, y); break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
@@ -224,6 +211,8 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float
object_inverse_normal_transform(kg, sd, &N);
/* project from direction vector to barycentric coordinates in triangles */
+ float3 signed_N = N;
+
N.x = fabsf(N.x);
N.y = fabsf(N.y);
N.z = fabsf(N.z);
@@ -293,12 +282,19 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float
float4 f = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
uint use_alpha = stack_valid(alpha_offset);
- if(weight.x > 0.0f)
- f += weight.x*svm_image_texture(kg, id, co.y, co.z, srgb, use_alpha);
- if(weight.y > 0.0f)
- f += weight.y*svm_image_texture(kg, id, co.x, co.z, srgb, use_alpha);
- if(weight.z > 0.0f)
- f += weight.z*svm_image_texture(kg, id, co.y, co.x, srgb, use_alpha);
+ /* Map so that no textures are flipped, rotation is somewhat arbitrary. */
+ if(weight.x > 0.0f) {
+ float2 uv = make_float2((signed_N.x < 0.0f)? 1.0f - co.y: co.y, co.z);
+ f += weight.x*svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
+ }
+ if(weight.y > 0.0f) {
+ float2 uv = make_float2((signed_N.y > 0.0f)? 1.0f - co.x: co.x, co.z);
+ f += weight.y*svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
+ }
+ if(weight.z > 0.0f) {
+ float2 uv = make_float2((signed_N.z > 0.0f)? 1.0f - co.y: co.y, co.x);
+ f += weight.z*svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
+ }
if(stack_valid(out_offset))
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp
index 2569d9eec27..943b218f0e4 100644
--- a/intern/cycles/render/constant_fold.cpp
+++ b/intern/cycles/render/constant_fold.cpp
@@ -160,6 +160,14 @@ bool ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, bool clamp)
bypass(input->link);
return true;
}
+ else {
+ /* disconnect other inputs if we can't fully bypass due to clamp */
+ foreach(ShaderInput *other, node->inputs) {
+ if(other != input && other->link) {
+ graph->disconnect(other);
+ }
+ }
+ }
return false;
}
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 2d810ff664f..08203163d1a 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -221,28 +221,6 @@ OutputNode *ShaderGraph::output()
return (OutputNode*)nodes.front();
}
-ShaderGraph *ShaderGraph::copy()
-{
- ShaderGraph *newgraph = new ShaderGraph();
-
- /* copy nodes */
- ShaderNodeSet nodes_all;
- foreach(ShaderNode *node, nodes)
- nodes_all.insert(node);
-
- ShaderNodeMap nodes_copy;
- copy_nodes(nodes_all, nodes_copy);
-
- /* add nodes (in same order, so output is still first) */
- newgraph->clear_nodes();
- foreach(ShaderNode *node, nodes)
- newgraph->add(nodes_copy[node]);
-
- newgraph->simplified = simplified;
-
- return newgraph;
-}
-
void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
{
assert(!finalized);
@@ -1040,6 +1018,9 @@ int ShaderGraph::get_num_closures()
else if(CLOSURE_IS_PRINCIPLED(closure_type)) {
num_closures += 8;
}
+ else if(CLOSURE_IS_VOLUME(closure_type)) {
+ num_closures += VOLUME_STACK_SIZE;
+ }
else {
++num_closures;
}
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 72e391991a7..f0fd789c6bd 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -151,6 +151,7 @@ public:
virtual bool has_surface_emission() { return false; }
virtual bool has_surface_transparent() { return false; }
virtual bool has_surface_bssrdf() { return false; }
+ virtual bool has_bump() { return false; }
virtual bool has_bssrdf_bump() { return false; }
virtual bool has_spatial_varying() { return false; }
virtual bool has_object_dependency() { return false; }
@@ -245,8 +246,6 @@ public:
ShaderGraph();
~ShaderGraph();
- ShaderGraph *copy();
-
ShaderNode *add(ShaderNode *node);
OutputNode *output();
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index f4482e0bb25..bb94b9bb82a 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -43,7 +43,6 @@ static bool isfinite(half /*value*/)
ImageManager::ImageManager(const DeviceInfo& info)
{
need_update = true;
- pack_images = false;
osl_texture_system = NULL;
animation_frame = 0;
@@ -87,11 +86,6 @@ ImageManager::~ImageManager()
}
}
-void ImageManager::set_pack_images(bool pack_images_)
-{
- pack_images = pack_images_;
-}
-
void ImageManager::set_osl_texture_system(void *texture_system)
{
osl_texture_system = texture_system;
@@ -115,16 +109,18 @@ bool ImageManager::set_animation_frame_update(int frame)
ImageDataType ImageManager::get_image_metadata(const string& filename,
void *builtin_data,
- bool& is_linear)
+ bool& is_linear,
+ bool& builtin_free_cache)
{
bool is_float = false, is_half = false;
is_linear = false;
+ builtin_free_cache = false;
int channels = 4;
if(builtin_data) {
if(builtin_image_info_cb) {
int width, height, depth;
- builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels);
+ builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels, builtin_free_cache);
}
if(is_float) {
@@ -218,37 +214,14 @@ int ImageManager::max_flattened_slot(ImageDataType type)
/* The lower three bits of a device texture slot number indicate its type.
* These functions convert the slot ids from ImageManager "images" ones
* to device ones and vice verse.
- *
- * There are special cases for CUDA Fermi, since there we have only 90 image texture
- * slots available and should keep the flattended numbers in the 0-89 range.
*/
int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type)
{
- if(cuda_fermi_limits) {
- if(type == IMAGE_DATA_TYPE_BYTE4) {
- return slot + TEX_START_BYTE4_CUDA;
- }
- else {
- return slot;
- }
- }
-
return (slot << IMAGE_DATA_TYPE_SHIFT) | (type);
}
int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type)
{
- if(cuda_fermi_limits) {
- if(flat_slot >= 4) {
- *type = IMAGE_DATA_TYPE_BYTE4;
- return flat_slot - TEX_START_BYTE4_CUDA;
- }
- else {
- *type = IMAGE_DATA_TYPE_FLOAT4;
- return flat_slot;
- }
- }
-
*type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK);
return flat_slot >> IMAGE_DATA_TYPE_SHIFT;
}
@@ -295,8 +268,9 @@ int ImageManager::add_image(const string& filename,
{
Image *img;
size_t slot;
+ bool builtin_free_cache;
- ImageDataType type = get_image_metadata(filename, builtin_data, is_linear);
+ ImageDataType type = get_image_metadata(filename, builtin_data, is_linear, builtin_free_cache);
thread_scoped_lock device_lock(device_mutex);
@@ -364,7 +338,7 @@ int ImageManager::add_image(const string& filename,
else {
/* Very unlikely, since max_num_images is insanely big. But better safe than sorry. */
int tex_count = 0;
- for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
tex_count += tex_num_images[type];
}
if(tex_count > max_num_images) {
@@ -382,6 +356,7 @@ int ImageManager::add_image(const string& filename,
img = new Image();
img->filename = filename;
img->builtin_data = builtin_data;
+ img->builtin_free_cache = builtin_free_cache;
img->need_load = true;
img->animated = animated;
img->frame = frame;
@@ -467,7 +442,12 @@ void ImageManager::tag_reload_image(const string& filename,
}
}
-bool ImageManager::file_load_image_generic(Image *img, ImageInput **in, int &width, int &height, int &depth, int &components)
+bool ImageManager::file_load_image_generic(Image *img,
+ ImageInput **in,
+ int &width,
+ int &height,
+ int &depth,
+ int &components)
{
if(img->filename == "")
return false;
@@ -506,8 +486,8 @@ bool ImageManager::file_load_image_generic(Image *img, ImageInput **in, int &wid
if(!builtin_image_info_cb || !builtin_image_pixels_cb)
return false;
- bool is_float;
- builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components);
+ bool is_float, free_cache;
+ builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components, free_cache);
}
/* we only handle certain number of components */
@@ -542,6 +522,10 @@ bool ImageManager::file_load_image(Image *img,
vector<StorageType> pixels_storage;
StorageType *pixels;
const size_t max_size = max(max(width, height), depth);
+ if(max_size == 0) {
+ /* Don't bother with invalid images. */
+ return false;
+ }
if(texture_limit > 0 && max_size > texture_limit) {
pixels_storage.resize(((size_t)width)*height*depth*4);
pixels = &pixels_storage[0];
@@ -549,6 +533,10 @@ bool ImageManager::file_load_image(Image *img,
else {
pixels = (StorageType*)tex_img.resize(width, height, depth);
}
+ if(pixels == NULL) {
+ /* Could be that we've run out of memory. */
+ return false;
+ }
bool cmyk = false;
const size_t num_pixels = ((size_t)width) * height * depth;
if(in) {
@@ -588,13 +576,15 @@ bool ImageManager::file_load_image(Image *img,
builtin_image_float_pixels_cb(img->filename,
img->builtin_data,
(float*)&pixels[0],
- num_pixels * components);
+ num_pixels * components,
+ img->builtin_free_cache);
}
else if(FileFormat == TypeDesc::UINT8) {
builtin_image_pixels_cb(img->filename,
img->builtin_data,
(uchar*)&pixels[0],
- num_pixels * components);
+ num_pixels * components,
+ img->builtin_free_cache);
}
else {
/* TODO(dingto): Support half for ImBuf. */
@@ -754,7 +744,7 @@ void ImageManager::device_load_image(Device *device,
pixels[3] = TEX_IMAGE_MISSING_A;
}
- if(!pack_images) {
+ {
thread_scoped_lock device_lock(device_mutex);
device->tex_alloc(name.c_str(),
tex_img,
@@ -783,7 +773,7 @@ void ImageManager::device_load_image(Device *device,
pixels[0] = TEX_IMAGE_MISSING_R;
}
- if(!pack_images) {
+ {
thread_scoped_lock device_lock(device_mutex);
device->tex_alloc(name.c_str(),
tex_img,
@@ -815,7 +805,7 @@ void ImageManager::device_load_image(Device *device,
pixels[3] = (TEX_IMAGE_MISSING_A * 255);
}
- if(!pack_images) {
+ {
thread_scoped_lock device_lock(device_mutex);
device->tex_alloc(name.c_str(),
tex_img,
@@ -843,7 +833,7 @@ void ImageManager::device_load_image(Device *device,
pixels[0] = (TEX_IMAGE_MISSING_R * 255);
}
- if(!pack_images) {
+ {
thread_scoped_lock device_lock(device_mutex);
device->tex_alloc(name.c_str(),
tex_img,
@@ -874,7 +864,7 @@ void ImageManager::device_load_image(Device *device,
pixels[3] = TEX_IMAGE_MISSING_A;
}
- if(!pack_images) {
+ {
thread_scoped_lock device_lock(device_mutex);
device->tex_alloc(name.c_str(),
tex_img,
@@ -902,7 +892,7 @@ void ImageManager::device_load_image(Device *device,
pixels[0] = TEX_IMAGE_MISSING_R;
}
- if(!pack_images) {
+ {
thread_scoped_lock device_lock(device_mutex);
device->tex_alloc(name.c_str(),
tex_img,
@@ -1059,9 +1049,6 @@ void ImageManager::device_update(Device *device,
pool.wait_work();
- if(pack_images)
- device_pack_images(device, dscene, progress);
-
need_update = false;
}
@@ -1091,141 +1078,6 @@ void ImageManager::device_update_slot(Device *device,
}
}
-uint8_t ImageManager::pack_image_options(ImageDataType type, size_t slot)
-{
- uint8_t options = 0;
- /* Image Options are packed into one uint:
- * bit 0 -> Interpolation
- * bit 1 + 2 + 3 -> Extension
- */
- if(images[type][slot]->interpolation == INTERPOLATION_CLOSEST) {
- options |= (1 << 0);
- }
- if(images[type][slot]->extension == EXTENSION_REPEAT) {
- options |= (1 << 1);
- }
- else if(images[type][slot]->extension == EXTENSION_EXTEND) {
- options |= (1 << 2);
- }
- else /* EXTENSION_CLIP */ {
- options |= (1 << 3);
- }
- return options;
-}
-
-template<typename T>
-void ImageManager::device_pack_images_type(
- ImageDataType type,
- const vector<device_vector<T>*>& cpu_textures,
- device_vector<T> *device_image,
- uint4 *info)
-{
- size_t size = 0, offset = 0;
- /* First step is to calculate size of the texture we need. */
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] == NULL) {
- continue;
- }
- device_vector<T>& tex_img = *cpu_textures[slot];
- size += tex_img.size();
- }
- /* Now we know how much memory we need, so we can allocate and fill. */
- T *pixels = device_image->resize(size);
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] == NULL) {
- continue;
- }
- device_vector<T>& tex_img = *cpu_textures[slot];
- uint8_t options = pack_image_options(type, slot);
- const int index = type_index_to_flattened_slot(slot, type) * 2;
- info[index] = make_uint4(tex_img.data_width,
- tex_img.data_height,
- offset,
- options);
- info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0);
- memcpy(pixels + offset,
- (void*)tex_img.data_pointer,
- tex_img.memory_size());
- offset += tex_img.size();
- }
-}
-
-void ImageManager::device_pack_images(Device *device,
- DeviceScene *dscene,
- Progress& /*progess*/)
-{
- /* For OpenCL, we pack all image textures into a single large texture, and
- * do our own interpolation in the kernel.
- */
-
- /* TODO(sergey): This will over-allocate a bit, but this is constant memory
- * so should be fine for a short term.
- */
- const size_t info_size = max4(max_flattened_slot(IMAGE_DATA_TYPE_FLOAT4),
- max_flattened_slot(IMAGE_DATA_TYPE_BYTE4),
- max_flattened_slot(IMAGE_DATA_TYPE_FLOAT),
- max_flattened_slot(IMAGE_DATA_TYPE_BYTE));
- uint4 *info = dscene->tex_image_packed_info.resize(info_size*2);
-
- /* Pack byte4 textures. */
- device_pack_images_type(IMAGE_DATA_TYPE_BYTE4,
- dscene->tex_byte4_image,
- &dscene->tex_image_byte4_packed,
- info);
- /* Pack float4 textures. */
- device_pack_images_type(IMAGE_DATA_TYPE_FLOAT4,
- dscene->tex_float4_image,
- &dscene->tex_image_float4_packed,
- info);
- /* Pack byte textures. */
- device_pack_images_type(IMAGE_DATA_TYPE_BYTE,
- dscene->tex_byte_image,
- &dscene->tex_image_byte_packed,
- info);
- /* Pack float textures. */
- device_pack_images_type(IMAGE_DATA_TYPE_FLOAT,
- dscene->tex_float_image,
- &dscene->tex_image_float_packed,
- info);
-
- /* Push textures to the device. */
- if(dscene->tex_image_byte4_packed.size()) {
- if(dscene->tex_image_byte4_packed.device_pointer) {
- thread_scoped_lock device_lock(device_mutex);
- device->tex_free(dscene->tex_image_byte4_packed);
- }
- device->tex_alloc("__tex_image_byte4_packed", dscene->tex_image_byte4_packed);
- }
- if(dscene->tex_image_float4_packed.size()) {
- if(dscene->tex_image_float4_packed.device_pointer) {
- thread_scoped_lock device_lock(device_mutex);
- device->tex_free(dscene->tex_image_float4_packed);
- }
- 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);
- device->tex_free(dscene->tex_image_packed_info);
- }
- device->tex_alloc("__tex_image_packed_info", dscene->tex_image_packed_info);
- }
-}
-
void ImageManager::device_free_builtin(Device *device, DeviceScene *dscene)
{
for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
@@ -1251,18 +1103,6 @@ void ImageManager::device_free(Device *device, DeviceScene *dscene)
dscene->tex_float_image.clear();
dscene->tex_byte_image.clear();
dscene->tex_half_image.clear();
-
- device->tex_free(dscene->tex_image_float4_packed);
- device->tex_free(dscene->tex_image_byte4_packed);
- device->tex_free(dscene->tex_image_float_packed);
- device->tex_free(dscene->tex_image_byte_packed);
- device->tex_free(dscene->tex_image_packed_info);
-
- dscene->tex_image_float4_packed.clear();
- dscene->tex_image_byte4_packed.clear();
- dscene->tex_image_float_packed.clear();
- dscene->tex_image_byte_packed.clear();
- dscene->tex_image_packed_info.clear();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 77214bf25bc..c86d1cbedbf 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -57,7 +57,10 @@ public:
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha);
- ImageDataType get_image_metadata(const string& filename, void *builtin_data, bool& is_linear);
+ ImageDataType get_image_metadata(const string& filename,
+ void *builtin_data,
+ bool& is_linear,
+ bool& builtin_free_cache);
void device_prepare_update(DeviceScene *dscene);
void device_update(Device *device,
@@ -73,7 +76,6 @@ public:
void device_free_builtin(Device *device, DeviceScene *dscene);
void set_osl_texture_system(void *texture_system);
- void set_pack_images(bool pack_images_);
bool set_animation_frame_update(int frame);
bool need_update;
@@ -88,19 +90,23 @@ public:
int &width,
int &height,
int &depth,
- int &channels)> builtin_image_info_cb;
+ int &channels,
+ bool &free_cache)> builtin_image_info_cb;
function<bool(const string &filename,
void *data,
unsigned char *pixels,
- const size_t pixels_size)> builtin_image_pixels_cb;
+ const size_t pixels_size,
+ const bool free_cache)> builtin_image_pixels_cb;
function<bool(const string &filename,
void *data,
float *pixels,
- const size_t pixels_size)> builtin_image_float_pixels_cb;
+ const size_t pixels_size,
+ const bool free_cache)> builtin_image_float_pixels_cb;
struct Image {
string filename;
void *builtin_data;
+ bool builtin_free_cache;
bool use_alpha;
bool need_load;
@@ -123,9 +129,13 @@ private:
vector<Image*> images[IMAGE_DATA_NUM_TYPES];
void *osl_texture_system;
- bool pack_images;
- bool file_load_image_generic(Image *img, ImageInput **in, int &width, int &height, int &depth, int &components);
+ bool file_load_image_generic(Image *img,
+ ImageInput **in,
+ int &width,
+ int &height,
+ int &depth,
+ int &components);
template<TypeDesc::BASETYPE FileFormat,
typename StorageType,
@@ -140,8 +150,6 @@ private:
int flattened_slot_to_type_index(int flat_slot, ImageDataType *type);
string name_from_type(int type);
- uint8_t pack_image_options(ImageDataType type, size_t slot);
-
void device_load_image(Device *device,
DeviceScene *dscene,
Scene *scene,
@@ -152,17 +160,6 @@ private:
DeviceScene *dscene,
ImageDataType type,
int slot);
-
- template<typename T>
- void device_pack_images_type(
- ImageDataType type,
- const vector<device_vector<T>*>& cpu_textures,
- device_vector<T> *device_image,
- uint4 *info);
-
- void device_pack_images(Device *device,
- DeviceScene *dscene,
- Progress& progess);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index a004bb5b856..15b728d6e02 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -31,7 +31,6 @@ NODE_DEFINE(Integrator)
{
NodeType *type = NodeType::add("integrator", create);
- SOCKET_INT(min_bounce, "Min Bounce", 2);
SOCKET_INT(max_bounce, "Max Bounce", 7);
SOCKET_INT(max_diffuse_bounce, "Max Diffuse Bounce", 7);
@@ -39,9 +38,7 @@ NODE_DEFINE(Integrator)
SOCKET_INT(max_transmission_bounce, "Max Transmission Bounce", 7);
SOCKET_INT(max_volume_bounce, "Max Volume Bounce", 7);
- SOCKET_INT(transparent_min_bounce, "Transparent Min Bounce", 2);
SOCKET_INT(transparent_max_bounce, "Transparent Max Bounce", 7);
- SOCKET_BOOLEAN(transparent_shadows, "Transparent Shadows", false);
SOCKET_INT(ao_bounces, "AO Bounces", 0);
@@ -104,7 +101,6 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
/* integrator parameters */
kintegrator->max_bounce = max_bounce + 1;
- kintegrator->min_bounce = min_bounce + 1;
kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
@@ -112,7 +108,6 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->max_volume_bounce = max_volume_bounce + 1;
kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
- kintegrator->transparent_min_bounce = transparent_min_bounce + 1;
if(ao_bounces == 0) {
kintegrator->ao_bounces = INT_MAX;
@@ -125,19 +120,14 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
* We only need to enable transparent shadows, if we actually have
* transparent shaders in the scene. Otherwise we can disable it
* to improve performance a bit. */
- if(transparent_shadows) {
- kintegrator->transparent_shadows = false;
- foreach(Shader *shader, scene->shaders) {
- /* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */
- if((shader->has_surface_transparent && shader->use_transparent_shadow) || shader->has_volume) {
- kintegrator->transparent_shadows = true;
- break;
- }
+ kintegrator->transparent_shadows = false;
+ foreach(Shader *shader, scene->shaders) {
+ /* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */
+ if((shader->has_surface_transparent && shader->use_transparent_shadow) || shader->has_volume) {
+ kintegrator->transparent_shadows = true;
+ break;
}
}
- else {
- kintegrator->transparent_shadows = false;
- }
kintegrator->volume_max_steps = volume_max_steps;
kintegrator->volume_step_size = volume_step_size;
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index 9501d7f8416..3cb430d72b4 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -31,7 +31,6 @@ class Integrator : public Node {
public:
NODE_DECLARE
- int min_bounce;
int max_bounce;
int max_diffuse_bounce;
@@ -39,9 +38,7 @@ public:
int max_transmission_bounce;
int max_volume_bounce;
- int transparent_min_bounce;
int transparent_max_bounce;
- bool transparent_shadows;
int ao_bounces;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 625dd3ded39..4adc00bc839 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -224,12 +224,12 @@ void LightManager::disable_ineffective_light(Device *device, Scene *scene)
bool LightManager::object_usable_as_light(Object *object) {
Mesh *mesh = object->mesh;
- /* Skip if we are not visible for BSDFs. */
- if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
+ /* Skip objects with NaNs */
+ if(!object->bounds.valid()) {
return false;
}
- /* Skip motion blurred deforming meshes, not supported yet. */
- if(mesh->has_motion_blur()) {
+ /* Skip if we are not visible for BSDFs. */
+ if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
return false;
}
/* Skip if we have no emission shaders. */
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 03825f780e0..84537bf5993 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -1925,16 +1925,7 @@ void MeshManager::device_update_displacement_images(Device *device,
if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
continue;
}
- if(device->info.pack_images) {
- /* If device requires packed images we need to update all
- * images now, even if they're not used for displacement.
- */
- image_manager->device_update(device,
- dscene,
- scene,
- progress);
- return;
- }
+
ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode*>(node);
int slot = image_node->slot;
if(slot != -1) {
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 57b475e5cd0..2b682756c6a 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -365,7 +365,8 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
if(is_float == -1) {
if(builtin_data == NULL) {
ImageDataType type;
- type = image_manager->get_image_metadata(filename.string(), NULL, is_linear);
+ bool builtin_free_cache;
+ type = image_manager->get_image_metadata(filename.string(), NULL, is_linear, builtin_free_cache);
if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4)
is_float = 1;
}
@@ -554,7 +555,8 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
if(is_float == -1) {
if(builtin_data == NULL) {
ImageDataType type;
- type = image_manager->get_image_metadata(filename.string(), NULL, is_linear);
+ bool builtin_free_cache;
+ type = image_manager->get_image_metadata(filename.string(), NULL, is_linear, builtin_free_cache);
if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4)
is_float = 1;
}
@@ -1799,6 +1801,14 @@ BsdfBaseNode::BsdfBaseNode(const NodeType *node_type)
special_type = SHADER_SPECIAL_TYPE_CLOSURE;
}
+bool BsdfBaseNode::has_bump()
+{
+ /* detect if anything is plugged into the normal input besides the default */
+ ShaderInput *normal_in = input("Normal");
+ return (normal_in && normal_in->link &&
+ normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
+}
+
/* BSDF Closure */
BsdfNode::BsdfNode(const NodeType *node_type)
@@ -2308,13 +2318,13 @@ NODE_DEFINE(PrincipledBsdfNode)
SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
- SOCKET_IN_FLOAT(clearcoat_gloss, "Clearcoat Gloss", 0.0f);
+ SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
SOCKET_IN_FLOAT(transmission_roughness, "Transmission Roughness", 0.0f);
@@ -2337,6 +2347,12 @@ PrincipledBsdfNode::PrincipledBsdfNode()
distribution_orig = NBUILTIN_CLOSURES;
}
+bool PrincipledBsdfNode::has_surface_bssrdf()
+{
+ ShaderInput *subsurface_in = input("Subsurface");
+ return (subsurface_in->link != NULL || subsurface > CLOSURE_WEIGHT_CUTOFF);
+}
+
void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if(shader->has_surface) {
@@ -2351,7 +2367,7 @@ void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attribu
void PrincipledBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, ShaderInput *p_subsurface, ShaderInput *p_subsurface_radius,
ShaderInput *p_specular, ShaderInput *p_roughness, ShaderInput *p_specular_tint, ShaderInput *p_anisotropic,
- ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_gloss,
+ ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_roughness,
ShaderInput *p_ior, ShaderInput *p_transmission, ShaderInput *p_anisotropic_rotation, ShaderInput *p_transmission_roughness)
{
ShaderInput *base_color_in = input("Base Color");
@@ -2374,7 +2390,7 @@ void PrincipledBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic,
int sheen_offset = compiler.stack_assign(p_sheen);
int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
int clearcoat_offset = compiler.stack_assign(p_clearcoat);
- int clearcoat_gloss_offset = compiler.stack_assign(p_clearcoat_gloss);
+ int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
int ior_offset = compiler.stack_assign(p_ior);
int transmission_offset = compiler.stack_assign(p_transmission);
int transmission_roughness_offset = compiler.stack_assign(p_transmission_roughness);
@@ -2391,7 +2407,7 @@ void PrincipledBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic,
compiler.add_node(normal_offset, tangent_offset,
compiler.encode_uchar4(specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
- compiler.encode_uchar4(sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset));
+ compiler.encode_uchar4(sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
compiler.add_node(compiler.encode_uchar4(ior_offset, transmission_offset, anisotropic_rotation_offset, transmission_roughness_offset),
distribution, SVM_STACK_INVALID, SVM_STACK_INVALID);
@@ -2419,7 +2435,7 @@ void PrincipledBsdfNode::compile(SVMCompiler& compiler)
{
compile(compiler, input("Metallic"), input("Subsurface"), input("Subsurface Radius"), input("Specular"),
input("Roughness"), input("Specular Tint"), input("Anisotropic"), input("Sheen"), input("Sheen Tint"),
- input("Clearcoat"), input("Clearcoat Gloss"), input("IOR"), input("Transmission"),
+ input("Clearcoat"), input("Clearcoat Roughness"), input("IOR"), input("Transmission"),
input("Anisotropic Rotation"), input("Transmission Roughness"));
}
@@ -2431,9 +2447,7 @@ void PrincipledBsdfNode::compile(OSLCompiler& compiler)
bool PrincipledBsdfNode::has_bssrdf_bump()
{
- /* detect if anything is plugged into the normal input besides the default */
- ShaderInput *normal_in = input("Normal");
- return (normal_in->link && normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
+ return has_surface_bssrdf() && has_bump();
}
/* Translucent BSDF Closure */
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index aac6ce2f375..ec4c7c7c50d 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -252,6 +252,7 @@ public:
class PointDensityTextureNode : public ShaderNode {
public:
SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
~PointDensityTextureNode();
ShaderNode *clone() const;
@@ -325,6 +326,16 @@ class BsdfBaseNode : public ShaderNode {
public:
BsdfBaseNode(const NodeType *node_type);
+ bool has_spatial_varying() { return true; }
+ virtual ClosureType get_closure_type() { return closure; }
+ virtual bool has_bump();
+
+ virtual bool equals(const ShaderNode& /*other*/)
+ {
+ /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
+ return false;
+ }
+
ClosureType closure;
};
@@ -333,19 +344,11 @@ public:
explicit BsdfNode(const NodeType *node_type);
SHADER_NODE_BASE_CLASS(BsdfNode)
- bool has_spatial_varying() { return true; }
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL);
- virtual ClosureType get_closure_type() { return closure; }
float3 color;
float3 normal;
float surface_mix_weight;
-
- virtual bool equals(const ShaderNode& /*other*/)
- {
- /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
- return false;
- }
};
class AnisotropicBsdfNode : public BsdfNode {
@@ -372,30 +375,22 @@ class PrincipledBsdfNode : public BsdfBaseNode {
public:
SHADER_NODE_CLASS(PrincipledBsdfNode)
- bool has_spatial_varying() { return true; }
- bool has_surface_bssrdf() { return true; }
+ bool has_surface_bssrdf();
bool has_bssrdf_bump();
void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius,
ShaderInput *specular, ShaderInput *roughness, ShaderInput *specular_tint, ShaderInput *anisotropic,
- ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_gloss,
+ ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_roughness,
ShaderInput *ior, ShaderInput *transmission, ShaderInput *anisotropic_rotation, ShaderInput *transmission_roughness);
float3 base_color;
float3 subsurface_color, subsurface_radius;
float metallic, subsurface, specular, roughness, specular_tint, anisotropic,
- sheen, sheen_tint, clearcoat, clearcoat_gloss, ior, transmission,
+ sheen, sheen_tint, clearcoat, clearcoat_roughness, ior, transmission,
anisotropic_rotation, transmission_roughness;
float3 normal, clearcoat_normal, tangent;
float surface_mix_weight;
ClosureType distribution, distribution_orig;
- virtual bool equals(const ShaderNode * /*other*/)
- {
- /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
- return false;
- }
-
- ClosureType get_closure_type() { return closure; }
bool has_integrator_dependency();
void attributes(Shader *shader, AttributeRequestSet *attributes);
};
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 375abfeb27a..12690090066 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -262,6 +262,17 @@ bool Object::is_traceable()
return true;
}
+uint Object::visibility_for_tracing() const {
+ uint trace_visibility = visibility;
+ if (is_shadow_catcher) {
+ trace_visibility &= ~PATH_RAY_SHADOW_NON_CATCHER;
+ }
+ else {
+ trace_visibility &= ~PATH_RAY_SHADOW_CATCHER;
+ }
+ return trace_visibility;
+}
+
/* Object Manager */
ObjectManager::ObjectManager()
@@ -356,6 +367,13 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
/* OBJECT_PROPERTIES */
objects[offset+8] = make_float4(surface_area, pass_id, random_number, __int_as_float(particle_index));
+ if(mesh->use_motion_blur) {
+ state->have_motion = true;
+ }
+ if(mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
+ flag |= SD_OBJECT_HAS_VERTEX_MOTION;
+ }
+
if(state->need_motion == Scene::MOTION_PASS) {
/* Motion transformations, is world/object space depending if mesh
* comes with deformed position in object space, or if we transform
@@ -376,9 +394,6 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
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);
@@ -397,10 +412,6 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
}
#endif
- if(mesh->use_motion_blur) {
- state->have_motion = true;
- }
-
/* Dupli object coords and motion info. */
int totalsteps = mesh->motion_steps;
int numsteps = (totalsteps - 1)/2;
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 12d7b2c81cf..6927bbfe4c7 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -60,7 +60,7 @@ public:
ParticleSystem *particle_system;
int particle_index;
-
+
Object();
~Object();
@@ -75,6 +75,11 @@ public:
* kernel scene.
*/
bool is_traceable();
+
+ /* Combine object's visibility with all possible internal run-time
+ * determined flags which denotes trace-time visibility.
+ */
+ uint visibility_for_tracing() const;
};
/* Object Manager */
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 6bff29d1c76..5c5ac6e2be9 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -156,6 +156,7 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *s
og->surface_state.clear();
og->volume_state.clear();
og->displacement_state.clear();
+ og->bump_state.clear();
og->background_state.reset();
}
@@ -232,8 +233,10 @@ void OSLShaderManager::shading_system_init()
"glossy", /* PATH_RAY_GLOSSY */
"singular", /* PATH_RAY_SINGULAR */
"transparent", /* PATH_RAY_TRANSPARENT */
- "shadow", /* PATH_RAY_SHADOW_OPAQUE */
- "shadow", /* PATH_RAY_SHADOW_TRANSPARENT */
+ "shadow", /* PATH_RAY_SHADOW_OPAQUE_NON_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_OPAQUE_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_CATCHER */
"__unused__",
"__unused__",
@@ -718,6 +721,7 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
current_shader->has_surface_bssrdf = true;
current_shader->has_bssrdf_bump = true; /* can't detect yet */
}
+ current_shader->has_bump = true; /* can't detect yet */
}
if(node->has_spatial_varying()) {
@@ -1026,6 +1030,9 @@ void OSLCompiler::generate_nodes(const ShaderNodeSet& nodes)
if(node->has_bssrdf_bump())
current_shader->has_bssrdf_bump = true;
}
+ if(node->has_bump()) {
+ current_shader->has_bump = true;
+ }
}
else if(current_type == SHADER_TYPE_VOLUME) {
if(node->has_spatial_varying())
@@ -1088,21 +1095,14 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
ShaderGraph *graph = shader->graph;
ShaderNode *output = (graph)? graph->output(): NULL;
- /* copy graph for shader with bump mapping */
- if(output->input("Surface")->link && output->input("Displacement")->link)
- if(!shader->graph_bump)
- shader->graph_bump = shader->graph->copy();
+ bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
+ output->input("Surface")->link && output->input("Displacement")->link;
/* finalize */
shader->graph->finalize(scene,
- false,
- shader->has_integrator_dependency);
- if(shader->graph_bump) {
- shader->graph_bump->finalize(scene,
- true,
- shader->has_integrator_dependency,
- shader->displacement_method == DISPLACE_BOTH);
- }
+ has_bump,
+ shader->has_integrator_dependency,
+ shader->displacement_method == DISPLACE_BOTH);
current_shader = shader;
@@ -1110,7 +1110,8 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
shader->has_surface_emission = false;
shader->has_surface_transparent = false;
shader->has_surface_bssrdf = false;
- shader->has_bssrdf_bump = false;
+ shader->has_bump = has_bump;
+ shader->has_bssrdf_bump = has_bump;
shader->has_volume = false;
shader->has_displacement = false;
shader->has_surface_spatial_varying = false;
@@ -1122,8 +1123,8 @@ 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->displacement_method != DISPLACE_TRUE)
- shader->osl_surface_bump_ref = compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP);
+ if(has_bump)
+ shader->osl_surface_bump_ref = compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
else
shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 4db20338744..c59a5d97df5 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -148,8 +148,6 @@ void Scene::device_update(Device *device_, Progress& progress)
* - Film needs light manager to run for use_light_visibility
* - Lookup tables are done a second time to handle film tables
*/
-
- image_manager->set_pack_images(device->info.pack_images);
progress.set_status("Updating Shaders");
shader_manager->device_update(device, &dscene, this, progress);
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 4c2c4f5fcc3..0194327f567 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -121,13 +121,6 @@ public:
vector<device_vector<uchar>* > tex_byte_image;
vector<device_vector<half>* > tex_half_image;
- /* opencl images */
- device_vector<float4> tex_image_float4_packed;
- device_vector<uchar4> tex_image_byte4_packed;
- device_vector<float> tex_image_float_packed;
- device_vector<uchar> tex_image_byte_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 08909943c49..3798483aa9c 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -46,7 +46,7 @@ Session::Session(const SessionParams& params_)
: params(params_),
tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution,
params.background == false || params.progressive_refine, params.background, params.tile_order,
- max(params.device.multi_devices.size(), 1)),
+ max(params.device.multi_devices.size(), 1), params.pixel_size),
stats()
{
device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
@@ -721,7 +721,7 @@ DeviceRequestedFeatures Session::get_requested_device_features()
BakeManager *bake_manager = scene->bake_manager;
requested_features.use_baking = bake_manager->get_baking();
requested_features.use_integrator_branched = (scene->integrator->method == Integrator::BRANCHED_PATH);
- requested_features.use_transparent &= scene->integrator->transparent_shadows;
+ requested_features.use_denoising = params.use_denoising;
return requested_features;
}
@@ -960,6 +960,7 @@ void Session::update_status_time(bool show_pause, bool show_done)
}
else if(show_done) {
status = "Done";
+ progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
}
else {
status = substatus;
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 9f8bb8c42fa..980eda0876d 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -53,6 +53,7 @@ public:
int2 tile_size;
TileOrder tile_order;
int start_resolution;
+ int pixel_size;
int threads;
bool display_buffer_linear;
@@ -81,6 +82,7 @@ public:
samples = INT_MAX;
tile_size = make_int2(64, 64);
start_resolution = INT_MAX;
+ pixel_size = 1;
threads = 0;
use_denoising = false;
@@ -110,6 +112,7 @@ public:
&& experimental == params.experimental
&& tile_size == params.tile_size
&& start_resolution == params.start_resolution
+ && pixel_size == params.pixel_size
&& threads == params.threads
&& display_buffer_linear == params.display_buffer_linear
&& cancel_timeout == params.cancel_timeout
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 50400edd5ca..86378dfb495 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -177,7 +177,6 @@ Shader::Shader()
pass_id = 0;
graph = NULL;
- graph_bump = NULL;
has_surface = false;
has_surface_transparent = false;
@@ -185,11 +184,13 @@ Shader::Shader()
has_surface_bssrdf = false;
has_volume = false;
has_displacement = false;
+ has_bump = false;
has_bssrdf_bump = false;
has_surface_spatial_varying = false;
has_volume_spatial_varying = false;
has_object_dependency = false;
has_integrator_dependency = false;
+ has_volume_connected = false;
displacement_method = DISPLACE_BUMP;
@@ -203,7 +204,6 @@ Shader::Shader()
Shader::~Shader()
{
delete graph;
- delete graph_bump;
}
bool Shader::is_constant_emission(float3 *emission)
@@ -238,9 +238,7 @@ void Shader::set_graph(ShaderGraph *graph_)
/* assign graph */
delete graph;
- delete graph_bump;
graph = graph_;
- graph_bump = NULL;
/* Store info here before graph optimization to make sure that
* nodes that get optimized away still count. */
@@ -457,15 +455,11 @@ void ShaderManager::device_update_common(Device *device,
flag |= SD_VOLUME_MIS;
if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
flag |= SD_VOLUME_CUBIC;
- if(shader->graph_bump)
+ if(shader->has_bump)
flag |= SD_HAS_BUMP;
if(shader->displacement_method != DISPLACE_BUMP)
flag |= SD_HAS_DISPLACEMENT;
- /* shader with bump mapping */
- if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump)
- flag |= SD_HAS_BSSRDF_BUMP;
-
/* constant emission check */
float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
if(shader->is_constant_emission(&constant_emission))
@@ -502,9 +496,7 @@ void ShaderManager::device_update_common(Device *device,
KernelIntegrator *kintegrator = &dscene->data.integrator;
kintegrator->use_volumes = has_volumes;
/* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
- if(scene->integrator->transparent_shadows) {
- kintegrator->transparent_shadows = has_transparent_shadow;
- }
+ kintegrator->transparent_shadows = has_transparent_shadow;
}
void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
@@ -609,11 +601,6 @@ void ShaderManager::get_requested_features(Scene *scene,
Shader *shader = scene->shaders[i];
/* Gather requested features from all the nodes from the graph nodes. */
get_requested_graph_features(shader->graph, requested_features);
- /* Gather requested features from the graph itself. */
- if(shader->graph_bump) {
- get_requested_graph_features(shader->graph_bump,
- requested_features);
- }
ShaderNode *output_node = shader->graph->output();
if(output_node->input("Displacement")->link != NULL) {
requested_features->nodes_features |= NODE_FEATURE_BUMP;
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index b6714b13247..79a67d6756a 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -89,11 +89,6 @@ public:
/* shader graph */
ShaderGraph *graph;
- /* shader graph with auto bump mapping included, we compile two shaders,
- * with and without bump, because the displacement method is a mesh
- * level setting, so we need to handle both */
- ShaderGraph *graph_bump;
-
/* sampling */
bool use_mis;
bool use_transparent_shadow;
@@ -121,6 +116,7 @@ public:
bool has_volume;
bool has_displacement;
bool has_surface_bssrdf;
+ bool has_bump;
bool has_bssrdf_bump;
bool has_surface_spatial_varying;
bool has_volume_spatial_varying;
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 48287d872d4..32f89897970 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -521,6 +521,9 @@ void SVMCompiler::generate_closure_node(ShaderNode *node,
if(node->has_bssrdf_bump())
current_shader->has_bssrdf_bump = true;
}
+ if(node->has_bump()) {
+ current_shader->has_bump = true;
+ }
}
}
@@ -799,29 +802,21 @@ void SVMCompiler::compile(Scene *scene,
Summary *summary)
{
/* copy graph for shader with bump mapping */
- ShaderNode *node = shader->graph->output();
+ ShaderNode *output = shader->graph->output();
int start_num_svm_nodes = svm_nodes.size();
const double time_start = time_dt();
- if(node->input("Surface")->link && node->input("Displacement")->link)
- if(!shader->graph_bump)
- shader->graph_bump = shader->graph->copy();
+ bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
+ output->input("Surface")->link && output->input("Displacement")->link;
/* finalize */
{
scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
shader->graph->finalize(scene,
- false,
- shader->has_integrator_dependency);
- }
-
- if(shader->graph_bump) {
- scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL);
- shader->graph_bump->finalize(scene,
- true,
- shader->has_integrator_dependency,
- shader->displacement_method == DISPLACE_BOTH);
+ has_bump,
+ shader->has_integrator_dependency,
+ shader->displacement_method == DISPLACE_BOTH);
}
current_shader = shader;
@@ -830,7 +825,8 @@ void SVMCompiler::compile(Scene *scene,
shader->has_surface_emission = false;
shader->has_surface_transparent = false;
shader->has_surface_bssrdf = false;
- shader->has_bssrdf_bump = false;
+ shader->has_bump = has_bump;
+ shader->has_bssrdf_bump = has_bump;
shader->has_volume = false;
shader->has_displacement = false;
shader->has_surface_spatial_varying = false;
@@ -839,9 +835,9 @@ void SVMCompiler::compile(Scene *scene,
shader->has_integrator_dependency = false;
/* generate bump shader */
- if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump) {
+ if(has_bump) {
scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
- compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP);
+ compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
svm_nodes[index].y = svm_nodes.size();
svm_nodes.insert(svm_nodes.end(),
current_svm_nodes.begin(),
@@ -853,7 +849,7 @@ void SVMCompiler::compile(Scene *scene,
scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL);
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
/* 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) {
+ if(!has_bump) {
svm_nodes[index].y = svm_nodes.size();
}
svm_nodes.insert(svm_nodes.end(),
@@ -895,7 +891,6 @@ SVMCompiler::Summary::Summary()
: num_svm_nodes(0),
peak_stack_usage(0),
time_finalize(0.0),
- time_finalize_bump(0.0),
time_generate_surface(0.0),
time_generate_bump(0.0),
time_generate_volume(0.0),
@@ -911,10 +906,7 @@ string SVMCompiler::Summary::full_report() const
report += string_printf("Peak stack usage: %d\n", peak_stack_usage);
report += string_printf("Time (in seconds):\n");
- report += string_printf(" Finalize: %f\n", time_finalize);
- report += string_printf(" Bump finalize: %f\n", time_finalize_bump);
- report += string_printf("Finalize: %f\n", time_finalize +
- time_finalize_bump);
+ report += string_printf("Finalize: %f\n", time_finalize);
report += string_printf(" Surface: %f\n", time_generate_surface);
report += string_printf(" Bump: %f\n", time_generate_bump);
report += string_printf(" Volume: %f\n", time_generate_volume);
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index abbd9e50610..98ef5fa05d8 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -74,9 +74,6 @@ public:
/* Time spent on surface graph finalization. */
double time_finalize;
- /* Time spent on bump graph finalization. */
- double time_finalize_bump;
-
/* Time spent on generating SVM nodes for surface shader. */
double time_generate_surface;
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index 176a1f4f0f3..a9620f79fa0 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -88,12 +88,14 @@ enum SpiralDirection {
} /* namespace */
TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
- bool preserve_tile_device_, bool background_, TileOrder tile_order_, int num_devices_)
+ bool preserve_tile_device_, bool background_, TileOrder tile_order_,
+ int num_devices_, int pixel_size_)
{
progressive = progressive_;
tile_size = tile_size_;
tile_order = tile_order_;
start_resolution = start_resolution_;
+ pixel_size = pixel_size_;
num_samples = num_samples_;
num_devices = num_devices_;
preserve_tile_device = preserve_tile_device_;
@@ -163,15 +165,17 @@ void TileManager::set_samples(int num_samples_)
uint64_t pixel_samples = 0;
/* While rendering in the viewport, the initial preview resolution is increased to the native resolution
* before the actual rendering begins. Therefore, additional pixel samples will be rendered. */
- int divider = get_divider(params.width, params.height, start_resolution) / 2;
- while(divider > 1) {
+ int divider = max(get_divider(params.width, params.height, start_resolution) / 2, pixel_size);
+ while(divider > pixel_size) {
int image_w = max(1, params.width/divider);
int image_h = max(1, params.height/divider);
pixel_samples += image_w * image_h;
divider >>= 1;
}
- state.total_pixel_samples = pixel_samples + (uint64_t)get_num_effective_samples() * params.width*params.height;
+ int image_w = max(1, params.width/divider);
+ int image_h = max(1, params.height/divider);
+ state.total_pixel_samples = pixel_samples + (uint64_t)get_num_effective_samples() * image_w*image_h;
if(schedule_denoising) {
state.total_pixel_samples += params.width*params.height;
}
@@ -471,7 +475,7 @@ bool TileManager::done()
int end_sample = (range_num_samples == -1)
? num_samples
: range_start_sample + range_num_samples;
- return (state.resolution_divider == 1) &&
+ return (state.resolution_divider == pixel_size) &&
(state.sample+state.num_samples >= end_sample);
}
@@ -480,9 +484,9 @@ bool TileManager::next()
if(done())
return false;
- if(progressive && state.resolution_divider > 1) {
+ if(progressive && state.resolution_divider > pixel_size) {
state.sample = 0;
- state.resolution_divider /= 2;
+ state.resolution_divider = max(state.resolution_divider/2, pixel_size);
state.num_samples = 1;
set_tiles();
}
@@ -496,7 +500,7 @@ bool TileManager::next()
else
state.num_samples = range_num_samples;
- state.resolution_divider = 1;
+ state.resolution_divider = pixel_size;
set_tiles();
}
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index e39a8f0627a..4cd57b7b30c 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -88,7 +88,7 @@ public:
int num_samples;
TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution,
- bool preserve_tile_device, bool background, TileOrder tile_order, int num_devices = 1);
+ bool preserve_tile_device, bool background, TileOrder tile_order, int num_devices = 1, int pixel_size = 1);
~TileManager();
void free_device();
@@ -122,6 +122,7 @@ protected:
int2 tile_size;
TileOrder tile_order;
int start_resolution;
+ int pixel_size;
int num_devices;
/* in some cases it is important that the same tile will be returned for the same
diff --git a/intern/cycles/test/util_string_test.cpp b/intern/cycles/test/util_string_test.cpp
index 22ec8e0ee8e..6c059ba5d12 100644
--- a/intern/cycles/test/util_string_test.cpp
+++ b/intern/cycles/test/util_string_test.cpp
@@ -245,4 +245,41 @@ TEST(util_string_remove_trademark, both)
EXPECT_EQ(str, "foo bar zzz");
}
+TEST(util_string_remove_trademark, both_space)
+{
+ string str = string_remove_trademark("foo bar(TM) (R) zzz");
+ EXPECT_EQ(str, "foo bar zzz");
+}
+
+TEST(util_string_remove_trademark, both_space_around)
+{
+ string str = string_remove_trademark("foo bar (TM) (R) zzz");
+ EXPECT_EQ(str, "foo bar zzz");
+}
+
+TEST(util_string_remove_trademark, trademark_space_suffix)
+{
+ string str = string_remove_trademark("foo bar (TM)");
+ EXPECT_EQ(str, "foo bar");
+}
+
+TEST(util_string_remove_trademark, trademark_space_middle)
+{
+ string str = string_remove_trademark("foo bar (TM) baz");
+ EXPECT_EQ(str, "foo bar baz");
+}
+
+
+TEST(util_string_remove_trademark, r_space_suffix)
+{
+ string str = string_remove_trademark("foo bar (R)");
+ EXPECT_EQ(str, "foo bar");
+}
+
+TEST(util_string_remove_trademark, r_space_middle)
+{
+ string str = string_remove_trademark("foo bar (R) baz");
+ EXPECT_EQ(str, "foo bar baz");
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index 43f9a57d099..7f3747a0f58 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -38,6 +38,7 @@ set(SRC_HEADERS
util_atomic.h
util_boundbox.h
util_debug.h
+ util_defines.h
util_guarded_allocator.cpp
util_foreach.h
util_function.h
diff --git a/intern/cycles/util/util_atomic.h b/intern/cycles/util/util_atomic.h
index 6c52117ef9a..f3c7ae546a0 100644
--- a/intern/cycles/util/util_atomic.h
+++ b/intern/cycles/util/util_atomic.h
@@ -22,19 +22,10 @@
/* Using atomic ops header from Blender. */
#include "atomic_ops.h"
-ATOMIC_INLINE void atomic_update_max_z(size_t *maximum_value, size_t value)
-{
- size_t prev_value = *maximum_value;
- while(prev_value < value) {
- if(atomic_cas_z(maximum_value, prev_value, value) != prev_value) {
- break;
- }
- }
-}
-
#define atomic_add_and_fetch_float(p, x) atomic_add_and_fetch_fl((p), (x))
#define atomic_fetch_and_inc_uint32(p) atomic_fetch_and_add_uint32((p), 1)
+#define atomic_fetch_and_dec_uint32(p) atomic_fetch_and_add_uint32((p), -1)
#define CCL_LOCAL_MEM_FENCE 0
#define ccl_barrier(flags) (void)0
@@ -68,6 +59,7 @@ ccl_device_inline float atomic_add_and_fetch_float(volatile ccl_global float *so
#define atomic_fetch_and_add_uint32(p, x) atomic_add((p), (x))
#define atomic_fetch_and_inc_uint32(p) atomic_inc((p))
+#define atomic_fetch_and_dec_uint32(p) atomic_dec((p))
#define CCL_LOCAL_MEM_FENCE CLK_LOCAL_MEM_FENCE
#define ccl_barrier(flags) barrier(flags)
@@ -79,7 +71,9 @@ ccl_device_inline float atomic_add_and_fetch_float(volatile ccl_global float *so
#define atomic_add_and_fetch_float(p, x) (atomicAdd((float*)(p), (float)(x)) + (float)(x))
#define atomic_fetch_and_add_uint32(p, x) atomicAdd((unsigned int*)(p), (unsigned int)(x))
+#define atomic_fetch_and_sub_uint32(p, x) atomicSub((unsigned int*)(p), (unsigned int)(x))
#define atomic_fetch_and_inc_uint32(p) atomic_fetch_and_add_uint32((p), 1)
+#define atomic_fetch_and_dec_uint32(p) atomic_fetch_and_sub_uint32((p), 1)
#define CCL_LOCAL_MEM_FENCE
#define ccl_barrier(flags) __syncthreads()
diff --git a/intern/cycles/util/util_debug.cpp b/intern/cycles/util/util_debug.cpp
index ab038d2b9fb..eb078d69252 100644
--- a/intern/cycles/util/util_debug.cpp
+++ b/intern/cycles/util/util_debug.cpp
@@ -122,13 +122,16 @@ void DebugFlags::OpenCL::reset()
}
DebugFlags::DebugFlags()
+: viewport_static_bvh(false)
{
/* Nothing for now. */
}
void DebugFlags::reset()
{
+ viewport_static_bvh = false;
cpu.reset();
+ cuda.reset();
opencl.reset();
}
@@ -184,8 +187,8 @@ std::ostream& operator <<(std::ostream &os,
<< " Device type : " << opencl_device_type << "\n"
<< " Kernel type : " << opencl_kernel_type << "\n"
<< " Debug : " << string_from_bool(debug_flags.opencl.debug) << "\n"
- << " Single program : " << string_from_bool(debug_flags.opencl.single_program)
- << "\n";
+ << " Single program : " << string_from_bool(debug_flags.opencl.single_program) << "\n"
+ << " Memory limit : " << string_human_readable_size(debug_flags.opencl.mem_limit) << "\n";
return os;
}
diff --git a/intern/cycles/util/util_debug.h b/intern/cycles/util/util_debug.h
index 4505d584490..9255279c5ab 100644
--- a/intern/cycles/util/util_debug.h
+++ b/intern/cycles/util/util_debug.h
@@ -30,6 +30,9 @@ CCL_NAMESPACE_BEGIN
*/
class DebugFlags {
public:
+ /* Use static BVH in viewport, to match final render exactly. */
+ bool viewport_static_bvh;
+
/* Descriptor of CPU feature-set to be used. */
struct CPU {
CPU();
@@ -115,6 +118,10 @@ public:
/* Use single program */
bool single_program;
+
+ /* TODO(mai): Currently this is only for OpenCL, but we should have it implemented for all devices. */
+ /* Artificial memory limit in bytes (0 if disabled). */
+ size_t mem_limit;
};
/* Get instance of debug flags registry. */
diff --git a/intern/cycles/util/util_defines.h b/intern/cycles/util/util_defines.h
new file mode 100644
index 00000000000..ae654092c87
--- /dev/null
+++ b/intern/cycles/util/util_defines.h
@@ -0,0 +1,135 @@
+
+/*
+ * Copyright 2011-2017 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_DEFINES_H__
+#define __UTIL_DEFINES_H__
+
+/* Bitness */
+
+#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
+# define __KERNEL_64_BIT__
+#endif
+
+/* Qualifiers for kernel code shared by CPU and GPU */
+
+#ifndef __KERNEL_GPU__
+# define ccl_device static inline
+# define ccl_device_noinline static
+# define ccl_global
+# define ccl_constant
+# define ccl_local
+# define ccl_local_param
+# define ccl_private
+# define ccl_restrict __restrict
+# define ccl_ref &
+# define __KERNEL_WITH_SSE_ALIGN__
+
+# if defined(_WIN32) && !defined(FREE_WINDOWS)
+# define ccl_device_inline static __forceinline
+# define ccl_device_forceinline static __forceinline
+# define ccl_align(...) __declspec(align(__VA_ARGS__))
+# ifdef __KERNEL_64_BIT__
+# define ccl_try_align(...) __declspec(align(__VA_ARGS__))
+# else /* __KERNEL_64_BIT__ */
+# undef __KERNEL_WITH_SSE_ALIGN__
+/* No support for function arguments (error C2719). */
+# define ccl_try_align(...)
+# endif /* __KERNEL_64_BIT__ */
+# define ccl_may_alias
+# define ccl_always_inline __forceinline
+# define ccl_never_inline __declspec(noinline)
+# define ccl_maybe_unused
+# else /* _WIN32 && !FREE_WINDOWS */
+# define ccl_device_inline static inline __attribute__((always_inline))
+# define ccl_device_forceinline static inline __attribute__((always_inline))
+# define ccl_align(...) __attribute__((aligned(__VA_ARGS__)))
+# ifndef FREE_WINDOWS64
+# define __forceinline inline __attribute__((always_inline))
+# endif
+# define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
+# define ccl_may_alias __attribute__((__may_alias__))
+# define ccl_always_inline __attribute__((always_inline))
+# define ccl_never_inline __attribute__((noinline))
+# define ccl_maybe_unused __attribute__((used))
+# endif /* _WIN32 && !FREE_WINDOWS */
+
+/* Use to suppress '-Wimplicit-fallthrough' (in place of 'break'). */
+# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */
+# define ATTR_FALLTHROUGH __attribute__((fallthrough))
+# else
+# define ATTR_FALLTHROUGH ((void)0)
+# endif
+#endif /* __KERNEL_GPU__ */
+
+/* macros */
+
+/* hints for branch prediction, only use in code that runs a _lot_ */
+#if defined(__GNUC__) && defined(__KERNEL_CPU__)
+# define LIKELY(x) __builtin_expect(!!(x), 1)
+# define UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+# define LIKELY(x) (x)
+# define UNLIKELY(x) (x)
+#endif
+
+#if defined(__cplusplus) && ((__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800))
+# define HAS_CPP11_FEATURES
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# if defined(HAS_CPP11_FEATURES)
+/* Some magic to be sure we don't have reference in the type. */
+template<typename T> static inline T decltype_helper(T x) { return x; }
+# define TYPEOF(x) decltype(decltype_helper(x))
+# else
+# define TYPEOF(x) typeof(x)
+# endif
+#endif
+
+/* Causes warning:
+ * incompatible types when assigning to type 'Foo' from type 'Bar'
+ * ... the compiler optimizes away the temp var */
+#ifdef __GNUC__
+#define CHECK_TYPE(var, type) { \
+ TYPEOF(var) *__tmp; \
+ __tmp = (type *)NULL; \
+ (void)__tmp; \
+} (void)0
+
+#define CHECK_TYPE_PAIR(var_a, var_b) { \
+ TYPEOF(var_a) *__tmp; \
+ __tmp = (typeof(var_b) *)NULL; \
+ (void)__tmp; \
+} (void)0
+#else
+# define CHECK_TYPE(var, type)
+# define CHECK_TYPE_PAIR(var_a, var_b)
+#endif
+
+/* can be used in simple macros */
+#define CHECK_TYPE_INLINE(val, type) \
+ ((void)(((type)0) != (val)))
+
+#ifndef __KERNEL_GPU__
+# include <cassert>
+# define util_assert(statement) assert(statement)
+#else
+# define util_assert(statement)
+#endif
+
+#endif /* __UTIL_DEFINES_H__ */
+
diff --git a/intern/cycles/util/util_logging.h b/intern/cycles/util/util_logging.h
index ecf9c9cfee0..492f830e67c 100644
--- a/intern/cycles/util/util_logging.h
+++ b/intern/cycles/util/util_logging.h
@@ -19,28 +19,30 @@
#if defined(WITH_CYCLES_LOGGING) && !defined(__KERNEL_GPU__)
# include <glog/logging.h>
-#else
-# include <iostream>
#endif
+#include <iostream>
+
CCL_NAMESPACE_BEGIN
#if !defined(WITH_CYCLES_LOGGING) || defined(__KERNEL_GPU__)
-class StubStream : public std::ostream {
- public:
- StubStream() : std::ostream(NULL) { }
+class StubStream {
+public:
+ template<class T>
+ StubStream& operator<<(const T&) {
+ return *this;
+ }
};
class LogMessageVoidify {
public:
LogMessageVoidify() { }
- void operator&(::std::ostream&) { }
+ void operator&(StubStream&) { }
};
# define LOG_SUPPRESS() (true) ? (void) 0 : LogMessageVoidify() & StubStream()
# define LOG(severity) LOG_SUPPRESS()
# define VLOG(severity) LOG_SUPPRESS()
-
#endif
#define VLOG_ONCE(level, flag) if(!flag) flag = true, VLOG(level)
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index b719640b19c..fb04d49bcd9 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -94,6 +94,7 @@ ccl_device_inline float fminf(float a, float b)
#ifndef __KERNEL_GPU__
using std::isfinite;
using std::isnan;
+using std::sqrt;
ccl_device_inline int abs(int x)
{
@@ -223,7 +224,7 @@ ccl_device_inline bool isfinite_safe(float f)
{
/* By IEEE 754 rule, 2*Inf equals Inf */
unsigned int x = __float_as_uint(f);
- return (f == f) && (x == 0 || (f != 2.0f*f)) && !((x << 1) > 0xff000000u);
+ return (f == f) && (x == 0 || x == (1u << 31) || (f != 2.0f*f)) && !((x << 1) > 0xff000000u);
}
ccl_device_inline float ensure_finite(float v)
@@ -329,15 +330,22 @@ template<class A, class B> A lerp(const A& a, const A& b, const B& t)
return (A)(a * ((B)1 - t) + b * t);
}
+#endif /* __KERNEL_OPENCL__ */
+
/* Triangle */
+#ifndef __KERNEL_OPENCL__
ccl_device_inline float triangle_area(const float3& v1,
const float3& v2,
const float3& v3)
+#else
+ccl_device_inline float triangle_area(const float3 v1,
+ const float3 v2,
+ const float3 v3)
+#endif
{
return len(cross(v3 - v2, v1 - v2))*0.5f;
}
-#endif /* __KERNEL_OPENCL__ */
/* Orthonormal vectors */
diff --git a/intern/cycles/util/util_math_float3.h b/intern/cycles/util/util_math_float3.h
index 5327d9f7cc6..e73e5bc17a2 100644
--- a/intern/cycles/util/util_math_float3.h
+++ b/intern/cycles/util/util_math_float3.h
@@ -108,8 +108,7 @@ ccl_device_inline float3 operator*(const float3& a, const float f)
ccl_device_inline float3 operator*(const float f, const float3& a)
{
- /* TODO(sergey): Currently disabled, gives speedup but causes precision issues. */
-#if defined(__KERNEL_SSE__) && 0
+#if defined(__KERNEL_SSE__)
return float3(_mm_mul_ps(_mm_set1_ps(f), a.m128));
#else
return make_float3(a.x*f, a.y*f, a.z*f);
@@ -118,10 +117,8 @@ ccl_device_inline float3 operator*(const float f, const float3& a)
ccl_device_inline float3 operator/(const float f, const float3& a)
{
- /* TODO(sergey): Currently disabled, gives speedup but causes precision issues. */
-#if defined(__KERNEL_SSE__) && 0
- __m128 rc = _mm_rcp_ps(a.m128);
- return float3(_mm_mul_ps(_mm_set1_ps(f),rc));
+#if defined(__KERNEL_SSE__)
+ return float3(_mm_div_ps(_mm_set1_ps(f), a.m128));
#else
return make_float3(f / a.x, f / a.y, f / a.z);
#endif
@@ -135,10 +132,8 @@ ccl_device_inline float3 operator/(const float3& a, const float f)
ccl_device_inline float3 operator/(const float3& a, const float3& b)
{
- /* TODO(sergey): Currently disabled, gives speedup but causes precision issues. */
-#if defined(__KERNEL_SSE__) && 0
- __m128 rc = _mm_rcp_ps(b.m128);
- return float3(_mm_mul_ps(a, rc));
+#if defined(__KERNEL_SSE__)
+ return float3(_mm_div_ps(a.m128, b.m128));
#else
return make_float3(a.x / b.x, a.y / b.y, a.z / b.z);
#endif
@@ -282,9 +277,8 @@ ccl_device_inline float3 mix(const float3& a, const float3& b, float t)
ccl_device_inline float3 rcp(const float3& a)
{
#ifdef __KERNEL_SSE__
- const float4 r(_mm_rcp_ps(a.m128));
- return float3(_mm_sub_ps(_mm_add_ps(r, r),
- _mm_mul_ps(_mm_mul_ps(r, r), a)));
+ /* Don't use _mm_rcp_ps due to poor precision. */
+ return float3(_mm_div_ps(_mm_set_ps1(1.0f), a.m128));
#else
return make_float3(1.0f/a.x, 1.0f/a.y, 1.0f/a.z);
#endif
@@ -374,9 +368,9 @@ ccl_device_inline bool isfinite3_safe(float3 v)
ccl_device_inline float3 ensure_finite3(float3 v)
{
- if(!isfinite_safe(v.x)) v.x = 0.0;
- if(!isfinite_safe(v.y)) v.y = 0.0;
- if(!isfinite_safe(v.z)) v.z = 0.0;
+ if(!isfinite_safe(v.x)) v.x = 0.0f;
+ if(!isfinite_safe(v.y)) v.y = 0.0f;
+ if(!isfinite_safe(v.z)) v.z = 0.0f;
return v;
}
diff --git a/intern/cycles/util/util_math_float4.h b/intern/cycles/util/util_math_float4.h
index d89121b3a1d..aa7e56fefe9 100644
--- a/intern/cycles/util/util_math_float4.h
+++ b/intern/cycles/util/util_math_float4.h
@@ -48,23 +48,30 @@ ccl_device_inline bool operator==(const float4& a, const float4& b);
ccl_device_inline float dot(const float4& a, const float4& b);
ccl_device_inline float len_squared(const float4& a);
ccl_device_inline float4 rcp(const float4& a);
+ccl_device_inline float4 sqrt(const float4& a);
+ccl_device_inline float4 sqr(const float4& a);
ccl_device_inline float4 cross(const float4& a, const float4& b);
ccl_device_inline bool is_zero(const float4& a);
-ccl_device_inline float reduce_add(const float4& a);
ccl_device_inline float average(const float4& a);
ccl_device_inline float len(const float4& a);
ccl_device_inline float4 normalize(const float4& a);
ccl_device_inline float4 safe_normalize(const float4& a);
ccl_device_inline float4 min(const float4& a, const float4& b);
ccl_device_inline float4 max(const float4& a, const float4& b);
+ccl_device_inline float4 fabs(const float4& a);
#endif /* !__KERNEL_OPENCL__*/
#ifdef __KERNEL_SSE__
template<size_t index_0, size_t index_1, size_t index_2, size_t index_3>
__forceinline const float4 shuffle(const float4& b);
+template<size_t index_0, size_t index_1, size_t index_2, size_t index_3>
+__forceinline const float4 shuffle(const float4& a, const float4& b);
template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b);
+template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& a, const float4& b);
+template<> __forceinline const float4 shuffle<2, 3, 2, 3>(const float4& a, const float4& b);
+
# ifdef __KERNEL_SSE3__
template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b);
template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4& b);
@@ -77,9 +84,7 @@ ccl_device_inline float4 select(const int4& mask,
const float4& b);
ccl_device_inline float4 reduce_min(const float4& a);
ccl_device_inline float4 reduce_max(const float4& a);
-# if 0
ccl_device_inline float4 reduce_add(const float4& a);
-# endif
#endif /* !__KERNEL_GPU__ */
/*******************************************************************************
@@ -128,7 +133,7 @@ ccl_device_inline float4 operator/(const float4& a, float f)
ccl_device_inline float4 operator/(const float4& a, const float4& b)
{
#ifdef __KERNEL_SSE__
- return a * rcp(b);
+ return float4(_mm_div_ps(a.m128, b.m128));
#else
return make_float4(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w);
#endif
@@ -171,8 +176,7 @@ ccl_device_inline float4 operator/=(float4& a, float f)
ccl_device_inline int4 operator<(const float4& a, const float4& b)
{
#ifdef __KERNEL_SSE__
- /* TODO(sergey): avoid cvt. */
- return int4(_mm_cvtps_epi32(_mm_cmplt_ps(a.m128, b.m128)));
+ return int4(_mm_castps_si128(_mm_cmplt_ps(a.m128, b.m128)));
#else
return make_int4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w);
#endif
@@ -181,8 +185,7 @@ ccl_device_inline int4 operator<(const float4& a, const float4& b)
ccl_device_inline int4 operator>=(const float4& a, const float4& b)
{
#ifdef __KERNEL_SSE__
- /* TODO(sergey): avoid cvt. */
- return int4(_mm_cvtps_epi32(_mm_cmpge_ps(a.m128, b.m128)));
+ return int4(_mm_castps_si128(_mm_cmpge_ps(a.m128, b.m128)));
#else
return make_int4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w);
#endif
@@ -191,8 +194,7 @@ ccl_device_inline int4 operator>=(const float4& a, const float4& b)
ccl_device_inline int4 operator<=(const float4& a, const float4& b)
{
#ifdef __KERNEL_SSE__
- /* TODO(sergey): avoid cvt. */
- return int4(_mm_cvtps_epi32(_mm_cmple_ps(a.m128, b.m128)));
+ return int4(_mm_castps_si128(_mm_cmple_ps(a.m128, b.m128)));
#else
return make_int4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w);
#endif
@@ -224,14 +226,30 @@ ccl_device_inline float len_squared(const float4& a)
ccl_device_inline float4 rcp(const float4& a)
{
#ifdef __KERNEL_SSE__
- float4 r(_mm_rcp_ps(a.m128));
- return float4(_mm_sub_ps(_mm_add_ps(r, r),
- _mm_mul_ps(_mm_mul_ps(r, r), a)));
+ /* Don't use _mm_rcp_ps due to poor precision. */
+ return float4(_mm_div_ps(_mm_set_ps1(1.0f), a.m128));
#else
return make_float4(1.0f/a.x, 1.0f/a.y, 1.0f/a.z, 1.0f/a.w);
#endif
}
+ccl_device_inline float4 sqrt(const float4& a)
+{
+#ifdef __KERNEL_SSE__
+ return float4(_mm_sqrt_ps(a.m128));
+#else
+ return make_float4(sqrtf(a.x),
+ sqrtf(a.y),
+ sqrtf(a.z),
+ sqrtf(a.w));
+#endif
+}
+
+ccl_device_inline float4 sqr(const float4& a)
+{
+ return a * a;
+}
+
ccl_device_inline float4 cross(const float4& a, const float4& b)
{
#ifdef __KERNEL_SSE__
@@ -254,20 +272,25 @@ ccl_device_inline bool is_zero(const float4& a)
#endif
}
-ccl_device_inline float reduce_add(const float4& a)
+ccl_device_inline float4 reduce_add(const float4& a)
{
#ifdef __KERNEL_SSE__
+# ifdef __KERNEL_SSE3__
+ float4 h(_mm_hadd_ps(a.m128, a.m128));
+ return float4( _mm_hadd_ps(h.m128, h.m128));
+# else
float4 h(shuffle<1,0,3,2>(a) + a);
- /* TODO(sergey): Investigate efficiency. */
- return _mm_cvtss_f32(shuffle<2,3,0,1>(h) + h);
+ return shuffle<2,3,0,1>(h) + h;
+# endif
#else
- return ((a.x + a.y) + (a.z + a.w));
+ float sum = (a.x + a.y) + (a.z + a.w);
+ return make_float4(sum, sum, sum, sum);
#endif
}
ccl_device_inline float average(const float4& a)
{
- return reduce_add(a) * 0.25f;
+ return reduce_add(a).x * 0.25f;
}
ccl_device_inline float len(const float4& a)
@@ -309,6 +332,18 @@ ccl_device_inline float4 max(const float4& a, const float4& b)
max(a.w, b.w));
#endif
}
+
+ccl_device_inline float4 fabs(const float4& a)
+{
+#ifdef __KERNEL_SSE__
+ return float4(_mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))));
+#else
+ return make_float4(fabsf(a.x),
+ fabsf(a.y),
+ fabsf(a.z),
+ fabsf(a.w));
+#endif
+}
#endif /* !__KERNEL_OPENCL__*/
#ifdef __KERNEL_SSE__
@@ -320,11 +355,28 @@ __forceinline const float4 shuffle(const float4& b)
_MM_SHUFFLE(index_3, index_2, index_1, index_0))));
}
+template<size_t index_0, size_t index_1, size_t index_2, size_t index_3>
+__forceinline const float4 shuffle(const float4& a, const float4& b)
+{
+ return float4(_mm_shuffle_ps(a.m128, b.m128,
+ _MM_SHUFFLE(index_3, index_2, index_1, index_0)));
+}
+
template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b)
{
return float4(_mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b))));
}
+template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& a, const float4& b)
+{
+ return float4(_mm_movelh_ps(a.m128, b.m128));
+}
+
+template<> __forceinline const float4 shuffle<2, 3, 2, 3>(const float4& a, const float4& b)
+{
+ return float4(_mm_movehl_ps(b.m128, a.m128));
+}
+
# ifdef __KERNEL_SSE3__
template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b)
{
@@ -344,9 +396,7 @@ ccl_device_inline float4 select(const int4& mask,
const float4& b)
{
#ifdef __KERNEL_SSE__
- /* TODO(sergey): avoid cvt. */
- return float4(_mm_or_ps(_mm_and_ps(_mm_cvtepi32_ps(mask), a),
- _mm_andnot_ps(_mm_cvtepi32_ps(mask), b)));
+ return float4(_mm_blendv_ps(b.m128, a.m128, _mm_castsi128_ps(mask.m128)));
#else
return make_float4((mask.x)? a.x: b.x,
(mask.y)? a.y: b.y,
@@ -355,6 +405,13 @@ ccl_device_inline float4 select(const int4& mask,
#endif
}
+ccl_device_inline float4 mask(const int4& mask,
+ const float4& a)
+{
+ /* Replace elements of x with zero where mask isn't set. */
+ return select(mask, a, make_float4(0.0f));
+}
+
ccl_device_inline float4 reduce_min(const float4& a)
{
#ifdef __KERNEL_SSE__
@@ -375,17 +432,15 @@ ccl_device_inline float4 reduce_max(const float4& a)
#endif
}
-#if 0
-ccl_device_inline float4 reduce_add(const float4& a)
+ccl_device_inline float4 load_float4(const float *v)
{
#ifdef __KERNEL_SSE__
- float4 h = shuffle<1,0,3,2>(a) + a;
- return shuffle<2,3,0,1>(h) + h;
+ return float4(_mm_loadu_ps(v));
#else
- return make_float4((a.x + a.y) + (a.z + a.w));
+ return make_float4(v[0], v[1], v[2], v[3]);
#endif
}
-#endif
+
#endif /* !__KERNEL_GPU__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_math_matrix.h b/intern/cycles/util/util_math_matrix.h
index c7511f8306e..b31dbe4fc67 100644
--- a/intern/cycles/util/util_math_matrix.h
+++ b/intern/cycles/util/util_math_matrix.h
@@ -223,20 +223,20 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
{
const float singular_epsilon = 1e-9f;
- for (int row = 0; row < n; row++) {
- for (int col = 0; col < n; col++) {
+ for(int row = 0; row < n; row++) {
+ for(int col = 0; col < n; col++) {
MATS(V, n, row, col, v_stride) = (col == row) ? 1.0f : 0.0f;
}
}
- for (int sweep = 0; sweep < 8; sweep++) {
+ for(int sweep = 0; sweep < 8; sweep++) {
float off_diagonal = 0.0f;
- for (int row = 1; row < n; row++) {
- for (int col = 0; col < row; col++) {
+ for(int row = 1; row < n; row++) {
+ for(int col = 0; col < row; col++) {
off_diagonal += fabsf(MAT(A, n, row, col));
}
}
- if (off_diagonal < 1e-7f) {
+ if(off_diagonal < 1e-7f) {
/* The matrix has nearly reached diagonal form.
* Since the eigenvalues are only used to determine truncation, their exact values aren't required - a relative error of a few ULPs won't matter at all. */
break;
@@ -253,7 +253,7 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
float abs_element = fabsf(element);
/* If we're in a later sweep and the element already is very small, just set it to zero and skip the rotation. */
- if (sweep > 3 && abs_element <= singular_epsilon*fabsf(MAT(A, n, row, row)) && abs_element <= singular_epsilon*fabsf(MAT(A, n, col, col))) {
+ if(sweep > 3 && abs_element <= singular_epsilon*fabsf(MAT(A, n, row, row)) && abs_element <= singular_epsilon*fabsf(MAT(A, n, col, col))) {
MAT(A, n, row, col) = 0.0f;
continue;
}
@@ -272,10 +272,10 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
* Then, we compute sin(phi) and cos(phi) themselves. */
float singular_diff = MAT(A, n, row, row) - MAT(A, n, col, col);
float ratio;
- if (abs_element > singular_epsilon*fabsf(singular_diff)) {
+ if(abs_element > singular_epsilon*fabsf(singular_diff)) {
float cot_2phi = 0.5f*singular_diff / element;
ratio = 1.0f / (fabsf(cot_2phi) + sqrtf(1.0f + cot_2phi*cot_2phi));
- if (cot_2phi < 0.0f) ratio = -ratio; /* Copy sign. */
+ if(cot_2phi < 0.0f) ratio = -ratio; /* Copy sign. */
}
else {
ratio = element / singular_diff;
@@ -315,21 +315,21 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
}
/* Sort eigenvalues and the associated eigenvectors. */
- for (int i = 0; i < n - 1; i++) {
+ for(int i = 0; i < n - 1; i++) {
float v = MAT(A, n, i, i);
int k = i;
- for (int j = i; j < n; j++) {
- if (MAT(A, n, j, j) >= v) {
+ for(int j = i; j < n; j++) {
+ if(MAT(A, n, j, j) >= v) {
v = MAT(A, n, j, j);
k = j;
}
}
- if (k != i) {
+ if(k != i) {
/* Swap eigenvalues. */
MAT(A, n, k, k) = MAT(A, n, i, i);
MAT(A, n, i, i) = v;
/* Swap eigenvectors. */
- for (int j = 0; j < n; j++) {
+ for(int j = 0; j < n; j++) {
float v = MATS(V, n, i, j, v_stride);
MATS(V, n, i, j, v_stride) = MATS(V, n, k, j, v_stride);
MATS(V, n, k, j, v_stride) = v;
@@ -339,59 +339,59 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
}
#ifdef __KERNEL_SSE3__
-ccl_device_inline void math_vector_zero_sse(__m128 *A, int n)
+ccl_device_inline void math_vector_zero_sse(float4 *A, int n)
{
for(int i = 0; i < n; i++) {
- A[i] = _mm_setzero_ps();
+ A[i] = make_float4(0.0f);
}
}
-ccl_device_inline void math_matrix_zero_sse(__m128 *A, int n)
+ccl_device_inline void math_matrix_zero_sse(float4 *A, int n)
{
for(int row = 0; row < n; row++) {
for(int col = 0; col <= row; col++) {
- MAT(A, n, row, col) = _mm_setzero_ps();
+ MAT(A, n, row, col) = make_float4(0.0f);
}
}
}
/* Add Gramian matrix of v to A.
* The Gramian matrix of v is v^T*v, so element (i,j) is v[i]*v[j]. */
-ccl_device_inline void math_matrix_add_gramian_sse(__m128 *A, int n, const __m128 *ccl_restrict v, __m128 weight)
+ccl_device_inline void math_matrix_add_gramian_sse(float4 *A, int n, const float4 *ccl_restrict v, float4 weight)
{
for(int row = 0; row < n; row++) {
for(int col = 0; col <= row; col++) {
- MAT(A, n, row, col) = _mm_add_ps(MAT(A, n, row, col), _mm_mul_ps(_mm_mul_ps(v[row], v[col]), weight));
+ MAT(A, n, row, col) = MAT(A, n, row, col) + v[row] * v[col] * weight;
}
}
}
-ccl_device_inline void math_vector_add_sse(__m128 *V, int n, const __m128 *ccl_restrict a)
+ccl_device_inline void math_vector_add_sse(float4 *V, int n, const float4 *ccl_restrict a)
{
for(int i = 0; i < n; i++) {
- V[i] = _mm_add_ps(V[i], a[i]);
+ V[i] += a[i];
}
}
-ccl_device_inline void math_vector_mul_sse(__m128 *V, int n, const __m128 *ccl_restrict a)
+ccl_device_inline void math_vector_mul_sse(float4 *V, int n, const float4 *ccl_restrict a)
{
for(int i = 0; i < n; i++) {
- V[i] = _mm_mul_ps(V[i], a[i]);
+ V[i] *= a[i];
}
}
-ccl_device_inline void math_vector_max_sse(__m128 *a, const __m128 *ccl_restrict b, int n)
+ccl_device_inline void math_vector_max_sse(float4 *a, const float4 *ccl_restrict b, int n)
{
for(int i = 0; i < n; i++) {
- a[i] = _mm_max_ps(a[i], b[i]);
+ a[i] = max(a[i], b[i]);
}
}
-ccl_device_inline void math_matrix_hsum(float *A, int n, const __m128 *ccl_restrict B)
+ccl_device_inline void math_matrix_hsum(float *A, int n, const float4 *ccl_restrict B)
{
for(int row = 0; row < n; row++) {
for(int col = 0; col <= row; col++) {
- MAT(A, n, row, col) = _mm_hsum_ss(MAT(B, n, row, col));
+ MAT(A, n, row, col) = reduce_add(MAT(B, n, row, col))[0];
}
}
}
diff --git a/intern/cycles/util/util_optimization.h b/intern/cycles/util/util_optimization.h
index 6f70a474fe7..0382c0811dd 100644
--- a/intern/cycles/util/util_optimization.h
+++ b/intern/cycles/util/util_optimization.h
@@ -19,16 +19,6 @@
#ifndef __KERNEL_GPU__
-/* quiet unused define warnings */
-#if defined(__KERNEL_SSE2__) || \
- defined(__KERNEL_SSE3__) || \
- defined(__KERNEL_SSSE3__) || \
- defined(__KERNEL_SSE41__) || \
- defined(__KERNEL_AVX__) || \
- defined(__KERNEL_AVX2__)
- /* do nothing */
-#endif
-
/* x86
*
* Compile a regular, SSE2 and SSE3 kernel. */
@@ -73,48 +63,6 @@
#endif /* defined(__x86_64__) || defined(_M_X64) */
-/* SSE Experiment
- *
- * This is disabled code for an experiment to use SSE types globally for types
- * such as float3 and float4. Currently this gives an overall slowdown. */
-
-#if 0
-# define __KERNEL_SSE__
-# ifndef __KERNEL_SSE2__
-# define __KERNEL_SSE2__
-# endif
-# ifndef __KERNEL_SSE3__
-# define __KERNEL_SSE3__
-# endif
-# ifndef __KERNEL_SSSE3__
-# define __KERNEL_SSSE3__
-# endif
-# ifndef __KERNEL_SSE4__
-# define __KERNEL_SSE4__
-# endif
-#endif
-
-/* SSE Intrinsics includes
- *
- * We assume __KERNEL_SSEX__ flags to have been defined at this point */
-
-/* SSE intrinsics headers */
-#ifndef FREE_WINDOWS64
-
-#ifdef _MSC_VER
-# include <intrin.h>
-#elif (defined(__x86_64__) || defined(__i386__))
-# include <x86intrin.h>
-#endif
-
-#else
-
-/* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
- * Since we can't avoid including <windows.h>, better only include that */
-#include "util/util_windows.h"
-
-#endif
-
#endif
#endif /* __UTIL_OPTIMIZATION_H__ */
diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index f9c3b4bb139..bae5d5bd6d1 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -45,6 +45,7 @@ OIIO_NAMESPACE_USING
# include <shlwapi.h>
#endif
+#include "util/util_map.h"
#include "util/util_windows.h"
CCL_NAMESPACE_BEGIN
@@ -768,68 +769,180 @@ bool path_remove(const string& path)
return remove(path.c_str()) == 0;
}
-static string line_directive(const string& base, const string& path, int line)
+struct SourceReplaceState {
+ typedef map<string, string> ProcessedMapping;
+ /* Base director for all relative include headers. */
+ string base;
+ /* Result of processed files. */
+ ProcessedMapping processed_files;
+ /* Set of files which are considered "precompiled" and which are replaced
+ * with and empty string on a subsequent occurrence in include statement.
+ */
+ set<string> precompiled_headers;
+};
+
+static string path_source_replace_includes_recursive(
+ const string& source,
+ const string& source_filepath,
+ SourceReplaceState *state);
+
+static string line_directive(const SourceReplaceState& state,
+ const string& path,
+ const int line)
{
- string escaped_path = path;
+ string unescaped_path = path;
/* First we make path relative. */
- if(string_startswith(escaped_path, base.c_str())) {
- const string base_file = path_filename(base);
- const size_t base_len = base.length();
- escaped_path = base_file + escaped_path.substr(base_len,
- escaped_path.length() - base_len);
+ if(string_startswith(unescaped_path, state.base.c_str())) {
+ const string base_file = path_filename(state.base);
+ const size_t base_len = state.base.length();
+ unescaped_path = base_file +
+ unescaped_path.substr(base_len,
+ unescaped_path.length() - base_len);
}
/* Second, we replace all unsafe characters. */
- string_replace(escaped_path, "\"", "\\\"");
- string_replace(escaped_path, "\'", "\\\'");
- string_replace(escaped_path, "\?", "\\\?");
- string_replace(escaped_path, "\\", "\\\\");
+ const size_t length = unescaped_path.length();
+ string escaped_path = "";
+ for(size_t i = 0; i < length; ++i) {
+ const char ch = unescaped_path[i];
+ if(strchr("\"\'\?\\", ch) != NULL) {
+ escaped_path += "\\";
+ }
+ escaped_path += ch;
+ }
+ /* TODO(sergey): Check whether using std::to_string combined with several
+ * concatenation operations is any faster.
+ */
return string_printf("#line %d \"%s\"", line, escaped_path.c_str());
}
+static string path_source_handle_preprocessor(
+ const string& preprocessor_line,
+ const string& source_filepath,
+ const size_t line_number,
+ SourceReplaceState *state)
+{
+ string result = preprocessor_line;
+ string token = string_strip(
+ preprocessor_line.substr(1, preprocessor_line.size() - 1));
+ if(string_startswith(token, "include")) {
+ token = string_strip(token.substr(7, token.size() - 7));
+ if(token[0] == '"') {
+ const size_t n_start = 1;
+ const size_t n_end = token.find("\"", n_start);
+ const string filename = token.substr(n_start, n_end - n_start);
+ const bool is_precompiled = string_endswith(token, "// PRECOMPILED");
+ string filepath = path_join(state->base, filename);
+ if(!path_exists(filepath)) {
+ filepath = path_join(path_dirname(source_filepath),
+ filename);
+ }
+ if(is_precompiled) {
+ state->precompiled_headers.insert(filepath);
+ }
+ string text;
+ if(path_read_text(filepath, text)) {
+ text = path_source_replace_includes_recursive(
+ text, filepath, state);
+ /* Use line directives for better error messages. */
+ result = line_directive(*state, filepath, 1) + "\n"
+ + text + "\n"
+ + line_directive(*state, source_filepath, line_number + 1);
+ }
+ }
+ }
+ return result;
+}
+
+/* Our own little c preprocessor that replaces #includes with the file
+ * contents, to work around issue of OpenCL drivers not supporting
+ * include paths with spaces in them.
+ */
static string path_source_replace_includes_recursive(
- const string& base,
const string& source,
- const string& source_filepath)
+ const string& source_filepath,
+ SourceReplaceState *state)
{
- /* Our own little c preprocessor that replaces #includes with the file
- * contents, to work around issue of OpenCL drivers not supporting
- * include paths with spaces in them.
+ /* Try to re-use processed file without spending time on replacing all
+ * include directives again.
*/
-
+ SourceReplaceState::ProcessedMapping::iterator replaced_file =
+ state->processed_files.find(source_filepath);
+ if(replaced_file != state->processed_files.end()) {
+ if(state->precompiled_headers.find(source_filepath) !=
+ state->precompiled_headers.end()) {
+ return "";
+ }
+ return replaced_file->second;
+ }
+ /* Perform full file processing. */
string result = "";
- vector<string> lines;
- string_split(lines, source, "\n", false);
-
- for(size_t i = 0; i < lines.size(); ++i) {
- string line = lines[i];
- if(line[0] == '#') {
- string token = string_strip(line.substr(1, line.size() - 1));
- if(string_startswith(token, "include")) {
- token = string_strip(token.substr(7, token.size() - 7));
- if(token[0] == '"') {
- const size_t n_start = 1;
- const size_t n_end = token.find("\"", n_start);
- const string filename = token.substr(n_start, n_end - n_start);
- string filepath = path_join(base, filename);
- if(!path_exists(filepath)) {
- filepath = path_join(path_dirname(source_filepath),
- filename);
- }
- string text;
- if(path_read_text(filepath, text)) {
- text = path_source_replace_includes_recursive(
- base, text, filepath);
- /* Use line directives for better error messages. */
- line = line_directive(base, filepath, 1)
- + token.replace(0, n_end + 1, "\n" + text + "\n")
- + line_directive(base, source_filepath, i + 1);
- }
- }
+ const size_t source_length = source.length();
+ size_t index = 0;
+ /* Information about where we are in the source. */
+ size_t line_number = 0, column_number = 1;
+ /* Currently gathered non-preprocessor token.
+ * Store as start/length rather than token itself to avoid overhead of
+ * memory re-allocations on each character concatenation.
+ */
+ size_t token_start = 0, token_length = 0;
+ /* Denotes whether we're inside of preprocessor line, together with
+ * preprocessor line itself.
+ *
+ * TODO(sergey): Investigate whether using token start/end position
+ * gives measurable speedup.
+ */
+ bool inside_preprocessor = false;
+ string preprocessor_line = "";
+ /* Actual loop over the whole source. */
+ while(index < source_length) {
+ const char ch = source[index];
+ if(ch == '\n') {
+ if(inside_preprocessor) {
+ result += path_source_handle_preprocessor(preprocessor_line,
+ source_filepath,
+ line_number,
+ state);
+ /* Start gathering net part of the token. */
+ token_start = index;
+ token_length = 0;
+ }
+ inside_preprocessor = false;
+ preprocessor_line = "";
+ column_number = 0;
+ ++line_number;
+ }
+ else if(ch == '#' && column_number == 1 && !inside_preprocessor) {
+ /* Append all possible non-preprocessor token to the result. */
+ if(token_length != 0) {
+ result.append(source, token_start, token_length);
+ token_start = index;
+ token_length = 0;
}
+ inside_preprocessor = true;
+ }
+ if(inside_preprocessor) {
+ preprocessor_line += ch;
+ }
+ else {
+ ++token_length;
}
- result += line + "\n";
+ ++index;
+ ++column_number;
}
-
+ /* Append possible tokens which happened before special events handled
+ * above.
+ */
+ if(token_length != 0) {
+ result.append(source, token_start, token_length);
+ }
+ if(inside_preprocessor) {
+ result += path_source_handle_preprocessor(preprocessor_line,
+ source_filepath,
+ line_number,
+ state);
+ }
+ /* Store result for further reuse. */
+ state->processed_files[source_filepath] = result;
return result;
}
@@ -837,10 +950,12 @@ string path_source_replace_includes(const string& source,
const string& path,
const string& source_filename)
{
+ SourceReplaceState state;
+ state.base = path;
return path_source_replace_includes_recursive(
- path,
source,
- path_join(path, source_filename));
+ path_join(path, source_filename),
+ &state);
}
FILE *path_fopen(const string& path, const string& mode)
diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h
index bc672669e1f..134383e88db 100644
--- a/intern/cycles/util/util_progress.h
+++ b/intern/cycles/util/util_progress.h
@@ -41,6 +41,7 @@ public:
denoised_tiles = 0;
start_time = time_dt();
render_start_time = time_dt();
+ end_time = 0.0;
status = "Initializing";
substatus = "";
sync_status = "";
@@ -80,6 +81,7 @@ public:
denoised_tiles = 0;
start_time = time_dt();
render_start_time = time_dt();
+ end_time = 0.0;
status = "Initializing";
substatus = "";
sync_status = "";
@@ -146,6 +148,7 @@ public:
thread_scoped_lock lock(progress_mutex);
start_time = time_dt();
+ end_time = 0.0;
}
void set_render_start_time()
@@ -169,8 +172,15 @@ public:
{
thread_scoped_lock lock(progress_mutex);
- total_time_ = time_dt() - start_time;
- render_time_ = time_dt() - render_start_time;
+ double time = (end_time > 0) ? end_time : time_dt();
+
+ total_time_ = time - start_time;
+ render_time_ = time - render_start_time;
+ }
+
+ void set_end_time()
+ {
+ end_time = time_dt();
}
void reset_sample()
@@ -226,6 +236,7 @@ public:
int get_current_sample()
{
+ thread_scoped_lock lock(progress_mutex);
/* Note that the value here always belongs to the last tile that updated,
* so it's only useful if there is only one active tile. */
return current_tile_sample;
@@ -233,11 +244,13 @@ public:
int get_rendered_tiles()
{
+ thread_scoped_lock lock(progress_mutex);
return rendered_tiles;
}
int get_denoised_tiles()
{
+ thread_scoped_lock lock(progress_mutex);
return denoised_tiles;
}
@@ -334,6 +347,8 @@ protected:
int rendered_tiles, denoised_tiles;
double start_time, render_start_time;
+ /* End time written when render is done, so it doesn't keep increasing on redraws. */
+ double end_time;
string status;
string substatus;
diff --git a/intern/cycles/util/util_simd.h b/intern/cycles/util/util_simd.h
index 587febe3e52..58b3d267266 100644
--- a/intern/cycles/util/util_simd.h
+++ b/intern/cycles/util/util_simd.h
@@ -18,19 +18,38 @@
#ifndef __UTIL_SIMD_TYPES_H__
#define __UTIL_SIMD_TYPES_H__
+#ifndef __KERNEL_GPU__
+
#include <limits>
#include "util/util_debug.h"
-#include "util/util_types.h"
+#include "util/util_defines.h"
+
+/* SSE Intrinsics includes
+ *
+ * We assume __KERNEL_SSEX__ flags to have been defined at this point */
+
+/* SSE intrinsics headers */
+#ifndef FREE_WINDOWS64
+
+#ifdef _MSC_VER
+# include <intrin.h>
+#elif (defined(__x86_64__) || defined(__i386__))
+# include <x86intrin.h>
+#endif
+
+#else
+
+/* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
+ * Since we can't avoid including <windows.h>, better only include that */
+#include "util/util_windows.h"
+
+#endif
CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_SSE2__
-struct sseb;
-struct ssei;
-struct ssef;
-
extern const __m128 _mm_lookupmask_ps[16];
/* Special Types */
@@ -328,12 +347,12 @@ __forceinline size_t __bscf(size_t& v)
#endif /* _WIN32 */
-static const unsigned int BITSCAN_NO_BIT_SET_32 = 32;
-static const size_t BITSCAN_NO_BIT_SET_64 = 64;
+/* Test __KERNEL_SSE41__ for MSVC which does not define __SSE4_1__, and test
+ * __SSE4_1__ to avoid OpenImageIO conflicts with our emulation macros on other
+ * platforms when compiling code outside the kernel. */
+#if !(defined(__KERNEL_SSE41__) || defined(__SSE4_1__) || defined(__SSE4_2__))
-#ifdef __KERNEL_SSE3__
-/* Emulation of SSE4 functions with SSE3 */
-# ifndef __KERNEL_SSE41__
+/* Emulation of SSE4 functions with SSE2 */
#define _MM_FROUND_TO_NEAREST_INT 0x00
#define _MM_FROUND_TO_NEG_INF 0x01
@@ -342,50 +361,50 @@ static const size_t BITSCAN_NO_BIT_SET_64 = 64;
#define _MM_FROUND_CUR_DIRECTION 0x04
#undef _mm_blendv_ps
-#define _mm_blendv_ps __emu_mm_blendv_ps
-__forceinline __m128 _mm_blendv_ps( __m128 value, __m128 input, __m128 mask ) {
- return _mm_or_ps(_mm_and_ps(mask, input), _mm_andnot_ps(mask, value));
+#define _mm_blendv_ps _mm_blendv_ps_emu
+__forceinline __m128 _mm_blendv_ps_emu( __m128 value, __m128 input, __m128 mask)
+{
+ __m128i isignmask = _mm_set1_epi32(0x80000000);
+ __m128 signmask = _mm_castsi128_ps(isignmask);
+ __m128i iandsign = _mm_castps_si128(_mm_and_ps(mask, signmask));
+ __m128i icmpmask = _mm_cmpeq_epi32(iandsign, isignmask);
+ __m128 cmpmask = _mm_castsi128_ps(icmpmask);
+ return _mm_or_ps(_mm_and_ps(cmpmask, input), _mm_andnot_ps(cmpmask, value));
}
#undef _mm_blend_ps
-#define _mm_blend_ps __emu_mm_blend_ps
-__forceinline __m128 _mm_blend_ps( __m128 value, __m128 input, const int mask ) {
+#define _mm_blend_ps _mm_blend_ps_emu
+__forceinline __m128 _mm_blend_ps_emu( __m128 value, __m128 input, const int mask)
+{
assert(mask < 0x10); return _mm_blendv_ps(value, input, _mm_lookupmask_ps[mask]);
}
#undef _mm_blendv_epi8
-#define _mm_blendv_epi8 __emu_mm_blendv_epi8
-__forceinline __m128i _mm_blendv_epi8( __m128i value, __m128i input, __m128i mask ) {
+#define _mm_blendv_epi8 _mm_blendv_epi8_emu
+__forceinline __m128i _mm_blendv_epi8_emu( __m128i value, __m128i input, __m128i mask)
+{
return _mm_or_si128(_mm_and_si128(mask, input), _mm_andnot_si128(mask, value));
}
-#undef _mm_mullo_epi32
-#define _mm_mullo_epi32 __emu_mm_mullo_epi32
-__forceinline __m128i _mm_mullo_epi32( __m128i value, __m128i input ) {
- __m128i rvalue;
- char* _r = (char*)(&rvalue + 1);
- char* _v = (char*)(& value + 1);
- char* _i = (char*)(& input + 1);
- for( ssize_t i = -16 ; i != 0 ; i += 4 ) *((int32_t*)(_r + i)) = *((int32_t*)(_v + i))* *((int32_t*)(_i + i));
- return rvalue;
-}
-
#undef _mm_min_epi32
-#define _mm_min_epi32 __emu_mm_min_epi32
-__forceinline __m128i _mm_min_epi32( __m128i value, __m128i input ) {
+#define _mm_min_epi32 _mm_min_epi32_emu
+__forceinline __m128i _mm_min_epi32_emu( __m128i value, __m128i input)
+{
return _mm_blendv_epi8(input, value, _mm_cmplt_epi32(value, input));
}
#undef _mm_max_epi32
-#define _mm_max_epi32 __emu_mm_max_epi32
-__forceinline __m128i _mm_max_epi32( __m128i value, __m128i input ) {
+#define _mm_max_epi32 _mm_max_epi32_emu
+__forceinline __m128i _mm_max_epi32_emu( __m128i value, __m128i input)
+{
return _mm_blendv_epi8(value, input, _mm_cmplt_epi32(value, input));
}
#undef _mm_extract_epi32
-#define _mm_extract_epi32 __emu_mm_extract_epi32
-__forceinline int _mm_extract_epi32( __m128i input, const int index ) {
- switch ( index ) {
+#define _mm_extract_epi32 _mm_extract_epi32_emu
+__forceinline int _mm_extract_epi32_emu( __m128i input, const int index)
+{
+ switch(index) {
case 0: return _mm_cvtsi128_si32(input);
case 1: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(1, 1, 1, 1)));
case 2: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(2, 2, 2, 2)));
@@ -395,27 +414,26 @@ __forceinline int _mm_extract_epi32( __m128i input, const int index ) {
}
#undef _mm_insert_epi32
-#define _mm_insert_epi32 __emu_mm_insert_epi32
-__forceinline __m128i _mm_insert_epi32( __m128i value, int input, const int index ) {
+#define _mm_insert_epi32 _mm_insert_epi32_emu
+__forceinline __m128i _mm_insert_epi32_emu( __m128i value, int input, const int index)
+{
assert(index >= 0 && index < 4); ((int*)&value)[index] = input; return value;
}
-#undef _mm_extract_ps
-#define _mm_extract_ps __emu_mm_extract_ps
-__forceinline int _mm_extract_ps( __m128 input, const int index ) {
- int32_t* ptr = (int32_t*)&input; return ptr[index];
-}
-
#undef _mm_insert_ps
-#define _mm_insert_ps __emu_mm_insert_ps
-__forceinline __m128 _mm_insert_ps( __m128 value, __m128 input, const int index )
-{ assert(index < 0x100); ((float*)&value)[(index >> 4)&0x3] = ((float*)&input)[index >> 6]; return _mm_andnot_ps(_mm_lookupmask_ps[index&0xf], value); }
+#define _mm_insert_ps _mm_insert_ps_emu
+__forceinline __m128 _mm_insert_ps_emu( __m128 value, __m128 input, const int index)
+{
+ assert(index < 0x100);
+ ((float*)&value)[(index >> 4)&0x3] = ((float*)&input)[index >> 6];
+ return _mm_andnot_ps(_mm_lookupmask_ps[index&0xf], value);
+}
#undef _mm_round_ps
-#define _mm_round_ps __emu_mm_round_ps
-__forceinline __m128 _mm_round_ps( __m128 value, const int flags )
+#define _mm_round_ps _mm_round_ps_emu
+__forceinline __m128 _mm_round_ps_emu( __m128 value, const int flags)
{
- switch ( flags )
+ switch(flags)
{
case _MM_FROUND_TO_NEAREST_INT: return _mm_cvtepi32_ps(_mm_cvtps_epi32(value));
case _MM_FROUND_TO_NEG_INF : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps(-0.5f))));
@@ -425,57 +443,7 @@ __forceinline __m128 _mm_round_ps( __m128 value, const int flags )
return value;
}
-# ifdef _M_X64
-#undef _mm_insert_epi64
-#define _mm_insert_epi64 __emu_mm_insert_epi64
-__forceinline __m128i _mm_insert_epi64( __m128i value, __int64 input, const int index ) {
- assert(size_t(index) < 4); ((__int64*)&value)[index] = input; return value;
-}
-
-#undef _mm_extract_epi64
-#define _mm_extract_epi64 __emu_mm_extract_epi64
-__forceinline __int64 _mm_extract_epi64( __m128i input, const int index ) {
- assert(size_t(index) < 2);
- return index == 0 ? _mm_cvtsi128_si64x(input) : _mm_cvtsi128_si64x(_mm_unpackhi_epi64(input, input));
-}
-# endif
-
-# endif
-
-#undef _mm_fabs_ps
-#define _mm_fabs_ps(x) _mm_and_ps(x, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)))
-
-/* Return a __m128 with every element set to the largest element of v. */
-ccl_device_inline __m128 _mm_hmax_ps(__m128 v)
-{
- /* v[0, 1, 2, 3] => [0, 1, 0, 1] and [2, 3, 2, 3] => v[max(0, 2), max(1, 3), max(0, 2), max(1, 3)] */
- v = _mm_max_ps(_mm_movehl_ps(v, v), _mm_movelh_ps(v, v));
- /* v[max(0, 2), max(1, 3), max(0, 2), max(1, 3)] => [4 times max(1, 3)] and [4 times max(0, 2)] => v[4 times max(0, 1, 2, 3)] */
- v = _mm_max_ps(_mm_movehdup_ps(v), _mm_moveldup_ps(v));
- return v;
-}
-
-/* Return the sum of the four elements of x. */
-ccl_device_inline float _mm_hsum_ss(__m128 x)
-{
- __m128 a = _mm_movehdup_ps(x);
- __m128 b = _mm_add_ps(x, a);
- return _mm_cvtss_f32(_mm_add_ss(_mm_movehl_ps(a, b), b));
-}
-
-/* Return a __m128 with every element set to the sum of the four elements of x. */
-ccl_device_inline __m128 _mm_hsum_ps(__m128 x)
-{
- x = _mm_hadd_ps(x, x);
- x = _mm_hadd_ps(x, x);
- return x;
-}
-
-/* Replace elements of x with zero where mask isn't set. */
-#undef _mm_mask_ps
-#define _mm_mask_ps(x, mask) _mm_blendv_ps(_mm_setzero_ps(), x, mask)
-
-#endif
+#endif /* !(defined(__KERNEL_SSE41__) || defined(__SSE4_1__) || defined(__SSE4_2__)) */
#else /* __KERNEL_SSE2__ */
@@ -496,13 +464,19 @@ ccl_device_inline int bitscan(int value)
#endif /* __KERNEL_SSE2__ */
+/* quiet unused define warnings */
+#if defined(__KERNEL_SSE2__) || \
+ defined(__KERNEL_SSE3__) || \
+ defined(__KERNEL_SSSE3__) || \
+ defined(__KERNEL_SSE41__) || \
+ defined(__KERNEL_AVX__) || \
+ defined(__KERNEL_AVX2__)
+ /* do nothing */
+#endif
+
CCL_NAMESPACE_END
-#include "util/util_math.h"
-#include "util/util_sseb.h"
-#include "util/util_ssei.h"
-#include "util/util_ssef.h"
-#include "util/util_avxf.h"
+#endif /* __KERNEL_GPU__ */
#endif /* __UTIL_SIMD_TYPES_H__ */
diff --git a/intern/cycles/util/util_sseb.h b/intern/cycles/util/util_sseb.h
index 6e669701f3b..93c22aafdcd 100644
--- a/intern/cycles/util/util_sseb.h
+++ b/intern/cycles/util/util_sseb.h
@@ -22,6 +22,9 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_SSE2__
+struct ssei;
+struct ssef;
+
/*! 4-wide SSE bool type. */
struct sseb
{
diff --git a/intern/cycles/util/util_ssef.h b/intern/cycles/util/util_ssef.h
index cf99a08efae..bb007ff84a9 100644
--- a/intern/cycles/util/util_ssef.h
+++ b/intern/cycles/util/util_ssef.h
@@ -22,6 +22,9 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_SSE2__
+struct sseb;
+struct ssef;
+
/*! 4-wide SSE float type. */
struct ssef
{
diff --git a/intern/cycles/util/util_ssei.h b/intern/cycles/util/util_ssei.h
index 5f62569268c..ef2a9e68b7d 100644
--- a/intern/cycles/util/util_ssei.h
+++ b/intern/cycles/util/util_ssei.h
@@ -22,6 +22,9 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_SSE2__
+struct sseb;
+struct ssef;
+
/*! 4-wide SSE integer type. */
struct ssei
{
@@ -234,8 +237,10 @@ __forceinline size_t select_max(const sseb& valid, const ssei& v) { const ssei a
#else
-__forceinline int reduce_min(const ssei& v) { return min(min(v[0],v[1]),min(v[2],v[3])); }
-__forceinline int reduce_max(const ssei& v) { return max(max(v[0],v[1]),max(v[2],v[3])); }
+__forceinline int ssei_min(int a, int b) { return (a < b)? a: b; }
+__forceinline int ssei_max(int a, int b) { return (a > b)? a: b; }
+__forceinline int reduce_min(const ssei& v) { return ssei_min(ssei_min(v[0],v[1]),ssei_min(v[2],v[3])); }
+__forceinline int reduce_max(const ssei& v) { return ssei_max(ssei_max(v[0],v[1]),ssei_max(v[2],v[3])); }
__forceinline int reduce_add(const ssei& v) { return v[0]+v[1]+v[2]+v[3]; }
#endif
diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h
index baba549753d..7667f58eb7d 100644
--- a/intern/cycles/util/util_stats.h
+++ b/intern/cycles/util/util_stats.h
@@ -30,7 +30,7 @@ public:
void mem_alloc(size_t size) {
atomic_add_and_fetch_z(&mem_used, size);
- atomic_update_max_z(&mem_peak, mem_used);
+ atomic_fetch_and_update_max_z(&mem_peak, mem_used);
}
void mem_free(size_t size) {
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index a1008d510d1..94ad512982c 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -148,6 +148,12 @@ void string_replace(string& haystack, const string& needle, const string& other)
string string_remove_trademark(const string &s)
{
string result = s;
+
+ /* Special case, so we don;t leave sequential spaces behind. */
+ /* TODO(sergey): Consider using regex perhaps? */
+ string_replace(result, " (TM)", "");
+ string_replace(result, " (R)", "");
+
string_replace(result, "(TM)", "");
string_replace(result, "(R)", "");
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index fb0c34e1dc4..6ed97b0e0a6 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -206,9 +206,9 @@ void TaskScheduler::init(int num_threads)
threads.resize(num_threads);
const int num_groups = system_cpu_group_count();
- unsigned short num_process_groups;
+ unsigned short num_process_groups = 0;
vector<unsigned short> process_groups;
- int current_group_threads;
+ int current_group_threads = 0;
if(num_groups > 1) {
process_groups.resize(num_groups);
num_process_groups = system_cpu_process_groups(num_groups,
diff --git a/intern/cycles/util/util_time.h b/intern/cycles/util/util_time.h
index 65798244111..f03aa590e9b 100644
--- a/intern/cycles/util/util_time.h
+++ b/intern/cycles/util/util_time.h
@@ -37,7 +37,7 @@ public:
~scoped_timer()
{
if(value_ != NULL) {
- *value_ = time_dt() - time_start_;
+ *value_ = get_time();
}
}
@@ -46,6 +46,11 @@ public:
return time_start_;
}
+ double get_time() const
+ {
+ return time_dt() - time_start_;
+ }
+
protected:
double *value_;
double time_start_;
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index a5d1d7152d5..aabca6c81fc 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -21,72 +21,18 @@
# include <stdlib.h>
#endif
-/* Bitness */
+/* Standard Integer Types */
-#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
-# define __KERNEL_64_BIT__
+#if !defined(__KERNEL_GPU__) && !defined(_WIN32)
+# include <stdint.h>
#endif
-/* Qualifiers for kernel code shared by CPU and GPU */
-
-#ifndef __KERNEL_GPU__
-# define ccl_device static inline
-# define ccl_device_noinline static
-# define ccl_global
-# define ccl_constant
-# define ccl_local
-# define ccl_local_param
-# define ccl_private
-# define ccl_restrict __restrict
-# define __KERNEL_WITH_SSE_ALIGN__
-
-# if defined(_WIN32) && !defined(FREE_WINDOWS)
-# define ccl_device_inline static __forceinline
-# define ccl_device_forceinline static __forceinline
-# define ccl_align(...) __declspec(align(__VA_ARGS__))
-# ifdef __KERNEL_64_BIT__
-# define ccl_try_align(...) __declspec(align(__VA_ARGS__))
-# else /* __KERNEL_64_BIT__ */
-# undef __KERNEL_WITH_SSE_ALIGN__
-/* No support for function arguments (error C2719). */
-# define ccl_try_align(...)
-# endif /* __KERNEL_64_BIT__ */
-# define ccl_may_alias
-# define ccl_always_inline __forceinline
-# define ccl_never_inline __declspec(noinline)
-# define ccl_maybe_unused
-# else /* _WIN32 && !FREE_WINDOWS */
-# define ccl_device_inline static inline __attribute__((always_inline))
-# define ccl_device_forceinline static inline __attribute__((always_inline))
-# define ccl_align(...) __attribute__((aligned(__VA_ARGS__)))
-# ifndef FREE_WINDOWS64
-# define __forceinline inline __attribute__((always_inline))
-# endif
-# define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
-# define ccl_may_alias __attribute__((__may_alias__))
-# define ccl_always_inline __attribute__((always_inline))
-# define ccl_never_inline __attribute__((noinline))
-# define ccl_maybe_unused __attribute__((used))
-# endif /* _WIN32 && !FREE_WINDOWS */
-
-/* Use to suppress '-Wimplicit-fallthrough' (in place of 'break'). */
-# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */
-# define ATTR_FALLTHROUGH __attribute__((fallthrough))
-# else
-# define ATTR_FALLTHROUGH ((void)0)
-# endif
-#endif /* __KERNEL_GPU__ */
-
-/* Standard Integer Types */
+#include "util/util_defines.h"
#ifndef __KERNEL_GPU__
-/* int8_t, uint16_t, and friends */
-# ifndef _WIN32
-# include <stdint.h>
-# endif
-/* SIMD Types */
# include "util/util_optimization.h"
-#endif /* __KERNEL_GPU__ */
+# include "util/util_simd.h"
+#endif
CCL_NAMESPACE_BEGIN
@@ -201,65 +147,8 @@ enum ExtensionType {
EXTENSION_NUM_TYPES,
};
-/* macros */
-
-/* hints for branch prediction, only use in code that runs a _lot_ */
-#if defined(__GNUC__) && defined(__KERNEL_CPU__)
-# define LIKELY(x) __builtin_expect(!!(x), 1)
-# define UNLIKELY(x) __builtin_expect(!!(x), 0)
-#else
-# define LIKELY(x) (x)
-# define UNLIKELY(x) (x)
-#endif
-
-#if defined(__cplusplus) && ((__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800))
-# define HAS_CPP11_FEATURES
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
-# if defined(HAS_CPP11_FEATURES)
-/* Some magic to be sure we don't have reference in the type. */
-template<typename T> static inline T decltype_helper(T x) { return x; }
-# define TYPEOF(x) decltype(decltype_helper(x))
-# else
-# define TYPEOF(x) typeof(x)
-# endif
-#endif
-
-/* Causes warning:
- * incompatible types when assigning to type 'Foo' from type 'Bar'
- * ... the compiler optimizes away the temp var */
-#ifdef __GNUC__
-#define CHECK_TYPE(var, type) { \
- TYPEOF(var) *__tmp; \
- __tmp = (type *)NULL; \
- (void)__tmp; \
-} (void)0
-
-#define CHECK_TYPE_PAIR(var_a, var_b) { \
- TYPEOF(var_a) *__tmp; \
- __tmp = (typeof(var_b) *)NULL; \
- (void)__tmp; \
-} (void)0
-#else
-# define CHECK_TYPE(var, type)
-# define CHECK_TYPE_PAIR(var_a, var_b)
-#endif
-
-/* can be used in simple macros */
-#define CHECK_TYPE_INLINE(val, type) \
- ((void)(((type)0) != (val)))
-
-
CCL_NAMESPACE_END
-#ifndef __KERNEL_GPU__
-# include <cassert>
-# define util_assert(statement) assert(statement)
-#else
-# define util_assert(statement)
-#endif
-
/* Vectorized types declaration. */
#include "util/util_types_uchar2.h"
#include "util/util_types_uchar3.h"
@@ -298,5 +187,13 @@ CCL_NAMESPACE_END
#include "util/util_types_vector3_impl.h"
+/* SSE types. */
+#ifndef __KERNEL_GPU__
+# include "util/util_sseb.h"
+# include "util/util_ssei.h"
+# include "util/util_ssef.h"
+# include "util/util_avxf.h"
+#endif
+
#endif /* __UTIL_TYPES_H__ */
diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp
index fb61fb416b4..de7bfe8e687 100644
--- a/intern/elbeem/intern/isosurface.cpp
+++ b/intern/elbeem/intern/isosurface.cpp
@@ -15,6 +15,7 @@
#include "particletracer.h"
#include <algorithm>
#include <stdio.h>
+#include <cmath>
#ifdef sun
#include "ieeefp.h"
@@ -25,6 +26,8 @@
#define round(x) (x)
#endif
+using std::isfinite;
+
/******************************************************************************
* Constructor
*****************************************************************************/
@@ -937,17 +940,10 @@ void IsoSurface::smoothSurface(float sigma, bool normSmooth)
ew[(j+2)%3]);
}
- // NT important, check this...
-#ifndef WIN32
- if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6;
- if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6;
- if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6;
-#else // WIN32
- // FIXME check as well...
- if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6;
- if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6;
- if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6;
-#endif // WIN32
+ // FIX T50887: ensure pointareas are finite
+ if (!isfinite(cornerareas[i][0])) cornerareas[i][0] = 1e-6;
+ if (!isfinite(cornerareas[i][1])) cornerareas[i][1] = 1e-6;
+ if (!isfinite(cornerareas[i][2])) cornerareas[i][2] = 1e-6;
pointareas[mIndices[i*3+0]] += cornerareas[i][0];
pointareas[mIndices[i*3+1]] += cornerareas[i][1];
@@ -1096,17 +1092,10 @@ void IsoSurface::smoothNormals(float sigma) {
ew[(j+2)%3]);
}
- // NT important, check this...
-#ifndef WIN32
- if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6;
- if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6;
- if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6;
-#else // WIN32
- // FIXME check as well...
- if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6;
- if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6;
- if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6;
-#endif // WIN32
+ // FIX T50887: ensure pointareas are finite
+ if (!isfinite(cornerareas[i][0])) cornerareas[i][0] = 1e-6;
+ if (!isfinite(cornerareas[i][1])) cornerareas[i][1] = 1e-6;
+ if (!isfinite(cornerareas[i][2])) cornerareas[i][2] = 1e-6;
pointareas[mIndices[i*3+0]] += cornerareas[i][0];
pointareas[mIndices[i*3+1]] += cornerareas[i][1];
diff --git a/intern/elbeem/intern/solver_util.cpp b/intern/elbeem/intern/solver_util.cpp
index 6eca427c787..f0c7bce2b4e 100644
--- a/intern/elbeem/intern/solver_util.cpp
+++ b/intern/elbeem/intern/solver_util.cpp
@@ -855,6 +855,10 @@ void LbmFsgrSolver::advanceParticles() {
if(k<=mSizez-1-cutval){
CellFlagType pflag = RFLAG(level, i,j,k, workSet);
//errMsg("PIT move"," at "<<PRINT_IJK<<" flag"<<convertCellFlagType2String(pflag) );
+ if (pflag & CFMbndOutflow) {
+ DEL_PART;
+ continue;
+ }
if(pflag & (CFBnd)) {
handleObstacleParticle(p);
continue;
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 6887063eae9..967d3f58143 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -43,7 +43,7 @@ extern "C" {
* Creates a "handle" for a C++ GHOST object.
* A handle is just an opaque pointer to an empty struct.
* In the API the pointer is casted to the actual C++ class.
- * \param name Name of the handle to create.
+ * The 'name' argument to the macro is the name of the handle to create.
*/
GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index b142c2f7194..6802ad42c7b 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -292,11 +292,6 @@ protected:
/** Ignores window size messages (when window is dragged). */
bool m_ignoreWindowSizedMessages;
- /** Stores the mouse cursor delta due to setting a new cursor position
- * Needed because cocoa event delta cursor move takes setCursorPosition changes too.
- */
- GHOST_TInt32 m_cursorDelta_x, m_cursorDelta_y;
-
/** Temporarily ignore momentum scroll events */
bool m_ignoreMomentumScroll;
/** Is the scroll wheel event generated by a multitouch trackpad or mouse? */
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 173f59c9c8f..4582dfb2a49 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -366,8 +366,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
char *rstring = NULL;
m_modifierMask =0;
- m_cursorDelta_x=0;
- m_cursorDelta_y=0;
m_outsideLoopEventProcessed = false;
m_needDelayedApplicationBecomeActiveEventProcessing = false;
m_displayManager = new GHOST_DisplayManagerCocoa ();
@@ -644,6 +642,13 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_T
CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf));
+ // See https://stackoverflow.com/a/17559012. By default, hardware events
+ // will be suppressed for 500ms after a synthetic mouse event. For unknown
+ // reasons CGEventSourceSetLocalEventsSuppressionInterval does not work,
+ // however calling CGAssociateMouseAndMouseCursorPosition also removes the
+ // delay, even if this is undocumented.
+ CGAssociateMouseAndMouseCursorPosition(true);
+
[pool drain];
return GHOST_kSuccess;
}
@@ -1354,9 +1359,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries
{
NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
- GHOST_TInt32 x_mouse= mousePos.x;
- GHOST_TInt32 y_mouse= mousePos.y;
- GHOST_TInt32 x_accum, y_accum, x_cur, y_cur, x, y;
+ GHOST_TInt32 x_mouse = mousePos.x;
+ GHOST_TInt32 y_mouse = mousePos.y;
GHOST_Rect bounds, windowBounds, correctedBounds;
/* fallback to window bounds */
@@ -1370,29 +1374,26 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
correctedBounds.m_b = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_b;
correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t;
- //Update accumulation counts
+ //Get accumulation from previous mouse warps
+ GHOST_TInt32 x_accum, y_accum;
window->getCursorGrabAccum(x_accum, y_accum);
- x_accum += [event deltaX]-m_cursorDelta_x;
- y_accum += -[event deltaY]-m_cursorDelta_y; //Strange Apple implementation (inverted coordinates for the deltaY) ...
- window->setCursorGrabAccum(x_accum, y_accum);
//Warp mouse cursor if needed
- x_mouse += [event deltaX]-m_cursorDelta_x;
- y_mouse += -[event deltaY]-m_cursorDelta_y;
- correctedBounds.wrapPoint(x_mouse, y_mouse, 2);
-
- //Compensate for mouse moved event taking cursor position set into account
- m_cursorDelta_x = x_mouse-mousePos.x;
- m_cursorDelta_y = y_mouse-mousePos.y;
+ GHOST_TInt32 warped_x_mouse = x_mouse;
+ GHOST_TInt32 warped_y_mouse = y_mouse;
+ correctedBounds.wrapPoint(warped_x_mouse, warped_y_mouse, 4);
//Set new cursor position
- window->clientToScreenIntern(x_mouse, y_mouse, x_cur, y_cur);
- setMouseCursorPosition(x_cur, y_cur); /* wrap */
+ if (x_mouse != warped_x_mouse || y_mouse != warped_y_mouse) {
+ GHOST_TInt32 warped_x, warped_y;
+ window->clientToScreenIntern(warped_x_mouse, warped_y_mouse, warped_x, warped_y);
+ setMouseCursorPosition(warped_x, warped_y); /* wrap */
+ window->setCursorGrabAccum(x_accum + (x_mouse - warped_x_mouse), y_accum + (y_mouse - warped_y_mouse));
+ }
- //Post event
- window->getCursorGrabInitPos(x_cur, y_cur);
- window->screenToClientIntern(x_cur, y_cur, x_cur, y_cur);
- window->clientToScreenIntern(x_cur + x_accum, y_cur + y_accum, x, y);
+ //Generate event
+ GHOST_TInt32 x, y;
+ window->clientToScreenIntern(x_mouse + x_accum, y_mouse + y_accum, x, y);
pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y));
break;
}
@@ -1404,9 +1405,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y));
-
- m_cursorDelta_x=0;
- m_cursorDelta_y=0; //Mouse motion occurred between two cursor warps, so we can reset the delta counter
break;
}
}
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 9f03b5e9537..b0dae432643 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -941,6 +941,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized");
if (hwnd) {
+#if 0
+ // Disabled due to bug in Intel drivers, see T51959
if(msg == WM_NCCREATE) {
// Tell Windows to automatically handle scaling of non-client areas
// such as the caption bar. EnableNonClientDpiScaling was introduced in Windows 10
@@ -954,6 +956,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
}
}
+#endif
GHOST_WindowWin32 *window = (GHOST_WindowWin32 *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (window) {
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index b234291396b..5168c48ca2f 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -56,7 +56,7 @@ public:
* \param systemCocoa The associated system class to forward events to
* \param title The text shown in the title bar of the window.
* \param left The coordinate of the left edge of the window.
- * \param top The coordinate of the top edge of the window.
+ * \param bottom The coordinate of the bottom edge of the window.
* \param width The width the window.
* \param height The height the window.
* \param state The state the window is initially opened with.
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 97615dcea96..73c89f9d68d 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -1370,9 +1370,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
//Make window key if it wasn't to get the mouse move events
[m_window makeKeyWindow];
- //Dissociate cursor position even for warp mode, to allow mouse acceleration to work even when warping the cursor
- err = CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
-
[pool drain];
}
}
@@ -1382,7 +1379,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
setWindowCursorVisibility(true);
}
- err = CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
setCursorGrabAccum(0, 0);
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index fc46164c135..7ac54e5c915 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -890,19 +890,14 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
if (fpWTPacket) {
if (fpWTPacket((HCTX)lParam, wParam, &pkt)) {
if (m_tabletData) {
- switch (pkt.pkCursor) {
- case 0: /* first device */
- case 3: /* second device */
+ switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
+ case 0:
m_tabletData->Active = GHOST_kTabletModeNone; /* puck - not yet supported */
break;
case 1:
- case 4:
- case 7:
m_tabletData->Active = GHOST_kTabletModeStylus; /* stylus */
break;
case 2:
- case 5:
- case 8:
m_tabletData->Active = GHOST_kTabletModeEraser; /* eraser */
break;
}
diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
index ce8a5b29ece..66573b91ace 100644
--- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c
+++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
@@ -64,9 +64,9 @@ enum {
MEMHEAD_ALIGN_FLAG = 2,
};
-#define MEMHEAD_FROM_PTR(ptr) (((MemHead*) vmemh) - 1)
+#define MEMHEAD_FROM_PTR(ptr) (((MemHead*) ptr) - 1)
#define PTR_FROM_MEMHEAD(memhead) (memhead + 1)
-#define MEMHEAD_ALIGNED_FROM_PTR(ptr) (((MemHeadAligned*) vmemh) - 1)
+#define MEMHEAD_ALIGNED_FROM_PTR(ptr) (((MemHeadAligned*) ptr) - 1)
#define MEMHEAD_IS_MMAP(memhead) ((memhead)->len & (size_t) MEMHEAD_MMAP_FLAG)
#define MEMHEAD_IS_ALIGNED(memhead) ((memhead)->len & (size_t) MEMHEAD_ALIGN_FLAG)
@@ -76,12 +76,7 @@ enum {
MEM_INLINE void update_maximum(size_t *maximum_value, size_t value)
{
#ifdef USE_ATOMIC_MAX
- size_t prev_value = *maximum_value;
- while (prev_value < value) {
- if (atomic_cas_z(maximum_value, prev_value, value) != prev_value) {
- break;
- }
- }
+ atomic_fetch_and_update_max_z(maximum_value, value);
#else
*maximum_value = value > *maximum_value ? value : *maximum_value;
#endif
diff --git a/intern/libmv/ChangeLog b/intern/libmv/ChangeLog
index 45be9c25afa..81096dd90c9 100644
--- a/intern/libmv/ChangeLog
+++ b/intern/libmv/ChangeLog
@@ -1,3 +1,156 @@
+commit efd7a93317e0278b99e66785f667823e451daef1
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Tue May 9 10:16:42 2017 +0200
+
+ Fix strict compiler warnings, unused variables
+
+commit 8efd47e13dfdd3f7209bc96f26d0b13127dd6376
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed Dec 14 10:44:57 2016 +0100
+
+ Fix T50243: libmv_panography_test is broken
+
+ There was fully wrong logic in comparison: was actually accessing memory
+ past the array boundary. Run test manually and the figure seems correct
+ to me now.
+
+ Spotted by @LazyDodo, thanks!
+
+commit 6dfb9cd1bd14669d84be789000ce234747fb00ff
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Jul 14 11:49:38 2016 +0200
+
+ Fix some strict compiler warnings
+
+ One of them was a real bug!
+
+commit f61adaecf7b29ebe6677be0e1c825f0a8d475e4b
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 31 11:22:34 2017 +0200
+
+ Enable explicit schur complement for BA step
+
+ This is something we do in Blender and only reason it was not
+ enabled for standalone Libmv is because we did not have fresh
+ enough version of Ceres bundled.
+
+commit fc5d3a1d4880c6658aff693c1c1e8c10c96ce1a7
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed Nov 2 15:32:11 2016 +0100
+
+ Update tests to make tests pass after recent Ceres update
+
+ Just a precision issue, difference is around 1e-7. Should be fine to
+ simply update expected value.
+
+commit e1ac9f6124110c1a90d8e417bea47acfcbdcca42
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 31 10:54:48 2017 +0200
+
+ Update Ceres to latest release 1.12.0
+
+commit ac1571352b4962f110929b963f8616d7310ceea5
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri Apr 7 17:10:44 2017 +0200
+
+ Fix crash of keyframe selection on 32bit linux
+
+commit 5f8df3da965686df39a6ae5c9f17482075017bf4
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Tue Jan 19 14:00:53 2016 +0500
+
+ Solve some strict warnings in tests
+
+commit 8ea3a5d752a9ce3337ab7643897472a4d33747f1
+Author: Brecht Van Lommel <brechtvanlommel@gmail.com>
+Date: Sat Feb 18 23:52:31 2017 +0100
+
+ Fix a few compiler warnings with macOS / clang.
+
+commit ffbe81461770e70736e80b8cab8e6eb1f8b27160
+Author: Mike Erwin <significant.bit@gmail.com>
+Date: Wed May 31 10:43:08 2017 +0200
+
+ Fix comparison of identicals
+
+ Some of these check that dimensions match before running code that
+ assumes they do match.
+
+ Found with PVS-Studio T48917.
+
+commit 206c01999cde16c1c6c43a8e13ffa86020821d98
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 31 10:39:16 2017 +0200
+
+ Add basic track masking API in place
+
+ This brings back ability to mask non-interesting parts of
+ specific track (the feature got lost with new auto-track API).
+
+ Added it back by extending frame accessor class. This isn't really
+ a frame thing, but we don't have other type of accessor here.
+
+ Surely, we can use old-style API here and pass mask via region
+ tracker options for this particular case, but then it becomes much
+ less obvious how real auto-tracker will access this mask with old
+ style API.
+
+ So seems we do need an accessor for such data, just matter of
+ finding better place than frame accessor.
+
+commit faa069cb826892780356477cc10602390fecf06b
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 31 10:36:26 2017 +0200
+
+ Tests: Tweak epsilon to avoid what looks a false-positive failure
+
+commit 7c84e45c1d330871477ba3516f57178e5b9d101f
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 31 10:15:43 2017 +0200
+
+ CMake: Fix mistake in closing branch
+
+commit cb769a0d319a8c95948153d78a4c3378a0142ece
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Jul 21 12:52:33 2016 +0200
+
+ Set of fixes for MSVC215
+
+ - Move GLOG/GFLAGS defines to a more global scope,
+ this way ANY of our own libraries will use proper
+ declspec.
+
+ - Compile png/zlib/openexif on Windows as well since
+ those are required for a correct linking.
+
+commit bb95c8654fd2cea72d66ed04cd825cc3712ea804
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed Jul 20 18:14:46 2016 +0200
+
+ Disable unexisting Ceres option
+
+ Explicit Schur complement requires having
+ newer Ceres than we currently have bundled.
+
+commit a2e12c959ef32cc9382244d1581992c2f7aa9c09
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed Jul 20 18:04:57 2016 +0200
+
+ Various fixes for MSVC
+
+ - Update Eigen to 3.2.7 since this brings crucial
+ fixes for MSVC 2015.
+
+ - Switch to STATIC build by default.
+
+ There are issues building current sources as dynamic
+ libraries with MSVC2015 and additionally building
+ dynamic Ceres is not recommended anyway, so let's
+ not do this for the time being.
+
+ If anyone finds a way to make this all working --
+ it'llsurely be a welcome addition.
+
commit 7a676106720fb126a27ff010abdd8bb65d7e0d9a
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Jan 4 18:30:12 2016 +0500
@@ -365,239 +518,3 @@ Date: Thu May 8 15:50:26 2014 +0200
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D516
-
-commit 4405dff60ea08d454b64da1a7c0595d9328cf8a3
-Author: Keir Mierle <mierle@gmail.com>
-Date: Thu May 8 15:38:14 2014 +0200
-
- Add public SetMarkers to AutoTrack
-
- Reviewers: sergey
-
- Reviewed By: sergey
-
- Differential Revision: https://developer.blender.org/D515
-
-commit c90837f6db276a3b1f610eaad509155f6a43b24f
-Author: Keir Mierle <mierle@gmail.com>
-Date: Thu May 8 15:17:48 2014 +0200
-
- Make autotrack skeleton compile
-
- Reviewers: sergey
-
- Reviewed By: sergey
-
- Differential Revision: https://developer.blender.org/D514
-
-commit be01baa2e82e36f63e548f073157e68d2ff870c0
-Author: Keir Mierle <mierle@gmail.com>
-Date: Wed May 7 18:48:55 2014 +0200
-
- Add preliminary TrackMarkerToFrame in autotrack
-
- Reviewers: sergey
-
- Reviewed By: sergey
-
- Differential Revision: https://developer.blender.org/D509
-
-commit 0cab028d591b3d08672ca86eb6c6e4ac1aacf1d0
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed May 7 17:59:11 2014 +0200
-
- Remove assert from ArrayND Resize
-
- That assert broke initialization of arrays which doesn't
- own the data since constructor uses Resize to set shape
- and strides.
-
- Strides are still to be fixed, but that's for later.
-
-commit 64f9c118029a9351e9023e96527c120e1d724d5b
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed May 7 17:42:21 2014 +0200
-
- Fix ArrayND freeing the data it doesn't own
-
- Can't really guarantee it works fully correct now,
- but at least this check is needed anyway and compilation
- works just fine.
-
- Reviewers: keir
-
- Reviewed By: keir
-
- Differential Revision: https://developer.blender.org/D508
-
-commit 0618f1c8e88dfc738cdde55784da80b889905e7c
-Author: Keir Mierle <mierle@gmail.com>
-Date: Wed May 7 12:03:32 2014 +0200
-
- Minor changes
-
- Reviewers: sergey
-
- Reviewed By: sergey
-
- Differential Revision: https://developer.blender.org/D505
-
-commit 5c34335e1bb90c4ed701ee830c718ed4e20dbffa
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed May 7 11:12:23 2014 +0200
-
- Fix compilation error in frame accessor
-
- - int64 is not a standard type, we've got int64_t defined in
- std int. We also have an msvc port of this header, so should
- not be an issue.
-
- - Fixed inconsistency in usage of CacheKey and Key, used Key.
-
- - Some functions weren't marked as virtual.
-
- Additional change: added self to authors.
-
- Reviewers: keir
-
- Reviewed By: keir
-
- Differential Revision: https://developer.blender.org/D504
-
-commit 06bc207614e262cd688e2c3ed820ade7c77bdb66
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 6 22:30:59 2014 +0200
-
- Start new Tracks implementation
-
- This adds the new Tracks implementation, as well as a
- trivial test to show it compiles.
-
- Reviewers: sergey
-
- Reviewed By: sergey
-
- Differential Revision: https://developer.blender.org/D502
-
-commit 25ce061e6da69881460ba7718bb0d660a2380a02
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 6 19:10:51 2014 +0200
-
- Add Reconstruction class for new API
-
- This starts the new Reconstruction class (with support for e.g. planes). This
- also starts the new namespace "mv" which will eventually have all the symbols
- we wish to export.
-
- Reviewers: sergey
-
- Reviewed By: sergey
-
- Differential Revision: https://developer.blender.org/D501
-
-commit 0a6af3e29016048978aea607673340500e050339
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 6 17:52:53 2014 +0200
-
- Add a new Tracks implementation
-
- Reviewers: sergey
-
- Reviewed By: sergey
-
- Differential Revision: https://developer.blender.org/D500
-
-commit 887b68d29c2b198f4939f9ab5153881aa2c1806e
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 6 17:01:39 2014 +0200
-
- Initial commit of unfinished AutoTrack API
-
- This starts the creating the new AutoTrack API. The new API will
- make it possible for libmv to do full autotracking, including
- predictive tracking and also support multiple motion models (3D
- planes etc).
-
- The first goal (not in this patch) is to convert Blender to use
- the new API without adding any new functionality.
-
- Note: This does not add any of the API to the build system!
- It likely does not compile.
-
- Reviewers: sergey
-
- Reviewed By: sergey
-
- Differential Revision: https://developer.blender.org/D499
-
-commit 08cc227d431d257d27f300fbb8e6991e663302da
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue May 6 13:09:22 2014 +0200
-
- Fix homography test failure
-
- It was caused by assuming that reconstructed homography matrix
- should look exactly the same as the matrix used to generate a
- test case.
-
- It's not actually valid assumption because different-looking
- matrices could correspond to the same exact transform.
-
- In this change we make it so actual "re-projected" vectors
- are being checked, not the values in matrix. This makes it
- more predictable verification.
-
- Reviewers: keir
-
- Reviewed By: keir
-
- Differential Revision: https://developer.blender.org/D488
-
-commit 0b7d83dc9627447dc7df64d7e3a468aefe9ddc13
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed Apr 23 19:14:55 2014 +0600
-
- Fix compilation on OSX after previous commit
-
- EXPECT_EQ wasn't defined in the scope.
-
-commit d14049e00dabf8fdf49056779f0a3718fbb39e8f
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed Apr 23 15:08:16 2014 +0600
-
- Move aligned malloc implementation into own file
-
- It was rather stupid having it in brute region tracker,
- now it is in own file in base library (which was also
- added in this commit, before this it consist of header
- files only).
-
- Reviewers: keir
-
- Reviewed By: keir
-
- Differential Revision: https://developer.blender.org/D479
-
-commit 0ddf3851bfcb8de43660b119a25a77a25674200d
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Mon Apr 21 14:14:03 2014 +0600
-
- Optimization of PearsonProductMomentCorrelation
-
- Pass the arrays by reference rather than by value,
- should give some percent of speedup.
-
- Also don't pass the dimensions to the function but
- get them from the images themselves.
-
- Hopefully this will give some %% of tracker speedup.
-
-commit f68fdbe5896a6c5bd8b500caeec61b876c5e44c6
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Mon Apr 21 14:10:43 2014 +0600
-
- Fix wrong assert in ResizeImage()
-
- The assert didn't make any sense because ComputeBoundingBox()
- is intended to return bounding box in the following way:
- (xmin, xmax, ymin, ymax).
diff --git a/intern/libmv/bundle.sh b/intern/libmv/bundle.sh
index 27e012f665f..d155d050782 100755
--- a/intern/libmv/bundle.sh
+++ b/intern/libmv/bundle.sh
@@ -120,6 +120,7 @@ if(WITH_LIBMV)
add_definitions(\${GFLAGS_DEFINES})
add_definitions(\${GLOG_DEFINES})
add_definitions(\${CERES_DEFINES})
+ add_definitions(-DLIBMV_GFLAGS_NAMESPACE=\${GFLAGS_NAMESPACE})
list(APPEND INC
\${GFLAGS_INCLUDE_DIRS}
diff --git a/intern/libmv/intern/track_region.cc b/intern/libmv/intern/track_region.cc
index d395b6457d7..8989897e09f 100644
--- a/intern/libmv/intern/track_region.cc
+++ b/intern/libmv/intern/track_region.cc
@@ -36,7 +36,7 @@
/* define this to generate PNG images with content of search areas
on every itteration of tracking */
-#define DUMP_ALWAYS
+#undef DUMP_ALWAYS
using libmv::FloatImage;
using libmv::TrackRegionOptions;
diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h
index 0fe5469a4d4..b5680890eb8 100644
--- a/intern/memutil/MEM_CacheLimiterC-Api.h
+++ b/intern/memutil/MEM_CacheLimiterC-Api.h
@@ -61,8 +61,8 @@ bool MEM_CacheLimiter_is_disabled(void);
* Create new MEM_CacheLimiter object
* managed objects are destructed with the data_destructor
*
- * @param data_destructor
- * @return A new MEM_CacheLimter object
+ * \param data_destructor
+ * \return A new MEM_CacheLimter object
*/
MEM_CacheLimiterC *new_MEM_CacheLimiter(MEM_CacheLimiter_Destruct_Func data_destructor,
@@ -73,7 +73,7 @@ MEM_CacheLimiterC *new_MEM_CacheLimiter(MEM_CacheLimiter_Destruct_Func data_dest
*
* Frees the memory of the CacheLimiter but does not touch managed objects!
*
- * @param This "This" pointer
+ * \param This "This" pointer
*/
void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This);
@@ -81,8 +81,8 @@ void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This);
/**
* Manage object
*
- * @param This "This" pointer, data data object to manage
- * @return CacheLimiterHandle to ref, unref, touch the managed object
+ * \param This "This" pointer, data data object to manage
+ * \return CacheLimiterHandle to ref, unref, touch the managed object
*/
MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC *This, void *data);
@@ -90,7 +90,7 @@ MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC *This, void *
/**
* Free objects until memory constraints are satisfied
*
- * @param This "This" pointer
+ * \param This "This" pointer
*/
void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC *This);
@@ -99,7 +99,7 @@ void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC *This);
* Unmanage object previously inserted object.
* Does _not_ delete managed object!
*
- * @param This "This" pointer, handle of object
+ * \param handle of object
*/
void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC *handle);
@@ -108,7 +108,7 @@ void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC *handle);
/**
* Raise priority of object (put it at the tail of the deletion chain)
*
- * @param handle of object
+ * \param handle of object
*/
void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC *handle);
@@ -117,7 +117,7 @@ void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC *handle);
* Increment reference counter. Objects with reference counter != 0 are _not_
* deleted.
*
- * @param handle of object
+ * \param handle of object
*/
void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC *handle);
@@ -126,7 +126,7 @@ void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC *handle);
* Decrement reference counter. Objects with reference counter != 0 are _not_
* deleted.
*
- * @param handle of object
+ * \param handle of object
*/
void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle);
@@ -134,7 +134,7 @@ void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle);
/**
* Get reference counter.
*
- * @param handle of object
+ * \param handle of object
*/
int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle);
@@ -142,7 +142,7 @@ int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle);
/**
* Get pointer to managed object
*
- * @param handle of object
+ * \param handle of object
*/
void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle);
diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c
index 0342ae0146f..c52494a49f8 100644
--- a/intern/mikktspace/mikktspace.c
+++ b/intern/mikktspace/mikktspace.c
@@ -39,17 +39,23 @@
#define INTERNAL_RND_SORT_SEED 39871946
+#ifdef _MSC_VER
+# define MIKK_INLINE static __forceinline
+#else
+# define MIKK_INLINE static inline __attribute__((always_inline)) __attribute__((unused))
+#endif
+
// internal structure
typedef struct {
float x, y, z;
} SVec3;
-static tbool veq( const SVec3 v1, const SVec3 v2 )
+MIKK_INLINE tbool veq( const SVec3 v1, const SVec3 v2 )
{
return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z);
}
-static SVec3 vadd( const SVec3 v1, const SVec3 v2 )
+MIKK_INLINE SVec3 vadd( const SVec3 v1, const SVec3 v2 )
{
SVec3 vRes;
@@ -61,7 +67,7 @@ static SVec3 vadd( const SVec3 v1, const SVec3 v2 )
}
-static SVec3 vsub( const SVec3 v1, const SVec3 v2 )
+MIKK_INLINE SVec3 vsub( const SVec3 v1, const SVec3 v2 )
{
SVec3 vRes;
@@ -72,7 +78,7 @@ static SVec3 vsub( const SVec3 v1, const SVec3 v2 )
return vRes;
}
-static SVec3 vscale(const float fS, const SVec3 v)
+MIKK_INLINE SVec3 vscale(const float fS, const SVec3 v)
{
SVec3 vRes;
@@ -83,39 +89,54 @@ static SVec3 vscale(const float fS, const SVec3 v)
return vRes;
}
-static float LengthSquared( const SVec3 v )
+MIKK_INLINE float LengthSquared( const SVec3 v )
{
return v.x*v.x + v.y*v.y + v.z*v.z;
}
-static float Length( const SVec3 v )
+MIKK_INLINE float Length( const SVec3 v )
{
return sqrtf(LengthSquared(v));
}
-static SVec3 Normalize( const SVec3 v )
+#if 0 // UNUSED
+MIKK_INLINE SVec3 Normalize( const SVec3 v )
{
- return vscale(1 / Length(v), v);
+ return vscale(1.0f / Length(v), v);
}
+#endif
-static float vdot( const SVec3 v1, const SVec3 v2)
+MIKK_INLINE SVec3 NormalizeSafe( const SVec3 v )
+{
+ const float len = Length(v);
+ if (len != 0.0f) {
+ return vscale(1.0f / len, v);
+ }
+ else
+ {
+ return v;
+ }
+}
+
+MIKK_INLINE float vdot( const SVec3 v1, const SVec3 v2)
{
return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
}
-static tbool NotZero(const float fX)
+MIKK_INLINE tbool NotZero(const float fX)
{
// could possibly use FLT_EPSILON instead
return fabsf(fX) > FLT_MIN;
}
-static tbool VNotZero(const SVec3 v)
+#if 0 // UNUSED
+MIKK_INLINE tbool VNotZero(const SVec3 v)
{
// might change this to an epsilon based test
return NotZero(v.x) || NotZero(v.y) || NotZero(v.z);
}
-
+#endif
typedef struct {
@@ -169,13 +190,13 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con
const int iNrActiveGroups, const int piTriListIn[], const float fThresCos,
const SMikkTSpaceContext * pContext);
-static int MakeIndex(const int iFace, const int iVert)
+MIKK_INLINE int MakeIndex(const int iFace, const int iVert)
{
assert(iVert>=0 && iVert<4 && iFace>=0);
return (iFace<<2) | (iVert&0x3);
}
-static void IndexToData(int * piFace, int * piVert, const int iIndexIn)
+MIKK_INLINE void IndexToData(int * piFace, int * piVert, const int iIndexIn)
{
piVert[0] = iIndexIn&0x3;
piFace[0] = iIndexIn>>2;
@@ -202,8 +223,8 @@ static STSpace AvgTSpace(const STSpace * pTS0, const STSpace * pTS1)
ts_res.fMagT = 0.5f*(pTS0->fMagT+pTS1->fMagT);
ts_res.vOs = vadd(pTS0->vOs,pTS1->vOs);
ts_res.vOt = vadd(pTS0->vOt,pTS1->vOt);
- if ( VNotZero(ts_res.vOs) ) ts_res.vOs = Normalize(ts_res.vOs);
- if ( VNotZero(ts_res.vOt) ) ts_res.vOt = Normalize(ts_res.vOt);
+ ts_res.vOs = NormalizeSafe(ts_res.vOs);
+ ts_res.vOt = NormalizeSafe(ts_res.vOt);
}
return ts_res;
@@ -211,9 +232,9 @@ static STSpace AvgTSpace(const STSpace * pTS0, const STSpace * pTS1)
-static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index);
-static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index);
-static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index);
+MIKK_INLINE SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index);
+MIKK_INLINE SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index);
+MIKK_INLINE SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index);
// degen triangles
@@ -238,7 +259,7 @@ tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThre
int iNrActiveGroups = 0, index = 0;
const int iNrFaces = pContext->m_pInterface->m_getNumFaces(pContext);
tbool bRes = TFALSE;
- const float fThresCos = (float) cos((fAngularThreshold*(float)M_PI)/180.0f);
+ const float fThresCos = cosf((fAngularThreshold*(float)M_PI)/180.0f);
// verify all call-backs have been set
if ( pContext->m_pInterface->m_getNumFaces==NULL ||
@@ -258,7 +279,7 @@ tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThre
if (iNrTrianglesIn<=0) return TFALSE;
// allocate memory for an index list
- piTriListIn = (int *) malloc(sizeof(int)*3*iNrTrianglesIn);
+ piTriListIn = (int *) malloc(sizeof(int[3])*iNrTrianglesIn);
pTriInfos = (STriInfo *) malloc(sizeof(STriInfo)*iNrTrianglesIn);
if (piTriListIn==NULL || pTriInfos==NULL)
{
@@ -311,7 +332,7 @@ tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThre
// based on the 4 rules, identify groups based on connectivity
iNrMaxGroups = iNrTrianglesIn*3;
pGroups = (SGroup *) malloc(sizeof(SGroup)*iNrMaxGroups);
- piGroupTrianglesBuffer = (int *) malloc(sizeof(int)*iNrTrianglesIn*3);
+ piGroupTrianglesBuffer = (int *) malloc(sizeof(int[3])*iNrTrianglesIn);
if (pGroups==NULL || piGroupTrianglesBuffer==NULL)
{
if (pGroups!=NULL) free(pGroups);
@@ -427,6 +448,7 @@ typedef struct {
} STmpVert;
static const int g_iCells = 2048;
+static const float g_iCells_fl = 2048.0f;
#ifdef _MSC_VER
# define NOINLINE __declspec(noinline)
@@ -439,7 +461,7 @@ static const int g_iCells = 2048;
// results for the same effective input value fVal.
static NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal)
{
- const float fIndex = g_iCells * ((fVal-fMin)/(fMax-fMin));
+ const float fIndex = g_iCells_fl * ((fVal-fMin)/(fMax-fMin));
const int iIndex = (int)fIndex;
return iIndex < g_iCells ? (iIndex >= 0 ? iIndex : 0) : (g_iCells - 1);
}
@@ -488,7 +510,7 @@ static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SM
}
// make allocations
- piHashTable = (int *) malloc(sizeof(int)*iNrTrianglesIn*3);
+ piHashTable = (int *) malloc(sizeof(int[3])*iNrTrianglesIn);
piHashCount = (int *) malloc(sizeof(int)*g_iCells);
piHashOffsets = (int *) malloc(sizeof(int)*g_iCells);
piHashCount2 = (int *) malloc(sizeof(int)*g_iCells);
@@ -544,7 +566,7 @@ static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SM
if (iMaxCount<piHashCount[k])
iMaxCount=piHashCount[k];
pTmpVert = (STmpVert *) malloc(sizeof(STmpVert)*iMaxCount);
-
+
// complete the merge
for (k=0; k<g_iCells; k++)
@@ -880,7 +902,7 @@ static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_
return iTSpacesOffs;
}
-static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index)
+MIKK_INLINE SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index)
{
int iF, iI;
SVec3 res; float pos[3];
@@ -890,7 +912,7 @@ static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index)
return res;
}
-static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index)
+MIKK_INLINE SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index)
{
int iF, iI;
SVec3 res; float norm[3];
@@ -900,7 +922,7 @@ static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index)
return res;
}
-static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index)
+MIKK_INLINE SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index)
{
int iF, iI;
SVec3 res; float texc[2];
@@ -1048,7 +1070,7 @@ static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMi
// match up edge pairs
{
- SEdge * pEdges = (SEdge *) malloc(sizeof(SEdge)*iNrTrianglesIn*3);
+ SEdge * pEdges = (SEdge *) malloc(sizeof(SEdge[3])*iNrTrianglesIn);
if (pEdges==NULL)
BuildNeighborsSlow(pTriInfos, piTriListIn, iNrTrianglesIn);
else
@@ -1064,7 +1086,7 @@ static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMi
/////////////////////////////////////////////////////////////////////////////////////////////////////
static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], const int iMyTriIndex, SGroup * pGroup);
-static void AddTriToGroup(SGroup * pGroup, const int iTriIndex);
+MIKK_INLINE void AddTriToGroup(SGroup * pGroup, const int iTriIndex);
static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn)
{
@@ -1130,7 +1152,7 @@ static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupT
return iNrActiveGroups;
}
-static void AddTriToGroup(SGroup * pGroup, const int iTriIndex)
+MIKK_INLINE void AddTriToGroup(SGroup * pGroup, const int iTriIndex)
{
pGroup->pFaceIndices[pGroup->iNrFaces] = iTriIndex;
++pGroup->iNrFaces;
@@ -1247,10 +1269,8 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con
n = GetNormal(pContext, iVertIndex);
// project
- vOs = vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n));
- vOt = vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n));
- if ( VNotZero(vOs) ) vOs = Normalize(vOs);
- if ( VNotZero(vOt) ) vOt = Normalize(vOt);
+ vOs = NormalizeSafe(vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n)));
+ vOt = NormalizeSafe(vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n)));
// original face number
iOF_1 = pTriInfos[f].iOrgFaceNumber;
@@ -1262,10 +1282,8 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con
const int iOF_2 = pTriInfos[t].iOrgFaceNumber;
// project
- SVec3 vOs2 = vsub(pTriInfos[t].vOs, vscale(vdot(n,pTriInfos[t].vOs), n));
- SVec3 vOt2 = vsub(pTriInfos[t].vOt, vscale(vdot(n,pTriInfos[t].vOt), n));
- if ( VNotZero(vOs2) ) vOs2 = Normalize(vOs2);
- if ( VNotZero(vOt2) ) vOt2 = Normalize(vOt2);
+ SVec3 vOs2 = NormalizeSafe(vsub(pTriInfos[t].vOs, vscale(vdot(n,pTriInfos[t].vOs), n)));
+ SVec3 vOt2 = NormalizeSafe(vsub(pTriInfos[t].vOt, vscale(vdot(n,pTriInfos[t].vOt), n)));
{
const tbool bAny = ( (pTriInfos[f].iFlag | pTriInfos[t].iFlag) & GROUP_WITH_ANY )!=0 ? TTRUE : TFALSE;
@@ -1321,7 +1339,7 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con
}
pUniSubGroups[iUniqueSubGroups].iNrFaces = iMembers;
pUniSubGroups[iUniqueSubGroups].pTriMembers = pIndices;
- memcpy(pIndices, tmp_group.pTriMembers, iMembers*sizeof(int));
+ memcpy(pIndices, tmp_group.pTriMembers, sizeof(int)*iMembers);
pSubGroupTspace[iUniqueSubGroups] =
EvalTspace(tmp_group.pTriMembers, iMembers, piTriListIn, pTriInfos, pContext, pGroup->iVertexRepresentitive);
++iUniqueSubGroups;
@@ -1392,10 +1410,8 @@ static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriL
// project
index = piTriListIn[3*f+i];
n = GetNormal(pContext, index);
- vOs = vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n));
- vOt = vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n));
- if ( VNotZero(vOs) ) vOs = Normalize(vOs);
- if ( VNotZero(vOt) ) vOt = Normalize(vOt);
+ vOs = NormalizeSafe(vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n)));
+ vOt = NormalizeSafe(vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n)));
i2 = piTriListIn[3*f + (i<2?(i+1):0)];
i1 = piTriListIn[3*f + i];
@@ -1408,8 +1424,8 @@ static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriL
v2 = vsub(p2,p1);
// project
- v1 = vsub(v1, vscale(vdot(n,v1),n)); if ( VNotZero(v1) ) v1 = Normalize(v1);
- v2 = vsub(v2, vscale(vdot(n,v2),n)); if ( VNotZero(v2) ) v2 = Normalize(v2);
+ v1 = NormalizeSafe(vsub(v1, vscale(vdot(n,v1),n)));
+ v2 = NormalizeSafe(vsub(v2, vscale(vdot(n,v2),n)));
// weight contribution by the angle
// between the two edge vectors
@@ -1427,8 +1443,8 @@ static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriL
}
// normalize
- if ( VNotZero(res.vOs) ) res.vOs = Normalize(res.vOs);
- if ( VNotZero(res.vOt) ) res.vOt = Normalize(res.vOt);
+ res.vOs = NormalizeSafe(res.vOs);
+ res.vOt = NormalizeSafe(res.vOt);
if (fAngleSum>0)
{
res.fMagS /= fAngleSum;
@@ -1464,7 +1480,7 @@ static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSee
iL=iLeft; iR=iRight;
n = (iR-iL)+1;
assert(n>=0);
- index = (int) (uSeed%n);
+ index = (int) (uSeed%(unsigned int)n);
iMid=pSortBuffer[index + iL];
@@ -1661,6 +1677,20 @@ static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int
}
return;
}
+ else if(iElems < 16) {
+ int i, j;
+ for (i = 0; i < iElems - 1; i++) {
+ for (j = 0; j < iElems - i - 1; j++) {
+ int index = iLeft + j;
+ if (pSortBuffer[index].array[channel] > pSortBuffer[index + 1].array[channel]) {
+ sTmp = pSortBuffer[index];
+ pSortBuffer[index] = pSortBuffer[index + 1];
+ pSortBuffer[index + 1] = sTmp;
+ }
+ }
+ }
+ return;
+ }
// Random
t=uSeed&31;
@@ -1672,7 +1702,7 @@ static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int
iR = iRight;
n = (iR-iL)+1;
assert(n>=0);
- index = (int) (uSeed%n);
+ index = (int) (uSeed%(unsigned int)n);
iMid=pSortBuffer[index + iL].array[channel];
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index 52ce98fe74b..0a55a432cc6 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <GL/glew.h>
+#include <opensubdiv/version.h>
#include <opensubdiv/osd/glMesh.h>
/* CPU Backend */
@@ -74,6 +75,16 @@
#include "MEM_guardedalloc.h"
+#include <string>
+#include <vector>
+
+using std::string;
+using std::vector;
+
+#define STRINGIFY_ARG(x) "" #x
+#define STRINGIFY_APPEND(a, b) "" a #b
+#define STRINGIFY(x) STRINGIFY_APPEND("", x)
+
/* **************** Types declaration **************** */
using OpenSubdiv::Osd::GLMeshInterface;
@@ -146,6 +157,38 @@ typedef Mesh<GLVertexBuffer,
namespace {
+#if !defined(OPENSUBDIV_VERSION_NUMBER) && !defined(OPENSUBDIV_VERSION_MINOR)
+void stringSplit(vector<string>* tokens,
+ const string& str,
+ const string& separators,
+ bool skip_empty) {
+ size_t token_start = 0, token_length = 0;
+ for (size_t i = 0; i < str.length(); ++i) {
+ const char ch = str[i];
+ if (separators.find(ch) == string::npos) {
+ /* Append non-separator char to a token. */
+ ++token_length;
+ } else {
+ /* Append current token to the list (if any). */
+ if (token_length > 0 || !skip_empty) {
+ string token = str.substr(token_start, token_length);
+ tokens->push_back(token);
+ }
+ /* Re-set token pointers, */
+ token_start = i + 1;
+ token_length = 0;
+ }
+ }
+ /* Append token which might be at the end of the string. */
+ if ((token_length != 0) ||
+ (!skip_empty && token_start > 0 &&
+ separators.find(str[token_start-1]) != string::npos)) {
+ string token = str.substr(token_start, token_length);
+ tokens->push_back(token);
+ }
+}
+#endif
+
struct FVarVertex {
float u, v;
void Clear() {
@@ -381,3 +424,30 @@ int openSubdiv_supportGPUDisplay(void)
(GLEW_ARB_texture_buffer_object || GLEW_EXT_texture_buffer_object)));
/* also ARB_explicit_attrib_location? */
}
+
+int openSubdiv_getVersionHex(void)
+{
+#if defined(OPENSUBDIV_VERSION_NUMBER)
+ return OPENSUBDIV_VERSION_NUMBER;
+#elif defined(OPENSUBDIV_VERSION_MAJOR)
+ return OPENSUBDIV_VERSION_MAJOR * 10000 +
+ OPENSUBDIV_VERSION_MINOR * 100 +
+ OPENSUBDIV_VERSION_PATCH;
+#elif defined(OPENSUBDIV_VERSION)
+ const char* version = STRINGIFY(OPENSUBDIV_VERSION);
+ if (version[0] == 'v') {
+ version += 1;
+ }
+ int major = 0, minor = 0, patch = 0;
+ vector<string> tokens;
+ stringSplit(&tokens, version, "_", true);
+ if (tokens.size() == 3) {
+ major = atoi(tokens[0].c_str());
+ minor = atoi(tokens[1].c_str());
+ patch = atoi(tokens[2].c_str());
+ }
+ return major * 10000 + minor * 100 + patch;
+#else
+ return 0;
+#endif
+}
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index c3a194813e6..281bd3f010d 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -152,6 +152,8 @@ void openSubdiv_init(bool gpu_legacy_support);
void openSubdiv_cleanup(void);
bool openSubdiv_gpu_legacy_support(void);
+int openSubdiv_getVersionHex(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/make.bat b/make.bat
index 988cb5f4c68..febe15f2ced 100644
--- a/make.bat
+++ b/make.bat
@@ -5,6 +5,7 @@ setlocal EnableDelayedExpansion
setlocal ENABLEEXTENSIONS
set BLENDER_DIR=%~dp0
set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =%
+for %%X in (svn.exe) do (set HAS_SVN=%%~$PATH:X)
if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
goto EOF
@@ -17,6 +18,9 @@ set BUILD_CMAKE_ARGS=
set BUILD_ARCH=
set BUILD_VS_VER=
set BUILD_VS_YEAR=
+set BUILD_VS_LIBDIRPOST=
+set BUILD_VS_LIBDIR=
+set BUILD_VS_SVNDIR=
set BUILD_NGE=
set KEY_NAME=
set MSBUILD_PLATFORM=
@@ -67,25 +71,28 @@ if NOT "%1" == "" (
-C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake"
) else if "%1" == "release" (
set TARGET=Release
- ) else if "%1" == "x86" (
+ ) else if "%1" == "x86" (
set BUILD_ARCH=x86
- ) else if "%1" == "x64" (
+ ) else if "%1" == "x64" (
set BUILD_ARCH=x64
- ) else if "%1" == "2017" (
+ ) else if "%1" == "2017" (
set BUILD_VS_VER=15
set BUILD_VS_YEAR=2017
- ) else if "%1" == "2015" (
+ set BUILD_VS_LIBDIRPOST=vc14
+ ) else if "%1" == "2015" (
set BUILD_VS_VER=14
set BUILD_VS_YEAR=2015
- ) else if "%1" == "2013" (
+ set BUILD_VS_LIBDIRPOST=vc14
+ ) else if "%1" == "2013" (
set BUILD_VS_VER=12
set BUILD_VS_YEAR=2013
- ) else if "%1" == "packagename" (
+ set BUILD_VS_LIBDIRPOST=vc12
+ ) else if "%1" == "packagename" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
shift /1
- ) else if "%1" == "nobuild" (
+ ) else if "%1" == "nobuild" (
set NOBUILD=1
- ) else if "%1" == "showhash" (
+ ) else if "%1" == "showhash" (
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i
cd release/datafiles/locale
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i
@@ -122,31 +129,32 @@ if "%BUILD_ARCH%"=="" (
set BUILD_ARCH=x86
)
) else if "%BUILD_ARCH%"=="x64" (
- set WINDOWS_ARCH= Win64
- ) else if "%BUILD_ARCH%"=="x86" (
- set WINDOWS_ARCH=
- )
+ set WINDOWS_ARCH= Win64
+) else if "%BUILD_ARCH%"=="x86" (
+ set WINDOWS_ARCH=
+)
if "%BUILD_VS_VER%"=="" (
set BUILD_VS_VER=12
set BUILD_VS_YEAR=2013
+ set BUILD_VS_LIBDIRPOST=vc12
)
if "%BUILD_ARCH%"=="x64" (
set MSBUILD_PLATFORM=x64
- ) else if "%BUILD_ARCH%"=="x86" (
- set MSBUILD_PLATFORM=win32
+) else if "%BUILD_ARCH%"=="x86" (
+ set MSBUILD_PLATFORM=win32
)
if "%target%"=="Release" (
- rem for vc12 check for both cuda 7.5 and 8
- if "%CUDA_PATH%"=="" (
- echo Cuda Not found, aborting!
- goto EOF
- )
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
+ rem for vc12 check for both cuda 7.5 and 8
+ if "%CUDA_PATH%"=="" (
+ echo Cuda Not found, aborting!
+ goto EOF
+ )
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
+ -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
)
:DetectMSVC
@@ -183,8 +191,9 @@ if %ERRORLEVEL% NEQ 0 (
echo Visual Studio 2013 not found, trying Visual Studio 2015.
set BUILD_VS_VER=14
set BUILD_VS_YEAR=2015
+ set BUILD_VS_LIBDIRPOST=vc14
goto DetectMSVC
- ) else (
+ ) else (
echo Error: "MSBuild" command not in the PATH.
echo You must have MSVC installed and run this from the "Developer Command Prompt"
echo ^(available from Visual Studio's Start menu entry^), aborting!
@@ -204,11 +213,36 @@ if %ERRORLEVEL% NEQ 0 (
echo You must have CMake installed and added to your PATH, aborting!
goto EOF
)
-if NOT EXIST %BLENDER_DIR%..\lib\nul (
- echo Error: Path to libraries not found "%BLENDER_DIR%..\lib\"
+
+if "%BUILD_ARCH%"=="x64" (
+ set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
+) else if "%BUILD_ARCH%"=="x86" (
+ set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST%
+)
+set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
+
+if NOT EXIST %BUILD_VS_LIBDIR% (
+ rem libs not found, but svn is on the system
+ if not "%HAS_SVN%"=="" (
+ echo.
+ echo The required external libraries in %BUILD_VS_LIBDIR% are missing
+ echo.
+ set /p GetLibs= "Would you like to download them? (y/n)"
+ if /I "!GetLibs!"=="Y" (
+ echo.
+ echo Downloading %BUILD_VS_SVNDIR% libraries, please wait.
+ echo.
+ svn checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/%BUILD_VS_SVNDIR% %BUILD_VS_LIBDIR%
+ )
+ )
+)
+
+if NOT EXIST %BUILD_VS_LIBDIR% (
+ echo Error: Path to libraries not found "%BUILD_VS_LIBDIR%"
echo This is needed for building, aborting!
goto EOF
)
+
if "%TARGET%"=="" (
echo Error: Convenience target not set
echo This is required for building, aborting!
@@ -297,31 +331,32 @@ echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%\blender
echo.
goto EOF
:HELP
- echo.
- echo Convenience targets
- echo - release ^(identical to the official blender.org builds^)
- echo - full ^(same as release minus the cuda kernels^)
- echo - lite
- echo - headless
- echo - cycles
- echo - bpy
- echo.
- echo Utilities ^(not associated with building^)
- echo - clean ^(Target must be set^)
- echo - update
- echo - nobuild ^(only generate project files^)
- echo - showhash ^(Show git hashes of source tree^)
- echo.
- echo Configuration options
- echo - with_tests ^(enable building unit tests^)
- echo - noge ^(disable building game enginge and player^)
- echo - debug ^(Build an unoptimized debuggable build^)
- echo - packagename [newname] ^(override default cpack package name^)
- echo - buildir [newdir] ^(override default build folder^)
- echo - x86 ^(override host auto-detect and build 32 bit code^)
- echo - x64 ^(override host auto-detect and build 64 bit code^)
- echo - 2013 ^(build with visual studio 2013^)
- echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
- echo.
+ echo.
+ echo Convenience targets
+ echo - release ^(identical to the official blender.org builds^)
+ echo - full ^(same as release minus the cuda kernels^)
+ echo - lite
+ echo - headless
+ echo - cycles
+ echo - bpy
+ echo.
+ echo Utilities ^(not associated with building^)
+ echo - clean ^(Target must be set^)
+ echo - update
+ echo - nobuild ^(only generate project files^)
+ echo - showhash ^(Show git hashes of source tree^)
+ echo.
+ echo Configuration options
+ echo - with_tests ^(enable building unit tests^)
+ echo - noge ^(disable building game enginge and player^)
+ echo - debug ^(Build an unoptimized debuggable build^)
+ echo - packagename [newname] ^(override default cpack package name^)
+ echo - buildir [newdir] ^(override default build folder^)
+ echo - x86 ^(override host auto-detect and build 32 bit code^)
+ echo - x64 ^(override host auto-detect and build 64 bit code^)
+ echo - 2013 ^(build with visual studio 2013^)
+ echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
+ echo - 2017 ^(build with visual studio 2017^) [EXPERIMENTAL]
+ echo.
:EOF
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index d88788fa904..a9c0fd431eb 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -31358,6 +31358,136 @@
fx="-0.78262758"
fy="294.63174"
r="6.6750002" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient33897"
+ id="radialGradient29130"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.6249996,2.7477764e-7,-3.1704883e-7,1.874986,-24.234082,-761.21063)"
+ cx="39.528847"
+ cy="871.2453"
+ fx="39.528847"
+ fy="871.2453"
+ r="2.0000005" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient33897">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop33893" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop33895" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-367"
+ id="linearGradient63713"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="114.94328"
+ y2="60.73848" />
+ <linearGradient
+ id="linearGradient319-367">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-53" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-562" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-367"
+ id="linearGradient63715"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.65625"
+ y1="342.03125"
+ x2="-53.1875"
+ y2="342.0625" />
+ <linearGradient
+ id="linearGradient3043">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3045" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3047" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-367"
+ id="linearGradient63886"
+ x1="149.53125"
+ y1="95.781372"
+ x2="149.40625"
+ y2="103.12512"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3050">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3052" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3054" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient63892"
+ id="linearGradient63894"
+ x1="127.85783"
+ y1="115.03898"
+ x2="137.88899"
+ y2="121.44501"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient63892">
+ <stop
+ style="stop-color:#ba5d00;stop-opacity:1"
+ offset="0"
+ id="stop63888" />
+ <stop
+ id="stop63896"
+ offset="0.5"
+ style="stop-color:#fa9a3a;stop-opacity:1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop63890" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-367"
+ id="linearGradient63719"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="142.72656"
+ y2="127.72736" />
+ <linearGradient
+ id="linearGradient3062">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3064" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3066" />
+ </linearGradient>
</defs>
<sodipodi:namedview
id="base"
@@ -92721,6 +92851,406 @@
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#a8df84;stroke-width:2.93474906;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="path39834-2"
inkscape:connector-curvature="0" />
+ <g
+ id="g1418"
+ transform="matrix(1.6674711,0,0,1.6674711,-416.35106,-776.00982)"
+ style="display:inline;enable-background:new">
+ <path
+ style="fill:none;stroke:#4b2f1e;stroke-width:2.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1374"
+ sodipodi:type="arc"
+ sodipodi:cx="41"
+ sodipodi:cy="873.36212"
+ sodipodi:rx="4.2499995"
+ sodipodi:ry="4.2499995"
+ sodipodi:start="6.1086524"
+ sodipodi:end="7.5049158"
+ sodipodi:open="true"
+ d="m 45.185432,872.62412 c 0.358149,2.03116 -0.793733,4.02628 -2.731847,4.73169" />
+ <path
+ style="fill:none;stroke:#4b2f1e;stroke-width:2.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1376"
+ sodipodi:type="arc"
+ sodipodi:cx="41"
+ sodipodi:cy="873.36212"
+ sodipodi:rx="7"
+ sodipodi:ry="7"
+ sodipodi:start="4.4505896"
+ sodipodi:end="4.9741884"
+ sodipodi:open="true"
+ d="m 39.188267,866.60064 c 1.186888,-0.31802 2.436579,-0.31802 3.623467,0" />
+ <path
+ d="m 47.76148,875.17385 c -0.318025,1.18689 -0.942871,2.26916 -1.811733,3.13802"
+ sodipodi:open="true"
+ sodipodi:end="0.78539816"
+ sodipodi:start="0.26179939"
+ sodipodi:ry="6.9999995"
+ sodipodi:rx="6.9999995"
+ sodipodi:cy="873.36212"
+ sodipodi:cx="41"
+ sodipodi:type="arc"
+ id="path1378"
+ style="fill:none;stroke:#4b2f1e;stroke-width:2.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ d="m 39.546414,877.35581 c -1.938113,-0.70541 -3.089995,-2.70053 -2.731846,-4.73169"
+ sodipodi:open="true"
+ sodipodi:end="3.3161256"
+ sodipodi:start="1.9198622"
+ sodipodi:ry="4.2499995"
+ sodipodi:rx="4.2499995"
+ sodipodi:cy="873.36212"
+ sodipodi:cx="41"
+ sodipodi:type="arc"
+ id="path1380"
+ style="fill:none;stroke:#4b2f1e;stroke-width:2.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ style="fill:none;stroke:#4b2f1e;stroke-width:2.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1382"
+ sodipodi:type="arc"
+ sodipodi:cx="41"
+ sodipodi:cy="873.36212"
+ sodipodi:rx="6.9999995"
+ sodipodi:ry="6.9999995"
+ sodipodi:start="2.3561945"
+ sodipodi:end="2.8797933"
+ sodipodi:open="true"
+ d="m 36.050253,878.31187 c -0.868862,-0.86886 -1.493708,-1.95113 -1.811733,-3.13802" />
+ <rect
+ ry="2.75"
+ rx="2.75"
+ y="870.61212"
+ x="38.25"
+ height="5.5"
+ width="5.5000005"
+ id="rect1384"
+ style="fill:#4b2f1e;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:0;fill-rule:nonzero;stroke:none"
+ id="rect1386"
+ width="20"
+ height="20"
+ x="31"
+ y="862.36212"
+ rx="0"
+ ry="0" />
+ <rect
+ style="fill:#ff7d1f;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect1388"
+ width="4.0000005"
+ height="4"
+ x="39"
+ y="871.36212"
+ rx="2"
+ ry="2" />
+ <rect
+ ry="1.5"
+ rx="1.5000004"
+ y="871.86212"
+ x="39.5"
+ height="3"
+ width="3.0000007"
+ id="rect1390"
+ style="fill:none;stroke:url(#radialGradient29130);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ style="fill:none;stroke:#ffb36b;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1392"
+ sodipodi:type="arc"
+ sodipodi:cx="41"
+ sodipodi:cy="873.36212"
+ sodipodi:rx="4.2499995"
+ sodipodi:ry="4.2499995"
+ sodipodi:start="1.9198622"
+ sodipodi:end="3.3161256"
+ sodipodi:open="true"
+ d="m 39.546414,877.35581 c -1.938113,-0.70541 -3.089995,-2.70053 -2.731846,-4.73169" />
+ <path
+ d="m 36.050253,878.31187 c -0.868862,-0.86886 -1.493708,-1.95113 -1.811733,-3.13802"
+ sodipodi:open="true"
+ sodipodi:end="2.8797933"
+ sodipodi:start="2.3561945"
+ sodipodi:ry="6.9999995"
+ sodipodi:rx="6.9999995"
+ sodipodi:cy="873.36212"
+ sodipodi:cx="41"
+ sodipodi:type="arc"
+ id="path1394"
+ style="fill:none;stroke:#ffb36b;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ d="m 38.875,877.04273 c -0.321653,-0.18571 -0.617575,-0.41278 -0.880204,-0.6754"
+ sodipodi:open="true"
+ sodipodi:end="2.3561945"
+ sodipodi:start="2.0943951"
+ sodipodi:ry="4.2499995"
+ sodipodi:rx="4.2499995"
+ sodipodi:cy="873.36212"
+ sodipodi:cx="41"
+ sodipodi:type="arc"
+ id="path1396"
+ style="opacity:0.7;fill:none;stroke:#ff8919;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:#ff8919;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1398"
+ sodipodi:type="arc"
+ sodipodi:cx="41"
+ sodipodi:cy="873.36212"
+ sodipodi:rx="6.9999995"
+ sodipodi:ry="6.9999995"
+ sodipodi:start="2.3561945"
+ sodipodi:end="2.6179939"
+ sodipodi:open="true"
+ d="m 36.050253,878.31187 c -0.432565,-0.43257 -0.806561,-0.91997 -1.11243,-1.44975" />
+ <path
+ style="fill:none;stroke:#4b2f1e;stroke-width:2.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1400"
+ sodipodi:type="arc"
+ sodipodi:cx="-41"
+ sodipodi:cy="-873.36212"
+ sodipodi:rx="4.2500005"
+ sodipodi:ry="4.2500005"
+ sodipodi:start="0.87266463"
+ sodipodi:end="2.268928"
+ sodipodi:open="true"
+ d="m -38.268152,-870.10643 c -1.579966,1.32575 -3.88373,1.32575 -5.463696,0"
+ inkscape:transform-center-x="-2.2499995"
+ inkscape:transform-center-y="-2.25"
+ transform="scale(-1,-1)" />
+ <path
+ d="m -38.268152,-870.10643 c -1.579966,1.32575 -3.88373,1.32575 -5.463696,0"
+ sodipodi:open="true"
+ sodipodi:end="2.268928"
+ sodipodi:start="0.87266463"
+ sodipodi:ry="4.2500005"
+ sodipodi:rx="4.2500005"
+ sodipodi:cy="-873.36212"
+ sodipodi:cx="-41"
+ sodipodi:type="arc"
+ id="path1402"
+ style="fill:none;stroke:#ffb36b;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ inkscape:transform-center-x="-2.2499995"
+ inkscape:transform-center-y="-2.25"
+ transform="scale(-1,-1)" />
+ <path
+ style="fill:none;stroke:#ffb36b;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1404"
+ sodipodi:type="arc"
+ sodipodi:cx="-41"
+ sodipodi:cy="-873.36212"
+ sodipodi:rx="7.0000005"
+ sodipodi:ry="7.0000005"
+ sodipodi:start="1.3089969"
+ sodipodi:end="1.8325957"
+ sodipodi:open="true"
+ d="m -39.188266,-866.60064 c -1.186888,0.31803 -2.436579,0.31803 -3.623467,0"
+ inkscape:transform-center-y="-3.7500001"
+ transform="scale(-1,-1)"
+ inkscape:transform-center-x="-3.7499995" />
+ <path
+ style="opacity:0.3;fill:none;stroke:#ffe4cb;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1406"
+ sodipodi:type="arc"
+ sodipodi:cx="41"
+ sodipodi:cy="873.36212"
+ sodipodi:rx="4.25"
+ sodipodi:ry="4.25"
+ sodipodi:start="4.0142573"
+ sodipodi:end="4.9741884"
+ sodipodi:open="true"
+ d="m 38.268153,870.10643 c 1.062216,-0.8913 2.492452,-1.20838 3.831828,-0.84949" />
+ <path
+ d="m 39.188267,866.60064 c 1.186888,-0.31802 2.436579,-0.31802 3.623467,0"
+ sodipodi:open="true"
+ sodipodi:end="4.9741884"
+ sodipodi:start="4.4505896"
+ sodipodi:ry="7"
+ sodipodi:rx="7"
+ sodipodi:cy="873.36212"
+ sodipodi:cx="41"
+ sodipodi:type="arc"
+ id="path1408"
+ style="opacity:0.3;fill:none;stroke:#ffe4cb;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ style="opacity:0.6;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"
+ id="path1410"
+ sodipodi:type="arc"
+ sodipodi:cx="41"
+ sodipodi:cy="873.36212"
+ sodipodi:rx="6.9999995"
+ sodipodi:ry="6.9999995"
+ sodipodi:start="4.4505896"
+ sodipodi:end="4.712389"
+ sodipodi:open="true"
+ d="M 39.188267,866.60064 C 39.779161,866.44231 40.388261,866.36212 41,866.36212" />
+ <path
+ d="m 38.268153,870.10643 c 0.475408,-0.39891 1.032412,-0.68887 1.631866,-0.84949"
+ sodipodi:open="true"
+ sodipodi:end="4.4505896"
+ sodipodi:start="4.0142573"
+ sodipodi:ry="4.25"
+ sodipodi:rx="4.25"
+ sodipodi:cy="873.36212"
+ sodipodi:cx="41"
+ sodipodi:type="arc"
+ id="path1412"
+ style="opacity:0.6;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" />
+ <path
+ sodipodi:open="true"
+ style="fill:none;stroke:#ffb36b;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path1414"
+ sodipodi:type="arc"
+ sodipodi:cx="41"
+ sodipodi:cy="873.36212"
+ sodipodi:rx="7"
+ sodipodi:ry="7"
+ sodipodi:start="0.26179939"
+ sodipodi:end="0.78539816"
+ d="m 47.761481,875.17385 c -0.318026,1.18689 -0.942871,2.26916 -1.811734,3.13802" />
+ <path
+ d="m 45.185432,872.62412 c 0.358149,2.03116 -0.793733,4.02628 -2.731847,4.73169"
+ sodipodi:end="7.5049158"
+ sodipodi:start="6.1086524"
+ sodipodi:ry="4.2499995"
+ sodipodi:rx="4.2499995"
+ sodipodi:cy="873.36212"
+ sodipodi:cx="41"
+ sodipodi:type="arc"
+ id="path1416"
+ style="fill:none;stroke:#ffb36b;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:open="true" />
+ </g>
+ <g
+ transform="matrix(1.6674711,0,0,1.6674711,-138.14039,-258.06137)"
+ style="display:inline;enable-background:new"
+ id="g63699">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.3;fill:none;stroke:#422200;stroke-width:0.80000001;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 -102.5625,554.75 c -0.0429,0.005 -0.0849,0.0154 -0.125,0.0312 l -4.5,1.75 c -0.1919,0.0756 -0.31653,0.26258 -0.3125,0.4688 v 6.5 c 0.003,0.18741 0.11203,0.35691 0.28125,0.4375 l 4.5,2.25 c 0.13787,0.0682 0.29963,0.0682 0.4375,0 l 4.499997,-2.25 c 0.169224,-0.0806 0.278188,-0.25009 0.28125,-0.4375 V 557 c 0.004,-0.2062 -0.120622,-0.39315 -0.3125,-0.46875 l -4.499997,-1.75 c -0.0792,-0.0318 -0.16537,-0.0426 -0.25,-0.0312 z"
+ id="path63697" />
+ <g
+ id="g63687"
+ transform="translate(-252,462.99988)">
+ <g
+ transform="translate(-179,199.50012)"
+ id="g63679">
+ <path
+ inkscape:connector-curvature="0"
+ id="path63667"
+ d="m 328.5,-107.25 -4.5,1.75 v 6.5 l 4.5,2.25 4.5,-2.25 v -6.5 z"
+ style="fill:#422200;fill-opacity:1;fill-rule:evenodd;stroke:#422200;stroke-width:1.79999995;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="ccccccc" />
+ <g
+ transform="translate(179,-179)"
+ id="g63671">
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ style="fill:#915515;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 154,80 v -6.5 l -4.5,-1.75 v 10.5 z"
+ id="path63669"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#efa351;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 324,-99.00012 V -105.5 l 4.5,-1.75 0.5,0.25 v 10 l -0.5,0.25 z"
+ id="path63673"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient63713);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 332.5,-105.5 v 6.25 l -4,2 -4,-2.00012 V -105.5"
+ id="path63675"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#f5ca9b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 324,-105.5 4.5,-1.75 4.5,1.75 -4.5,2 z"
+ id="path63677" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.95999995;fill:none;stroke:url(#linearGradient63715);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 145.5,94.25012 c 0,0 4,1.75 4,1.75 l 4,-1.75"
+ id="path63681" />
+ <rect
+ style="opacity:0.25;fill:url(#linearGradient63886);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect63683"
+ width="1"
+ height="6.7500019"
+ x="149"
+ y="96.000122" />
+ </g>
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect63665"
+ width="16"
+ height="16"
+ x="-113"
+ y="554" />
+ <g
+ style="display:inline;enable-background:new"
+ id="g63695"
+ transform="matrix(0.7882544,0,0,0.7883038,-210.45268,388.9974)"
+ 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">
+ <circle
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ 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="circle63689"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#422200;stroke-width:1.97436094;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ transform="matrix(0.6425292,0,0,0.642531,44.523834,146.81699)"
+ 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" />
+ <circle
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ r="8"
+ cy="118"
+ cx="132"
+ style="opacity:0.8;fill:url(#linearGradient63894);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="circle63691"
+ 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"
+ transform="matrix(-0.5858806,-0.06590218,0.06677852,-0.5812167,198.80048,299.96262)"
+ 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" />
+ <circle
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ r="8"
+ cy="118"
+ cx="132"
+ transform="matrix(0.4991181,0,0,0.4991107,63.460522,163.7471)"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient63719);stroke-width:2.54167628;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="circle63693"
+ 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"
+ 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" />
+ </g>
+ </g>
</g>
<path
id="path39836-9"
diff --git a/release/datafiles/blender_icons16/icon16_outliner_ob_force_field.dat b/release/datafiles/blender_icons16/icon16_outliner_ob_force_field.dat
new file mode 100644
index 00000000000..59817bce4de
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_outliner_ob_force_field.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_outliner_ob_group_instance.dat b/release/datafiles/blender_icons16/icon16_outliner_ob_group_instance.dat
new file mode 100644
index 00000000000..072c049c941
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_outliner_ob_group_instance.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_outliner_ob_force_field.dat b/release/datafiles/blender_icons32/icon32_outliner_ob_force_field.dat
new file mode 100644
index 00000000000..bd57178b377
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_outliner_ob_force_field.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_outliner_ob_group_instance.dat b/release/datafiles/blender_icons32/icon32_outliner_ob_group_instance.dat
new file mode 100644
index 00000000000..868f9e4fbcc
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_outliner_ob_group_instance.dat
Binary files differ
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio
index 5bed23cf210..71223ea828e 100644
--- a/release/datafiles/colormanagement/config.ocio
+++ b/release/datafiles/colormanagement/config.ocio
@@ -304,7 +304,7 @@ colorspaces:
equalitygroup:
bitdepth: 32f
description: |
- Log based filmic shaper with 16.5 stops of latitude, and 25 stops of dynamic range.
+ Log based filmic shaper with 16.5 stops of latitude, and 25 stops of dynamic range
isdata: false
allocation: lg2
allocationvars: [-12.473931188, 12.526068812]
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 60956db2576..1cd817a8e8c 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/datafiles/splash_2x.png b/release/datafiles/splash_2x.png
index 3a5000c6bbc..2ba54b92cff 100644
--- a/release/datafiles/splash_2x.png
+++ b/release/datafiles/splash_2x.png
Binary files differ
diff --git a/release/scripts/freestyle/modules/freestyle/__init__.py b/release/scripts/freestyle/modules/freestyle/__init__.py
index d2795f65b6a..6f6b44224d8 100644
--- a/release/scripts/freestyle/modules/freestyle/__init__.py
+++ b/release/scripts/freestyle/modules/freestyle/__init__.py
@@ -19,17 +19,20 @@
"""
This module provides data types of view map components (0D and 1D
elements), base classes for defining line stylization rules
-(predicates, functions, chaining iterators, and stroke shaders), as
-well as helper functions for style module writing.
+(predicates, functions, chaining iterators, and stroke shaders),
+as well as helper functions for style module writing.
Submodules:
-* :mod:`freestyle.types`
-* :mod:`freestyle.predicates`
-* :mod:`freestyle.functions`
-* :mod:`freestyle.chainingiterators`
-* :mod:`freestyle.shaders`
-* :mod:`freestyle.utils`
+.. toctree::
+ :maxdepth: 1
+
+ freestyle.types.rst
+ freestyle.predicates.rst
+ freestyle.functions.rst
+ freestyle.chainingiterators.rst
+ freestyle.shaders.rst
+ freestyle.utils.rst
"""
diff --git a/release/scripts/freestyle/styles/apriori_and_causal_density.py b/release/scripts/freestyle/styles/apriori_and_causal_density.py
index 2ba768af835..42fc3370488 100644
--- a/release/scripts/freestyle/styles/apriori_and_causal_density.py
+++ b/release/scripts/freestyle/styles/apriori_and_causal_density.py
@@ -19,8 +19,8 @@
# Filename : apriori_and_causal_density.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : Selects the lines with high a priori density and
-# subjects them to the causal density so as to avoid
+# Purpose : Selects the lines with high a priori density and
+# subjects them to the causal density so as to avoid
# cluttering
from freestyle.chainingiterators import ChainPredicateIterator
diff --git a/release/scripts/freestyle/styles/cartoon.py b/release/scripts/freestyle/styles/cartoon.py
index e630127db1a..87518bb832e 100644
--- a/release/scripts/freestyle/styles/cartoon.py
+++ b/release/scripts/freestyle/styles/cartoon.py
@@ -19,7 +19,7 @@
# Filename : cartoon.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : Draws colored lines. The color is automatically
+# Purpose : Draws colored lines. The color is automatically
# inferred from each object's material in a cartoon-like
# fashion.
diff --git a/release/scripts/freestyle/styles/external_contour_sketchy.py b/release/scripts/freestyle/styles/external_contour_sketchy.py
index 44dbda4709f..6bccf23ac8d 100644
--- a/release/scripts/freestyle/styles/external_contour_sketchy.py
+++ b/release/scripts/freestyle/styles/external_contour_sketchy.py
@@ -19,8 +19,8 @@
# Filename : external_contour_sketchy.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : Draws the external contour of the scene using a sketchy
-# chaining iterator (in particular each ViewEdge can be drawn
+# Purpose : Draws the external contour of the scene using a sketchy
+# chaining iterator (in particular each ViewEdge can be drawn
# several times
from freestyle.chainingiterators import pySketchyChainingIterator
@@ -41,7 +41,7 @@ from freestyle.shaders import (
from freestyle.types import Operators
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
Operators.select(upred)
Operators.bidirectional_chain(pySketchyChainingIterator(), NotUP1D(upred))
shaders_list = [
diff --git a/release/scripts/freestyle/styles/haloing.py b/release/scripts/freestyle/styles/haloing.py
index 6cd37779a42..34e4f65cf91 100644
--- a/release/scripts/freestyle/styles/haloing.py
+++ b/release/scripts/freestyle/styles/haloing.py
@@ -19,8 +19,8 @@
# Filename : haloing.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : This style module selects the lines that
-# are connected (in the image) to a specific
+# Purpose : This style module selects the lines that
+# are connected (in the image) to a specific
# object and trims them in order to produce
# a haloing effect around the target shape
@@ -42,14 +42,14 @@ from freestyle.shaders import (
from freestyle.types import Id, Operators
-# id corresponds to the id of the target object
+# id corresponds to the id of the target object
# (accessed by SHIFT+click)
id = Id(3,0)
upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyIsOccludedByUP1D(id))
Operators.select(upred)
Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
shaders_list = [
- IncreasingThicknessShader(3, 5),
+ IncreasingThicknessShader(3, 5),
IncreasingColorShader(1,0,0, 1,0,1,0,1),
SamplingShader(1.0),
pyTVertexRemoverShader(),
diff --git a/release/scripts/freestyle/styles/invisible_lines.py b/release/scripts/freestyle/styles/invisible_lines.py
index 461429b6437..5506f4ef11f 100644
--- a/release/scripts/freestyle/styles/invisible_lines.py
+++ b/release/scripts/freestyle/styles/invisible_lines.py
@@ -19,7 +19,7 @@
# Filename : invisible_lines.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : Draws all lines whose Quantitative Invisibility
+# Purpose : Draws all lines whose Quantitative Invisibility
# is different from 0
from freestyle.chainingiterators import ChainSilhouetteIterator
diff --git a/release/scripts/freestyle/styles/long_anisotropically_dense.py b/release/scripts/freestyle/styles/long_anisotropically_dense.py
index 50bec4f1a79..bfd5910cefe 100644
--- a/release/scripts/freestyle/styles/long_anisotropically_dense.py
+++ b/release/scripts/freestyle/styles/long_anisotropically_dense.py
@@ -19,13 +19,13 @@
# Filename : long_anisotropically_dense.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : Selects the lines that are long and have a high anisotropic
-# a priori density and uses causal density
+# Purpose : Selects the lines that are long and have a high anisotropic
+# a priori density and uses causal density
# to draw without cluttering. Ideally, half of the
# selected lines are culled using the causal density.
#
# ********************* WARNING *************************************
-# ******** The Directional a priori density maps must ******
+# ******** The Directional a priori density maps must ******
# ******** have been computed prior to using this style module ******
from freestyle.chainingiterators import ChainSilhouetteIterator
@@ -75,7 +75,7 @@ Operators.sort(pyLengthBP1D())
shaders_list = [
SamplingShader(2.0),
ConstantThicknessShader(2),
- ConstantColorShader(0.2,0.2,0.25,1),
+ ConstantColorShader(0.2,0.2,0.25,1),
]
## uniform culling
Operators.create(pyDensityUP1D(3.0,2.0e-2, IntegrationType.MEAN, 0.1), shaders_list)
diff --git a/release/scripts/freestyle/styles/multiple_parameterization.py b/release/scripts/freestyle/styles/multiple_parameterization.py
index 0e224c74bbf..c03a61c9a81 100644
--- a/release/scripts/freestyle/styles/multiple_parameterization.py
+++ b/release/scripts/freestyle/styles/multiple_parameterization.py
@@ -19,7 +19,7 @@
# Filename : multiple_parameterization.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : The thickness and the color of the strokes vary continuously
+# Purpose : The thickness and the color of the strokes vary continuously
# independently from occlusions although only
# visible lines are actually drawn. This is equivalent
# to assigning the thickness using a parameterization covering
diff --git a/release/scripts/freestyle/styles/nature.py b/release/scripts/freestyle/styles/nature.py
index 74a42e6b2e5..1061f22017a 100644
--- a/release/scripts/freestyle/styles/nature.py
+++ b/release/scripts/freestyle/styles/nature.py
@@ -22,7 +22,7 @@
# Purpose : Uses the NatureUP1D predicate to select the lines
# of a given type (among Nature.SILHOUETTE, Nature.CREASE, Nature.SUGGESTIVE_CONTOURS,
# Nature.BORDERS).
-# The suggestive contours must have been enabled in the
+# The suggestive contours must have been enabled in the
# options dialog to appear in the View Map.
from freestyle.chainingiterators import ChainSilhouetteIterator
diff --git a/release/scripts/freestyle/styles/near_lines.py b/release/scripts/freestyle/styles/near_lines.py
index 5e260a22382..14c8d2f9e01 100644
--- a/release/scripts/freestyle/styles/near_lines.py
+++ b/release/scripts/freestyle/styles/near_lines.py
@@ -19,7 +19,7 @@
# Filename : near_lines.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : Draws the lines that are "closer" than a threshold
+# Purpose : Draws the lines that are "closer" than a threshold
# (between 0 and 1)
from freestyle.chainingiterators import ChainSilhouetteIterator
diff --git a/release/scripts/freestyle/styles/qi1.py b/release/scripts/freestyle/styles/qi1.py
index d70e56d401a..4d87055eafb 100644
--- a/release/scripts/freestyle/styles/qi1.py
+++ b/release/scripts/freestyle/styles/qi1.py
@@ -20,7 +20,7 @@
# Author : Stephane Grabli
# Date : 04/08/2005
# Purpose : Draws lines hidden by one surface.
-# *** Quantitative Invisibility must have been
+# *** Quantitative Invisibility must have been
# enabled in the options dialog to use this style module ****
from freestyle.chainingiterators import ChainSilhouetteIterator
diff --git a/release/scripts/freestyle/styles/qi2.py b/release/scripts/freestyle/styles/qi2.py
index 6ac933ecc05..937b5db590a 100644
--- a/release/scripts/freestyle/styles/qi2.py
+++ b/release/scripts/freestyle/styles/qi2.py
@@ -20,7 +20,7 @@
# Author : Stephane Grabli
# Date : 04/08/2005
# Purpose : Draws lines hidden by two surfaces.
-# *** Quantitative Invisibility must have been
+# *** Quantitative Invisibility must have been
# enabled in the options dialog to use this style module ****
from freestyle.chainingiterators import ChainSilhouetteIterator
diff --git a/release/scripts/freestyle/styles/sequentialsplit_sketchy.py b/release/scripts/freestyle/styles/sequentialsplit_sketchy.py
index b980fdc87d7..5755fd3b845 100644
--- a/release/scripts/freestyle/styles/sequentialsplit_sketchy.py
+++ b/release/scripts/freestyle/styles/sequentialsplit_sketchy.py
@@ -21,7 +21,7 @@
# Date : 04/08/2005
# Purpose : Use the sequential split with two different
# predicates to specify respectively the starting and
-# the stopping extremities for strokes
+# the stopping extremities for strokes
from freestyle.chainingiterators import ChainSilhouetteIterator
from freestyle.predicates import (
diff --git a/release/scripts/freestyle/styles/sketchy_multiple_parameterization.py b/release/scripts/freestyle/styles/sketchy_multiple_parameterization.py
index a3ce6112165..8302ec8e4c3 100644
--- a/release/scripts/freestyle/styles/sketchy_multiple_parameterization.py
+++ b/release/scripts/freestyle/styles/sketchy_multiple_parameterization.py
@@ -19,7 +19,7 @@
# Filename : sketchy_multiple_parameterization.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : Builds sketchy strokes whose topology relies on a
+# Purpose : Builds sketchy strokes whose topology relies on a
# parameterization that covers the complete lines (visible+invisible)
# whereas only the visible portions are actually drawn
diff --git a/release/scripts/freestyle/styles/uniformpruning_zsort.py b/release/scripts/freestyle/styles/uniformpruning_zsort.py
index 814e140ee49..64e808d9f8a 100644
--- a/release/scripts/freestyle/styles/uniformpruning_zsort.py
+++ b/release/scripts/freestyle/styles/uniformpruning_zsort.py
@@ -17,7 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
# Filename : uniformpruning_zsort.py
-# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
# Date : 08/04/2005
from freestyle.chainingiterators import ChainSilhouetteIterator
diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py
index 07fc9f0c338..774ca5173d5 100644
--- a/release/scripts/modules/bl_i18n_utils/settings.py
+++ b/release/scripts/modules/bl_i18n_utils/settings.py
@@ -118,7 +118,7 @@ MSG_COMMENT_PREFIX = "#~ "
MSG_CONTEXT_PREFIX = "MSGCTXT:"
# The default comment prefix used in po's.
-PO_COMMENT_PREFIX= "# "
+PO_COMMENT_PREFIX = "# "
# The comment prefix used to mark sources of msgids, in po's.
PO_COMMENT_PREFIX_SOURCE = "#: "
@@ -130,7 +130,7 @@ PO_COMMENT_PREFIX_SOURCE_CUSTOM = "#. :src: "
PO_COMMENT_PREFIX_GENERATED = "#. "
# The comment prefix used to comment entries in po's.
-PO_COMMENT_PREFIX_MSG= "#~ "
+PO_COMMENT_PREFIX_MSG = "#~ "
# The comment prefix used to mark fuzzy msgids, in po's.
PO_COMMENT_FUZZY = "#, fuzzy"
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 285e2ebe477..b33588c903b 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -128,7 +128,7 @@ class SpellChecker:
"multisampling",
"multiscatter",
"multitexture",
- "multithreaded",
+ "multithreaded",
"multiuser",
"multiview",
"namespace",
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py
index 1d555ae7123..185a0e73279 100644
--- a/release/scripts/modules/bpy/utils/__init__.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -37,6 +37,8 @@ __all__ = (
"register_module",
"register_manual_map",
"unregister_manual_map",
+ "register_classes_factory",
+ "register_submodule_factory",
"make_rna_paths",
"manual_map",
"previews",
@@ -71,6 +73,7 @@ import addon_utils as _addon_utils
_user_preferences = _bpy.context.user_preferences
_script_module_dirs = "startup", "modules"
+_is_factory_startup = _bpy.app.factory_startup
def _test_import(module_name, loaded_modules):
@@ -144,6 +147,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
:type refresh_scripts: bool
"""
use_time = use_class_register_check = _bpy.app.debug_python
+ use_user = not _is_factory_startup
if use_time:
import time
@@ -234,7 +238,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
from bpy_restrict_state import RestrictBlend
with RestrictBlend():
- for base_path in script_paths():
+ for base_path in script_paths(use_user=use_user):
for path_subdir in _script_module_dirs:
path = _os.path.join(base_path, path_subdir)
if _os.path.isdir(path):
@@ -306,7 +310,7 @@ def script_path_pref():
return _os.path.normpath(path) if path else None
-def script_paths(subdir=None, user_pref=True, check_all=False):
+def script_paths(subdir=None, user_pref=True, check_all=False, use_user=True):
"""
Returns a list of valid script paths.
@@ -328,15 +332,30 @@ def script_paths(subdir=None, user_pref=True, check_all=False):
# so the 'BLENDER_SYSTEM_SCRIPTS' environment variable will be used.
base_paths = _bpy_script_paths()
+ # Defined to be (system, user) so we can skip the second if needed.
+ if not use_user:
+ base_paths = base_paths[:1]
+
if check_all:
# All possible paths, no duplicates, keep order.
+ if use_user:
+ test_paths = ('LOCAL', 'USER', 'SYSTEM')
+ else:
+ test_paths = ('LOCAL', 'SYSTEM')
+
base_paths = (
- *(path for path in (_os.path.join(resource_path(res), "scripts")
- for res in ('LOCAL', 'USER', 'SYSTEM')) if path not in base_paths),
+ *(path for path in (
+ _os.path.join(resource_path(res), "scripts")
+ for res in test_paths) if path not in base_paths),
*base_paths,
- )
+ )
- for path in (*base_paths, script_path_user(), script_path_pref()):
+ if use_user:
+ test_paths = (*base_paths, script_path_user(), script_path_pref())
+ else:
+ test_paths = (*base_paths, script_path_pref())
+
+ for path in test_paths:
if path:
path = _os.path.normpath(path)
if path not in scripts and _os.path.isdir(path):
@@ -684,6 +703,65 @@ def unregister_module(module, verbose=False):
print("done.\n")
+def register_classes_factory(classes):
+ """
+ Utility function to create register and unregister functions
+ which simply registers and unregisters a sequence of classes.
+ """
+ def register():
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
+
+ def unregister():
+ from bpy.utils import unregister_class
+ for cls in reversed(classes):
+ unregister_class(cls)
+
+ return register, unregister
+
+
+def register_submodule_factory(module_name, submodule_names):
+ """
+ Utility function to create register and unregister functions
+ which simply load submodules,
+ calling their register & unregister functions.
+
+ .. note::
+
+ Modules are registered in the order given,
+ unregistered in reverse order.
+
+ :arg module_name: The module name, typically ``__name__``.
+ :type module_name: string
+ :arg submodule_names: List of submodule names to load and unload.
+ :type submodule_names: list of strings
+ :return: register and unregister functions.
+ :rtype: tuple pair of functions
+ """
+
+ module = None
+ submodules = []
+
+ def register():
+ nonlocal module
+ module = __import__(name=module_name, fromlist=submodule_names)
+ submodules[:] = [getattr(module, name) for name in submodule_names]
+ for mod in submodules:
+ mod.register()
+
+ def unregister():
+ from sys import modules
+ for mod in reversed(submodules):
+ mod.unregister()
+ name = mod.__name__
+ delattr(module, name.partition(".")[2])
+ del modules[name]
+ submodules.clear()
+
+ return register, unregister
+
+
# -----------------------------------------------------------------------------
# Manual lookups, each function has to return a basepath and a sequence
# of...
diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py
index 5e21260e5e4..f2df1bc16b3 100644
--- a/release/scripts/modules/bpy_extras/anim_utils.py
+++ b/release/scripts/modules/bpy_extras/anim_utils.py
@@ -20,35 +20,118 @@
__all__ = (
"bake_action",
- )
+ "bake_action_objects",
+
+ "bake_action_iter",
+ "bake_action_objects_iter",
+)
import bpy
-# XXX visual keying is actually always considered as True in this code...
-def bake_action(frame_start,
- frame_end,
- frame_step=1,
- only_selected=False,
- do_pose=True,
- do_object=True,
- do_visual_keying=True,
- do_constraint_clear=False,
- do_parents_clear=False,
- do_clean=False,
- action=None,
- ):
+def bake_action(
+ obj,
+ *,
+ action, frames,
+ **kwargs,
+):
+ """
+ :arg obj: Object to bake.
+ :type obj: :class:`bpy.types.Object`
+ :arg action: An action to bake the data into, or None for a new action
+ to be created.
+ :type action: :class:`bpy.types.Action` or None
+ :arg frames: Frames to bake.
+ :type frames: iterable of int
+ :return: an action or None
+ :rtype: :class:`bpy.types.Action`
"""
- Return an image from the file path with options to search multiple paths
- and return a placeholder if its not found.
-
- :arg frame_start: First frame to bake.
- :type frame_start: int
- :arg frame_end: Last frame to bake.
- :type frame_end: int
- :arg frame_step: Frame step.
- :type frame_step: int
+ if not (do_pose or do_object):
+ return None
+
+ action, = bake_action_objects(
+ [(obj, action)],
+ frames,
+ **kwargs,
+ )
+ return action
+
+
+def bake_action_objects(
+ object_action_pairs,
+ *,
+ frames,
+ **kwargs,
+):
+ """
+ A version of :func:`bake_action_objects_iter` that takes frames and returns the output.
+
+ :arg frames: Frames to bake.
+ :type frames: iterable of int
+
+ :return: A sequence of Action or None types (aligned with `object_action_pairs`)
+ :rtype: sequence of :class:`bpy.types.Action`
+ """
+ iter = bake_action_objects_iter(object_action_pairs, **kwargs)
+ iter.send(None)
+ for frame in frames:
+ iter.send(frame)
+ return iter.send(None)
+
+
+def bake_action_objects_iter(
+ object_action_pairs,
+ **kwargs,
+):
+ """
+ An coroutine that bakes actions for multiple objects.
+
+ :arg object_action_pairs: Sequence of object action tuples,
+ action is the destination for the baked data. When None a new action will be created.
+ :type object_action_pairs: Sequence of (:class:`bpy.types.Object`, :class:`bpy.types.Action`)
+ """
+ scene = bpy.context.scene
+ frame_back = scene.frame_current
+ iter_all = tuple(
+ bake_action_iter(obj, action=action, **kwargs)
+ for (obj, action) in object_action_pairs
+ )
+ for iter in iter_all:
+ iter.send(None)
+ while True:
+ frame = yield None
+ if frame is None:
+ break
+ scene.frame_set(frame)
+ scene.update()
+ for iter in iter_all:
+ iter.send(frame)
+ scene.frame_set(frame_back)
+ yield tuple(iter.send(None) for iter in iter_all)
+
+
+# XXX visual keying is actually always considered as True in this code...
+def bake_action_iter(
+ obj,
+ *,
+ action,
+ only_selected=False,
+ do_pose=True,
+ do_object=True,
+ do_visual_keying=True,
+ do_constraint_clear=False,
+ do_parents_clear=False,
+ do_clean=False,
+):
+ """
+ An coroutine that bakes action for a single object.
+
+ :arg obj: Object to bake.
+ :type obj: :class:`bpy.types.Object`
+ :arg action: An action to bake the data into, or None for a new action
+ to be created.
+ :type action: :class:`bpy.types.Action` or None
:arg only_selected: Only bake selected bones.
:type only_selected: bool
:arg do_pose: Bake pose channels.
@@ -63,14 +146,10 @@ def bake_action(frame_start,
:type do_parents_clear: bool
:arg do_clean: Remove redundant keyframes after baking.
:type do_clean: bool
- :arg action: An action to bake the data into, or None for a new action
- to be created.
- :type action: :class:`bpy.types.Action` or None
:return: an action or None
:rtype: :class:`bpy.types.Action`
"""
-
# -------------------------------------------------------------------------
# Helper Functions and vars
@@ -112,34 +191,32 @@ def bake_action(frame_start,
# -------------------------------------------------------------------------
# Setup the Context
- # TODO, pass data rather then grabbing from the context!
- scene = bpy.context.scene
- obj = bpy.context.object
- frame_back = scene.frame_current
-
if obj.pose is None:
do_pose = False
if not (do_pose or do_object):
- return None
+ raise Exception("Pose and object baking is disabled, no action needed")
pose_info = []
obj_info = []
options = {'INSERTKEY_NEEDED'}
- frame_range = range(frame_start, frame_end + 1, frame_step)
-
# -------------------------------------------------------------------------
# Collect transformations
- for f in frame_range:
- scene.frame_set(f)
- scene.update()
+ while True:
+ # Caller is responsible for setting the frame and updating the scene.
+ frame = yield None
+
+ # Signal we're done!
+ if frame is None:
+ break
+
if do_pose:
- pose_info.append(pose_frame_info(obj))
+ pose_info.append((frame, pose_frame_info(obj)))
if do_object:
- obj_info.append(obj_frame_info(obj))
+ obj_info.append((frame, obj_frame_info(obj)))
# -------------------------------------------------------------------------
# Clean (store initial data)
@@ -178,7 +255,7 @@ def bake_action(frame_start,
# create compatible eulers
euler_prev = None
- for (f, matrix) in zip(frame_range, pose_info):
+ for (f, matrix) in pose_info:
pbone.matrix_basis = matrix[name].copy()
pbone.keyframe_insert("location", -1, f, name, options)
@@ -210,7 +287,7 @@ def bake_action(frame_start,
# create compatible eulers
euler_prev = None
- for (f, matrix) in zip(frame_range, obj_info):
+ for (f, matrix) in obj_info:
name = "Action Bake" # XXX: placeholder
obj.matrix_basis = matrix
@@ -261,6 +338,4 @@ def bake_action(frame_start,
else:
i += 1
- scene.frame_set(frame_back)
-
- return action
+ yield action
diff --git a/release/scripts/modules/keyingsets_utils.py b/release/scripts/modules/keyingsets_utils.py
index 8cef64c3590..7ce5f3e029b 100644
--- a/release/scripts/modules/keyingsets_utils.py
+++ b/release/scripts/modules/keyingsets_utils.py
@@ -232,7 +232,7 @@ bbone_property_ids = (
"bbone_scalein",
"bbone_scaleout",
- # NOTE: These are in the nested bone struct
+ # NOTE: These are in the nested bone struct
# Do it this way to force them to be included
# in whatever actions are being keyed here
"bone.bbone_in",
diff --git a/release/scripts/modules/nodeitems_utils.py b/release/scripts/modules/nodeitems_utils.py
index be6f031217c..117e35dd028 100644
--- a/release/scripts/modules/nodeitems_utils.py
+++ b/release/scripts/modules/nodeitems_utils.py
@@ -59,15 +59,29 @@ class NodeItem:
return self._label
else:
# if no custom label is defined, fall back to the node type UI name
- return getattr(bpy.types, self.nodetype).bl_rna.name
+ bl_rna = bpy.types.Node.bl_rna_get_subclass(self.nodetype)
+ if bl_rna is not None:
+ return bl_rna.name
+ else:
+ return "Unknown"
+
+ @property
+ def translation_context(self):
+ if self._label:
+ return bpy.app.translations.contexts.default
+ else:
+ # if no custom label is defined, fall back to the node type UI name
+ bl_rna = bpy.types.Node.bl_rna_get_subclass(self.nodetype)
+ if bl_rna is not None:
+ return bl_rna.translation_context
+ else:
+ return bpy.app.translations.contexts.default
# NB: is a staticmethod because called with an explicit self argument
# NodeItemCustom sets this as a variable attribute in __init__
@staticmethod
def draw(self, layout, context):
- default_context = bpy.app.translations.contexts.default
-
- props = layout.operator("node.add_node", text=self.label, text_ctxt=default_context)
+ props = layout.operator("node.add_node", text=self.label, text_ctxt=self.translation_context)
props.type = self.nodetype
props.use_transform = True
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index 94f5e9e17bb..03f43486371 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -82,6 +82,32 @@ def float_as_string(f):
return val_str
+def get_py_class_from_rna(rna_type):
+ """ Get's the Python type for a class which isn't necessarily added to ``bpy.types``.
+ """
+ identifier = rna_type.identifier
+ py_class = getattr(bpy.types, identifier, None)
+ if py_class is not None:
+ return py_class
+
+ def subclasses_recurse(cls):
+ for c in cls.__subclasses__():
+ # is_registered
+ if "bl_rna" in cls.__dict__:
+ yield c
+ yield from subclasses_recurse(c)
+
+ while py_class is None:
+ base = rna_type.base
+ if base is None:
+ raise Exception("can't find type")
+ py_class_base = getattr(bpy.types, base.identifier, None)
+ if py_class_base is not None:
+ for cls in subclasses_recurse(py_class_base):
+ if cls.bl_rna.identifier == identifier:
+ return cls
+
+
class InfoStructRNA:
__slots__ = (
"bl_rna",
@@ -146,7 +172,8 @@ class InfoStructRNA:
def _get_py_visible_attrs(self):
attrs = []
- py_class = getattr(bpy.types, self.identifier)
+ py_class = get_py_class_from_rna(self.bl_rna)
+
for attr_str in dir(py_class):
if attr_str.startswith("_"):
continue
@@ -437,7 +464,11 @@ class InfoOperatorRNA:
self.args.append(prop)
def get_location(self):
- op_class = getattr(bpy.types, self.identifier)
+ try:
+ op_class = getattr(bpy.types, self.identifier)
+ except AttributeError:
+ # defined in C.
+ return None, None
op_func = getattr(op_class, "execute", None)
if op_func is None:
op_func = getattr(op_class, "invoke", None)
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index 5b81df28524..e447d8a4dc5 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -151,6 +151,13 @@ def write_sysinfo(filepath):
else:
output.write("Blender was built without Cycles support\n")
+ opensubdiv = bpy.app.opensubdiv
+ output.write("OpenSubdiv: ")
+ if opensubdiv.supported:
+ output.write("%s\n" % opensubdiv.version_string)
+ else:
+ output.write("Blender was built without OpenSubdiv support\n")
+
openvdb = bpy.app.openvdb
output.write("OpenVDB: ")
if openvdb.supported:
diff --git a/release/scripts/presets/cycles/integrator/direct_light.py b/release/scripts/presets/cycles/integrator/direct_light.py
index 12b332cb431..701aa10d556 100644
--- a/release/scripts/presets/cycles/integrator/direct_light.py
+++ b/release/scripts/presets/cycles/integrator/direct_light.py
@@ -2,12 +2,10 @@ import bpy
cycles = bpy.context.scene.cycles
cycles.max_bounces = 8
-cycles.min_bounces = 8
cycles.caustics_reflective = False
cycles.caustics_refractive = False
cycles.diffuse_bounces = 0
cycles.glossy_bounces = 1
cycles.transmission_bounces = 2
cycles.volume_bounces = 0
-cycles.transparent_min_bounces = 8
cycles.transparent_max_bounces = 8
diff --git a/release/scripts/presets/cycles/integrator/full_global_illumination.py b/release/scripts/presets/cycles/integrator/full_global_illumination.py
index 69fa6e735bd..a03c6c8bd64 100644
--- a/release/scripts/presets/cycles/integrator/full_global_illumination.py
+++ b/release/scripts/presets/cycles/integrator/full_global_illumination.py
@@ -2,12 +2,10 @@ import bpy
cycles = bpy.context.scene.cycles
cycles.max_bounces = 128
-cycles.min_bounces = 3
cycles.caustics_reflective = True
cycles.caustics_refractive = True
cycles.diffuse_bounces = 128
cycles.glossy_bounces = 128
cycles.transmission_bounces = 128
cycles.volume_bounces = 128
-cycles.transparent_min_bounces = 8
cycles.transparent_max_bounces = 128
diff --git a/release/scripts/presets/cycles/integrator/limited_global_illumination.py b/release/scripts/presets/cycles/integrator/limited_global_illumination.py
index 22a8478d23b..d37bf46c705 100644
--- a/release/scripts/presets/cycles/integrator/limited_global_illumination.py
+++ b/release/scripts/presets/cycles/integrator/limited_global_illumination.py
@@ -2,12 +2,10 @@ import bpy
cycles = bpy.context.scene.cycles
cycles.max_bounces = 8
-cycles.min_bounces = 3
cycles.caustics_reflective = False
cycles.caustics_refractive = False
cycles.diffuse_bounces = 1
cycles.glossy_bounces = 4
cycles.transmission_bounces = 8
cycles.volume_bounces = 2
-cycles.transparent_min_bounces = 8
cycles.transparent_max_bounces = 8
diff --git a/release/scripts/presets/cycles/sampling/final.py b/release/scripts/presets/cycles/sampling/final.py
index d03423b6c2e..f1222d927c1 100644
--- a/release/scripts/presets/cycles/sampling/final.py
+++ b/release/scripts/presets/cycles/sampling/final.py
@@ -1,20 +1,18 @@
import bpy
cycles = bpy.context.scene.cycles
-cycles.use_square_samples = True
-
# Path Trace
-cycles.samples = 24
-cycles.preview_samples = 12
+cycles.samples = 512
+cycles.preview_samples = 128
# Branched Path Trace
-cycles.aa_samples = 8
-cycles.preview_aa_samples = 4
+cycles.aa_samples = 128
+cycles.preview_aa_samples = 32
-cycles.diffuse_samples = 3
-cycles.glossy_samples = 2
-cycles.transmission_samples = 2
+cycles.diffuse_samples = 4
+cycles.glossy_samples = 4
+cycles.transmission_samples = 4
cycles.ao_samples = 1
-cycles.mesh_light_samples = 2
-cycles.subsurface_samples = 2
-cycles.volume_samples = 2
+cycles.mesh_light_samples = 4
+cycles.subsurface_samples = 4
+cycles.volume_samples = 4
diff --git a/release/scripts/presets/cycles/sampling/preview.py b/release/scripts/presets/cycles/sampling/preview.py
index 5f071c7474d..c16449e2c8f 100644
--- a/release/scripts/presets/cycles/sampling/preview.py
+++ b/release/scripts/presets/cycles/sampling/preview.py
@@ -1,20 +1,18 @@
import bpy
cycles = bpy.context.scene.cycles
-cycles.use_square_samples = True
-
# Path Trace
-cycles.samples = 12
-cycles.preview_samples = 6
+cycles.samples = 128
+cycles.preview_samples = 32
# Branched Path Trace
-cycles.aa_samples = 4
-cycles.preview_aa_samples = 2
+cycles.aa_samples = 32
+cycles.preview_aa_samples = 4
-cycles.diffuse_samples = 3
-cycles.glossy_samples = 2
-cycles.transmission_samples = 2
+cycles.diffuse_samples = 4
+cycles.glossy_samples = 4
+cycles.transmission_samples = 4
cycles.ao_samples = 1
-cycles.mesh_light_samples = 2
-cycles.subsurface_samples = 2
-cycles.volume_samples = 2
+cycles.mesh_light_samples = 4
+cycles.subsurface_samples = 4
+cycles.volume_samples = 4
diff --git a/release/scripts/presets/ffmpeg/DVD (note_colon_ this changes render resolution).py b/release/scripts/presets/ffmpeg/DVD_(note_colon__this_changes_render_resolution).py
index d858bd70836..d858bd70836 100644
--- a/release/scripts/presets/ffmpeg/DVD (note_colon_ this changes render resolution).py
+++ b/release/scripts/presets/ffmpeg/DVD_(note_colon__this_changes_render_resolution).py
diff --git a/release/scripts/presets/ffmpeg/h264 in MP4.py b/release/scripts/presets/ffmpeg/h264_in_MP4.py
index 0e9c32c4878..0e9c32c4878 100644
--- a/release/scripts/presets/ffmpeg/h264 in MP4.py
+++ b/release/scripts/presets/ffmpeg/h264_in_MP4.py
diff --git a/release/scripts/presets/ffmpeg/h264 in Matroska.py b/release/scripts/presets/ffmpeg/h264_in_Matroska.py
index 1fe066dc4bf..1fe066dc4bf 100644
--- a/release/scripts/presets/ffmpeg/h264 in Matroska.py
+++ b/release/scripts/presets/ffmpeg/h264_in_Matroska.py
diff --git a/release/scripts/presets/ffmpeg/h264 in Matroska for scrubbing.py b/release/scripts/presets/ffmpeg/h264_in_Matroska_for_scrubbing.py
index eb1889d272f..eb1889d272f 100644
--- a/release/scripts/presets/ffmpeg/h264 in Matroska for scrubbing.py
+++ b/release/scripts/presets/ffmpeg/h264_in_Matroska_for_scrubbing.py
diff --git a/release/scripts/presets/interface_theme/dark_blue_gradient.xml b/release/scripts/presets/interface_theme/dark_blue_gradient.xml
index d3d0f5bb522..d226f8531b2 100644
--- a/release/scripts/presets/interface_theme/dark_blue_gradient.xml
+++ b/release/scripts/presets/interface_theme/dark_blue_gradient.xml
@@ -110,7 +110,7 @@
inner="#39424bcc"
inner_sel="#667686bf"
item="#191919ff"
- text="#000000"
+ text="#b8b8b8"
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="25"
diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml
index 7a3d5146636..b9292856fe9 100644
--- a/release/scripts/presets/interface_theme/elsyiun.xml
+++ b/release/scripts/presets/interface_theme/elsyiun.xml
@@ -110,7 +110,7 @@
inner="#4b4b4bff"
inner_sel="#646464ff"
item="#191919ff"
- text="#000000"
+ text="#b8b8b8"
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="0"
diff --git a/release/scripts/presets/interface_theme/flatty_light.xml b/release/scripts/presets/interface_theme/flatty_light.xml
index 623e0b334dd..c89cbd92ca0 100644
--- a/release/scripts/presets/interface_theme/flatty_light.xml
+++ b/release/scripts/presets/interface_theme/flatty_light.xml
@@ -216,7 +216,7 @@
<wcol_list_item>
<ThemeWidgetColors outline="#e6e6e6"
inner="#00000000"
- inner_sel="#5680c2ff"
+ inner_sel="#446599ff"
item="#80b1ffff"
text="#1a1a1a"
text_sel="#ffffff"
@@ -238,30 +238,33 @@
</ThemeUserInterface>
</user_interface>
<view_3d>
- <ThemeView3D grid="#414141"
+ <ThemeView3D grid="#464646"
+ clipping_border_3d="#313131ff"
wire="#000000"
wire_edit="#808080"
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#00000028"
- speaker="#000000"
- camera="#000000"
- view_overlay="#808080"
- empty="#000000"
+ text_grease_pencil="#b5e61d"
object_selected="#f15800"
object_active="#ffaa40"
- object_grouped="#083008"
+ object_grouped="#004200"
object_grouped_active="#55bb55"
- transform="#ffffff"
+ text_keyframe="#ddd700"
+ camera="#000000"
+ empty="#000000"
+ lamp="#00000028"
+ speaker="#000000"
vertex="#000000"
vertex_select="#ff8500"
vertex_size="3"
+ vertex_bevel="#00a5ff"
vertex_unreferenced="#000000"
edge_select="#ffa000"
edge_seam="#db2512"
edge_sharp="#00ffff"
edge_crease="#cc0099"
+ edge_bevel="#00a5ff"
edge_facesel="#4b4b4b"
freestyle_edge_mark="#7fff7f"
face="#00000012"
@@ -291,19 +294,18 @@
normal="#22dddd"
vertex_normal="#2361dd"
split_normal="#dd23dd"
- bone_solid="#c8c8c8"
bone_pose="#50c8ff"
bone_pose_active="#8cffff"
- frame_current="#60c040"
- outline_width="1"
+ bone_solid="#c8c8c8"
bundle_solid="#c8c8c8"
camera_path="#000000"
skin_root="#b44d4d"
- clipping_border_3d="#313131ff"
- text_keyframe="#ddd700"
- text_grease_pencil="#b5e61d"
+ view_overlay="#808080"
+ transform="#ffffff"
+ frame_current="#60c040"
paint_curve_handle="#7fff7f7f"
- paint_curve_pivot="#ff7f7f7f">
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1">
<space>
<ThemeSpaceGradient title="#000000"
text="#000000"
@@ -321,8 +323,8 @@
tab_outline="#999999">
<gradients>
<ThemeGradientColors show_grad="TRUE"
- gradient="#1b1b1b"
- high_gradient="#3a3a3a">
+ gradient="#444444"
+ high_gradient="#858585">
</ThemeGradientColors>
</gradients>
<panelcolors>
@@ -348,6 +350,7 @@
vertex="#000000"
vertex_select="#ff8500"
vertex_size="6"
+ vertex_bevel="#000000"
vertex_unreferenced="#000000"
handle_free="#000000"
handle_auto="#909000"
@@ -372,13 +375,13 @@
header_text="#000000"
header_text_hi="#ffffff"
button="#999999e6"
- button_title="#000000"
+ button_title="#1a1a1a"
button_text="#000000"
button_text_hi="#ffffff"
- tab_active="#727272"
- tab_inactive="#535353"
- tab_back="#404040ff"
- tab_outline="#3c3c3c">
+ tab_active="#6697e6"
+ tab_inactive="#cccccc"
+ tab_back="#999999ff"
+ tab_outline="#999999">
<panelcolors>
<ThemePanelColors header="#c2c2c2ea"
back="#999999ff"
@@ -398,23 +401,23 @@
</ThemeGraphEditor>
</graph_editor>
<file_browser>
- <ThemeFileBrowser selected_file="#ff8c19">
+ <ThemeFileBrowser selected_file="#5680c2">
<space>
<ThemeSpaceGeneric back="#404040"
title="#000000"
- text="#f1f1f1"
- text_hi="#0f0f0f"
- header="#b3b3b3"
+ text="#eeeeee"
+ text_hi="#ffffff"
+ header="#adadad"
header_text="#000000"
header_text_hi="#ffffff"
- button="#7272727f"
- button_title="#000000"
+ button="#999999e6"
+ button_title="#1a1a1a"
button_text="#000000"
button_text_hi="#ffffff"
tab_active="#6697e6"
- tab_inactive="#535353"
- tab_back="#404040ff"
- tab_outline="#3c3c3c">
+ tab_inactive="#cccccc"
+ tab_back="#999999ff"
+ tab_outline="#999999">
<panelcolors>
<ThemePanelColors header="#c2c2c2ea"
back="#99999980"
@@ -501,6 +504,7 @@
keyframe_jitter_selected="#61c042"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
+ keyframe_scale_factor="1"
summary="#d3660066">
<space>
<ThemeSpaceGeneric back="#6b6b6b"
@@ -543,6 +547,7 @@
vertex="#000000"
vertex_select="#ff8500"
vertex_size="3"
+ vertex_bevel="#000000"
vertex_unreferenced="#000000"
face="#ffffff0a"
face_select="#ff85003c"
diff --git a/release/scripts/presets/interface_theme/science_lab.xml b/release/scripts/presets/interface_theme/science_lab.xml
index 9341e945375..2fe4cf99e41 100644
--- a/release/scripts/presets/interface_theme/science_lab.xml
+++ b/release/scripts/presets/interface_theme/science_lab.xml
@@ -110,7 +110,7 @@
inner="#303030ff"
inner_sel="#678db2ff"
item="#191919ff"
- text="#272727"
+ text="#e6f1ff"
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="0"
diff --git a/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py
index 7825a4d0f32..deb23d76d91 100644
--- a/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py
+++ b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py
@@ -10,7 +10,7 @@ op.include_armatures = True
op.include_shapekeys = False
op.deform_bones_only = True
op.active_uv_only = True
-op.include_uv_textures = True
+op.export_texture_type_selection = 'uv'
op.use_texture_copies = True
op.triangulate = True
op.use_object_instantiation = False
diff --git a/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py
index 9e2efcaa727..ca9de8bf005 100644
--- a/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py
+++ b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py
@@ -10,7 +10,7 @@ op.include_armatures = False
op.include_shapekeys = False
op.deform_bones_only = False
op.active_uv_only = True
-op.include_uv_textures = True
+op.export_texture_type_selection = 'uv'
op.use_texture_copies = True
op.triangulate = True
op.use_object_instantiation = False
diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py
index 02fb05e29eb..0632f9bc3ca 100644
--- a/release/scripts/startup/bl_operators/anim.py
+++ b/release/scripts/startup/bl_operators/anim.py
@@ -137,6 +137,9 @@ class ANIM_OT_keying_set_export(Operator):
break
else:
self.report({'WARN'}, "Could not find scene using Compositor Node Tree - %s" % (ksp.id))
+ elif ksp.id.bl_rna.name == "Key":
+ # "keys" conflicts with a Python keyword, hence the simple solution won't work
+ id_bpy_path = "bpy.data.shape_keys[\"%s\"]" % (ksp.id.name)
else:
idtype_list = ksp.id.bl_rna.name.lower() + "s"
id_bpy_path = "bpy.data.%s[\"%s\"]" % (idtype_list, ksp.id.name)
@@ -195,7 +198,7 @@ class ANIM_OT_keying_set_export(Operator):
class BakeAction(Operator):
- """Bake object/pose loc/scale/rotation animation to a new action"""
+ """Bake all selected objects loc/scale/rotation animation to an action"""
bl_idname = "nla.bake"
bl_label = "Bake Action"
bl_options = {'REGISTER', 'UNDO'}
@@ -219,7 +222,7 @@ class BakeAction(Operator):
default=1,
)
only_selected = BoolProperty(
- name="Only Selected",
+ name="Only Selected Bones",
description="Only key selected bones (Pose baking only)",
default=True,
)
@@ -255,29 +258,27 @@ class BakeAction(Operator):
)
def execute(self, context):
-
from bpy_extras import anim_utils
-
- action = None
- if self.use_current_action:
- obj = context.object
- if obj.animation_data:
- action = obj.animation_data.action
-
- action = anim_utils.bake_action(self.frame_start,
- self.frame_end,
- frame_step=self.step,
- only_selected=self.only_selected,
- do_pose='POSE' in self.bake_types,
- do_object='OBJECT' in self.bake_types,
- do_visual_keying=self.visual_keying,
- do_constraint_clear=self.clear_constraints,
- do_parents_clear=self.clear_parents,
- do_clean=True,
- action=action,
- )
-
- if action is None:
+ objects = context.selected_editable_objects
+ object_action_pairs = (
+ [(obj, getattr(obj.animation_data, "action", None)) for obj in objects]
+ if self.use_current_action else
+ [(obj, None) for obj in objects]
+ )
+
+ actions = anim_utils.bake_action_objects(
+ object_action_pairs,
+ frames=range(self.frame_start, self.frame_end + 1, self.step),
+ only_selected=self.only_selected,
+ do_pose='POSE' in self.bake_types,
+ do_object='OBJECT' in self.bake_types,
+ do_visual_keying=self.visual_keying,
+ do_constraint_clear=self.clear_constraints,
+ do_parents_clear=self.clear_parents,
+ do_clean=True,
+ )
+
+ if not any(actions):
self.report({'INFO'}, "Nothing to bake")
return {'CANCELLED'}
diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py
index e52d577b900..f63b0495d02 100644
--- a/release/scripts/startup/bl_operators/clip.py
+++ b/release/scripts/startup/bl_operators/clip.py
@@ -210,7 +210,7 @@ class CLIP_OT_set_active_clip(bpy.types.Operator):
@classmethod
def poll(cls, context):
space = context.space_data
- return space.type == 'CLIP_EDITOR'
+ return space.type == 'CLIP_EDITOR' and space.clip
def execute(self, context):
clip = context.space_data.clip
@@ -254,6 +254,11 @@ class CLIP_OT_track_to_empty(Operator):
constraint.object = tracking_object.name
constraint.camera = CLIP_camera_for_clip(context, clip)
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ return space.type == 'CLIP_EDITOR' and space.clip
+
def execute(self, context):
sc = context.space_data
clip = sc.clip
@@ -782,8 +787,8 @@ class CLIP_OT_setup_tracking_scene(Operator):
tree.links.new(mul_shadow.outputs["Image"], mul_image.inputs[2])
tree.links.new(rlayer_fg.outputs["Image"], vector_blur.inputs["Image"])
- tree.links.new(rlayer_fg.outputs["Z"], vector_blur.inputs["Z"])
- tree.links.new(rlayer_fg.outputs["Speed"], vector_blur.inputs["Speed"])
+ tree.links.new(rlayer_fg.outputs["Depth"], vector_blur.inputs["Z"])
+ tree.links.new(rlayer_fg.outputs["Vector"], vector_blur.inputs["Speed"])
tree.links.new(mul_image.outputs["Image"], alphaover.inputs[1])
tree.links.new(vector_blur.outputs["Image"], alphaover.inputs[2])
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index 5581415c083..cc590ac9502 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -723,7 +723,7 @@ def main(context,
global USER_FILL_HOLES_QUALITY
global USER_STRETCH_ASPECT
global USER_ISLAND_MARGIN
-
+
from math import cos
import time
@@ -747,7 +747,7 @@ def main(context,
USER_FILL_HOLES = 0
USER_FILL_HOLES_QUALITY = 50 # Only for hole filling.
USER_VIEW_INIT = 0 # Only for hole filling.
-
+
is_editmode = (context.active_object.mode == 'EDIT')
if is_editmode:
obList = [ob for ob in [context.active_object] if ob and ob.type == 'MESH']
diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index 84bae18dd6f..9782d5a072c 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -37,7 +37,7 @@ class MotionPathButtonsPanel:
mps = avs.motion_path
# Display Range
- layout.prop(mps, "type", expand=True)
+ layout.row().prop(mps, "type", expand=True)
split = layout.split()
@@ -87,11 +87,11 @@ class MotionPathButtonsPanel:
col.label(text="Show:")
col.prop(mps, "show_frame_numbers", text="Frame Numbers")
if mpath is not None:
- col.prop(mpath, "lines", text='Lines')
- col.prop(mpath, "line_thickness", text='Thickness')
+ col.prop(mpath, "lines", text="Lines")
+ col.prop(mpath, "line_thickness", text="Thickness")
col = split.column()
- col.label('')
+ col.label("")
col.prop(mps, "show_keyframe_highlight", text="Keyframes")
sub = col.column()
sub.enabled = mps.show_keyframe_highlight
@@ -102,10 +102,10 @@ class MotionPathButtonsPanel:
# Customize path
if mpath is not None:
row = layout.row(align=True)
- row.prop(mpath, "use_custom_color", text='', toggle=True, icon='COLOR')
+ row.prop(mpath, "use_custom_color", text="", toggle=True, icon='COLOR')
sub = row.row(align=True)
sub.enabled = mpath.use_custom_color
- sub.prop(mpath, "color", text='')
+ sub.prop(mpath, "color", text="")
# FIXME: this panel still needs to be ported so that it will work correctly with animviz
@@ -120,7 +120,7 @@ class OnionSkinButtonsPanel:
arm = context.armature
- layout.prop(arm, "ghost_type", expand=True)
+ layout.row().prop(arm, "ghost_type", expand=True)
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index 00892d5f85b..9b61101778f 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -886,10 +886,10 @@ class ConstraintButtonsPanel:
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")
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index a2ecf984eb5..6a13e2ddd44 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -57,7 +57,7 @@ class DATA_PT_skeleton(ArmatureButtonsPanel, Panel):
arm = context.armature
- layout.prop(arm, "pose_position", expand=True)
+ layout.row().prop(arm, "pose_position", expand=True)
col = layout.column()
col.label(text="Layers:")
@@ -80,7 +80,7 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel):
ob = context.object
arm = context.armature
- layout.prop(arm, "draw_type", expand=True)
+ layout.row().prop(arm, "draw_type", expand=True)
split = layout.split()
@@ -96,7 +96,7 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel):
col.prop(arm, "use_deform_delay", text="Delay Refresh")
-class DATA_PT_bone_group_specials(Menu):
+class DATA_MT_bone_group_specials(Menu):
bl_label = "Bone Group Specials"
def draw(self, context):
@@ -130,7 +130,7 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
col.active = (ob.proxy is None)
col.operator("pose.group_add", icon='ZOOMIN', text="")
col.operator("pose.group_remove", icon='ZOOMOUT', text="")
- col.menu("DATA_PT_bone_group_specials", icon='DOWNARROW_HLT', text="")
+ col.menu("DATA_MT_bone_group_specials", icon='DOWNARROW_HLT', text="")
if group:
col.separator()
col.operator("pose.group_move", icon='TRIA_UP', text="").direction = 'UP'
@@ -178,6 +178,10 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
layout.template_ID(ob, "pose_library", new="poselib.new", unlink="poselib.unlink")
if poselib:
+ # warning about poselib being in an invalid state
+ if len(poselib.fcurves) > 0 and len(poselib.pose_markers) == 0:
+ layout.label(icon='ERROR', text="Error: Potentially corrupt library, run 'Sanitize' operator to fix")
+
# list of poses in pose library
row = layout.row()
row.template_list("UI_UL_list", "pose_markers", poselib, "pose_markers",
@@ -215,7 +219,7 @@ class DATA_PT_ghost(ArmatureButtonsPanel, Panel):
arm = context.armature
- layout.prop(arm, "ghost_type", expand=True)
+ layout.row().prop(arm, "ghost_type", expand=True)
split = layout.split()
@@ -252,11 +256,11 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
layout.prop(ob.pose, "ik_solver")
if itasc:
- layout.prop(itasc, "mode", expand=True)
+ layout.row().prop(itasc, "mode", expand=True)
simulation = (itasc.mode == 'SIMULATION')
if simulation:
layout.label(text="Reiteration:")
- layout.prop(itasc, "reiteration_method", expand=True)
+ layout.row().prop(itasc, "reiteration_method", expand=True)
row = layout.row()
row.active = not simulation or itasc.reiteration_method != 'NEVER'
@@ -333,7 +337,7 @@ classes = (
DATA_PT_context_arm,
DATA_PT_skeleton,
DATA_PT_display,
- DATA_PT_bone_group_specials,
+ DATA_MT_bone_group_specials,
DATA_PT_bone_groups,
DATA_PT_pose_library,
DATA_PT_ghost,
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 101062095c4..14286045704 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -79,7 +79,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
cam = context.camera
- layout.prop(cam, "type", expand=True)
+ layout.row().prop(cam, "type", expand=True)
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index ac1eb9505a6..3a3ad31a8ef 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -371,10 +371,10 @@ class DATA_PT_paragraph(CurveButtonsPanelText, Panel):
text = context.curve
layout.label(text="Horizontal Alignment:")
- layout.prop(text, "align_x", expand=True)
+ layout.row().prop(text, "align_x", expand=True)
layout.label(text="Vertical Alignment:")
- layout.prop(text, "align_y", expand=True)
+ layout.row().prop(text, "align_y", expand=True)
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py
index f913ef51381..f9394139b42 100644
--- a/release/scripts/startup/bl_ui/properties_data_lamp.py
+++ b/release/scripts/startup/bl_ui/properties_data_lamp.py
@@ -83,7 +83,7 @@ class DATA_PT_lamp(DataButtonsPanel, Panel):
lamp = context.lamp
- layout.prop(lamp, "type", expand=True)
+ layout.row().prop(lamp, "type", expand=True)
split = layout.split()
@@ -210,13 +210,13 @@ class DATA_PT_shadow(DataButtonsPanel, Panel):
lamp = context.lamp
- layout.prop(lamp, "shadow_method", expand=True)
+ layout.row().prop(lamp, "shadow_method", expand=True)
if lamp.shadow_method == 'NOSHADOW' and lamp.type == 'AREA':
split = layout.split()
col = split.column()
- col.label(text="Form factor sampling:")
+ col.label(text="Form Factor Sampling:")
sub = col.row(align=True)
diff --git a/release/scripts/startup/bl_ui/properties_data_metaball.py b/release/scripts/startup/bl_ui/properties_data_metaball.py
index a621dc7210f..dd62c4523b1 100644
--- a/release/scripts/startup/bl_ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -70,7 +70,7 @@ class DATA_PT_metaball(DataButtonsPanel, Panel):
col.prop(mball, "threshold", text="Threshold")
layout.label(text="Update:")
- layout.prop(mball, "update_method", expand=True)
+ layout.row().prop(mball, "update_method", expand=True)
class DATA_PT_mball_texture_space(DataButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index d72855fab6b..15c9077d970 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -381,7 +381,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
split = layout.split()
col = split.column()
- col.label(text="Vertex group:")
+ col.label(text="Vertex Group:")
col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
sub = col.column()
sub.active = bool(md.vertex_group)
@@ -747,6 +747,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "steps")
col.prop(md, "render_steps")
col.prop(md, "use_smooth_shade")
+ col.prop(md, "use_merge_vertices")
+ sub = col.column()
+ sub.active = md.use_merge_vertices
+ sub.prop(md, "merge_threshold")
col = split.column()
row = col.row()
@@ -917,9 +921,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
scene = bpy.context.scene
engine = scene.render.engine
- show_adaptive_options = (engine == "CYCLES" and md == ob.modifiers[-1] and
- scene.cycles.feature_set == "EXPERIMENTAL")
-
+ 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")
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index 9c5be7624e0..3d105934bf8 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -123,7 +123,7 @@ class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
layout.active = rl.use_freestyle
row = layout.row()
- layout.prop(freestyle, "mode", text="Control mode")
+ layout.prop(freestyle, "mode", text="Control Mode")
layout.prop(freestyle, "use_view_map_cache", text="View Map Cache")
layout.label(text="Edge Detection Options:")
@@ -285,7 +285,7 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
def draw_modifier_box_error(self, box, modifier, message):
row = box.row()
- row.label(text=message, icon="ERROR")
+ row.label(text=message, icon='ERROR')
def draw_modifier_common(self, box, modifier):
row = box.row()
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 46b34373aa5..277b0842b3d 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -90,11 +90,11 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
split = layout.split()
col = split.column()
- col.label(text="Linear velocity:")
+ col.label(text="Linear Velocity:")
sub = col.column(align=True)
sub.prop(game, "velocity_min", text="Minimum")
sub.prop(game, "velocity_max", text="Maximum")
- col.label(text="Angular velocity:")
+ col.label(text="Angular Velocity:")
sub = col.column(align=True)
sub.prop(game, "angular_velocity_min", text="Minimum")
sub.prop(game, "angular_velocity_max", text="Maximum")
@@ -343,7 +343,7 @@ class RENDER_PT_game_stereo(RenderButtonsPanel, Panel):
stereo_mode = gs.stereo
# stereo options:
- layout.prop(gs, "stereo", expand=True)
+ layout.row().prop(gs, "stereo", expand=True)
# stereo:
if stereo_mode == 'STEREO':
@@ -392,7 +392,7 @@ class RENDER_PT_game_shading(RenderButtonsPanel, Panel):
gs = context.scene.game_settings
- layout.prop(gs, "material_mode", expand=True)
+ layout.row().prop(gs, "material_mode", expand=True)
if gs.material_mode == 'GLSL':
split = layout.split()
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 42e8d5272b3..2aa978a51d8 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -75,16 +75,16 @@ def gpencil_active_brush_settings_simple(context, layout):
col.prop(brush, "line_width", slider=True)
row = col.row(align=True)
- row.prop(brush, "use_random_pressure", text='', icon='RNDCURVE')
+ 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.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, "use_random_strength", text="", icon='RNDCURVE')
row.prop(brush, "strength", slider=True)
- row.prop(brush, "use_strength_pressure", text='', icon='STYLUS_PRESSURE')
+ 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.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)
@@ -233,7 +233,7 @@ class GreasePencilStrokeEditPanel:
if is_3d_view:
layout.separator()
-
+
layout.separator()
col = layout.column(align=True)
@@ -340,19 +340,19 @@ class GreasePencilBrushPanel:
row = layout.row()
row.prop(brush, "line_width")
row = layout.row(align=True)
- row.prop(brush, "use_random_pressure", text='', icon='RNDCURVE')
+ 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.prop(brush, "use_pressure", text="", icon='STYLUS_PRESSURE')
row = layout.row(align=True)
- row.prop(brush, "use_random_strength", text='', icon='RNDCURVE')
+ 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.prop(brush, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
row = layout.row(align=True)
row.prop(brush, "random_press", slider=True)
row = layout.row(align=True)
row.prop(brush, "jitter", slider=True)
- row.prop(brush, "use_jitter_pressure", text='', icon='STYLUS_PRESSURE')
+ row.prop(brush, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
row = layout.row()
row.prop(brush, "angle", slider=True)
row.prop(brush, "angle_factor", text="Factor", slider=True)
@@ -365,7 +365,7 @@ class GreasePencilBrushPanel:
col.separator()
row = col.row(align=False)
row.prop(brush, "pen_subdivision_steps")
- row.prop(brush, "random_subdiv", text='Randomness', slider=True)
+ row.prop(brush, "random_subdiv", text="Randomness", slider=True)
class GreasePencilStrokeSculptPanel:
@@ -463,7 +463,7 @@ class GreasePencilBrushCurvesPanel:
###############################
-class GPENCIL_PIE_tool_palette(Menu):
+class GPENCIL_MT_pie_tool_palette(Menu):
"""A pie menu for quick access to Grease Pencil tools"""
bl_label = "Grease Pencil Tools"
@@ -487,7 +487,7 @@ class GPENCIL_PIE_tool_palette(Menu):
# E - "Settings" Palette is included here too, since it needs to be in a stable position...
if gpd and gpd.layers.active:
col.separator()
- col.operator("wm.call_menu_pie", text="Settings...", icon='SCRIPTWIN').name = "GPENCIL_PIE_settings_palette"
+ col.operator("wm.call_menu_pie", text="Settings...", icon='SCRIPTWIN').name = "GPENCIL_MT_pie_settings_palette"
# Editing tools
if gpd:
@@ -525,13 +525,13 @@ class GPENCIL_PIE_tool_palette(Menu):
col.operator("gpencil.delete", icon='X', text="Delete...")
# SE - More Tools
- pie.operator("wm.call_menu_pie", text="More...").name = "GPENCIL_PIE_tools_more"
+ pie.operator("wm.call_menu_pie", text="More...").name = "GPENCIL_MT_pie_tools_more"
else:
# Toggle Edit Mode
pie.operator("gpencil.editmode_toggle", text="Enable Stroke Editing", icon='EDIT')
-class GPENCIL_PIE_settings_palette(Menu):
+class GPENCIL_MT_pie_settings_palette(Menu):
"""A pie menu for quick access to Grease Pencil settings"""
bl_label = "Grease Pencil Settings"
@@ -609,12 +609,12 @@ class GPENCIL_PIE_settings_palette(Menu):
row = col.row()
row.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
row.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")
- col.prop(gpd, "show_stroke_direction", text="Show drawing direction")
+ col.prop(gpd, "show_stroke_direction", text="Show Drawing Direction")
-class GPENCIL_PIE_tools_more(Menu):
+class GPENCIL_MT_pie_tools_more(Menu):
"""A pie menu for accessing more Grease Pencil tools"""
bl_label = "More Grease Pencil Tools"
@@ -643,10 +643,10 @@ class GPENCIL_PIE_tools_more(Menu):
pie.operator("transform.tosphere", icon='MOD_MULTIRES')
pie.operator("gpencil.convert", icon='OUTLINER_OB_CURVE', text="Convert...")
- pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_PIE_tool_palette"
+ pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_MT_pie_tool_palette"
-class GPENCIL_PIE_sculpt(Menu):
+class GPENCIL_MT_pie_sculpt(Menu):
"""A pie menu for accessing Grease Pencil stroke sculpting settings"""
bl_label = "Grease Pencil Sculpt"
@@ -839,8 +839,8 @@ class GPENCIL_MT_brush_specials(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("gpencil.brush_copy", icon='PASTEDOWN', text="Copy current drawing brush")
- layout.operator("gpencil.brush_presets_create", icon='HELP', text="Create a set of predefined brushes")
+ layout.operator("gpencil.brush_copy", icon='PASTEDOWN', text="Copy Current Drawing Brush")
+ layout.operator("gpencil.brush_presets_create", icon='HELP', text="Create a Set of Predefined Brushes")
class GPENCIL_MT_palettecolor_specials(Menu):
@@ -884,9 +884,9 @@ class GreasePencilDataPanel:
# Owner Selector
if context.space_data.type == 'VIEW_3D':
- layout.prop(context.tool_settings, "grease_pencil_source", expand=True)
+ layout.row().prop(context.tool_settings, "grease_pencil_source", expand=True)
elif context.space_data.type == 'CLIP_EDITOR':
- layout.prop(context.space_data, "grease_pencil_source", expand=True)
+ layout.row().prop(context.space_data, "grease_pencil_source", expand=True)
# Grease Pencil data selector
layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.data_add", unlink="gpencil.data_unlink")
@@ -963,7 +963,7 @@ class GreasePencilDataPanel:
row.prop(gpl, "line_change", text="Thickness Change", slider=True)
row.operator("gpencil.stroke_apply_thickness", icon='STYLUS_PRESSURE', text="")
- # Parenting
+ # Parenting
if context.space_data.type == 'VIEW_3D':
col = split.column(align=True)
col.label(text="Parent:")
@@ -1158,10 +1158,10 @@ class GreasePencilToolsPanel:
classes = (
- GPENCIL_PIE_tool_palette,
- GPENCIL_PIE_settings_palette,
- GPENCIL_PIE_tools_more,
- GPENCIL_PIE_sculpt,
+ GPENCIL_MT_pie_tool_palette,
+ GPENCIL_MT_pie_settings_palette,
+ GPENCIL_MT_pie_tools_more,
+ GPENCIL_MT_pie_sculpt,
GPENCIL_MT_snap,
GPENCIL_MT_gpencil_edit_specials,
GPENCIL_UL_brush,
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 06ae1847d06..73740df37e8 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -124,9 +124,10 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
ob = context.object
slot = context.material_slot
space = context.space_data
- is_sortable = (len(ob.material_slots) > 1)
if ob:
+ is_sortable = (len(ob.material_slots) > 1)
+
rows = 1
if is_sortable:
rows = 4
@@ -170,7 +171,7 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
split.separator()
if mat:
- layout.prop(mat, "type", expand=True)
+ layout.row().prop(mat, "type", expand=True)
if mat.use_nodes:
row = layout.row()
row.label(text="", icon='NODETREE')
@@ -991,7 +992,7 @@ class MATERIAL_PT_volume_transp(VolumeButtonsPanel, Panel):
mat = context.material # don't use node material
- layout.prop(mat, "transparency_method", expand=True)
+ layout.row().prop(mat, "transparency_method", expand=True)
class MATERIAL_PT_volume_integration(VolumeButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index d7e18f81232..43c8300b558 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -294,7 +294,7 @@ class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
ob = context.object
- layout.prop(ob, "dupli_type", expand=True)
+ layout.row().prop(ob, "dupli_type", expand=True)
if ob.dupli_type == 'FRAMES':
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index dfd20d90ec4..b79f8263e39 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -157,9 +157,9 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
col.separator()
if projpaint:
if settings.mode == 'MATERIAL':
- col.prop(settings, "use_clone_layer", text="Clone from paint slot")
+ col.prop(settings, "use_clone_layer", text="Clone from Paint Slot")
elif settings.mode == 'IMAGE':
- col.prop(settings, "use_clone_layer", text="Clone from image/UV map")
+ col.prop(settings, "use_clone_layer", text="Clone from Image/UV Map")
if settings.use_clone_layer:
ob = context.active_object
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index e86df975927..aa4cb0ba1e9 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -284,7 +284,7 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
col.prop(part, "lifetime_random", slider=True)
layout.label(text="Emit From:")
- layout.prop(part, "emit_from", expand=True)
+ layout.row().prop(part, "emit_from", expand=True)
row = layout.row()
if part.emit_from == 'VERT':
@@ -297,7 +297,7 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
row.prop(part, "use_even_distribution")
if part.emit_from == 'FACE' or part.emit_from == 'VOLUME':
- layout.prop(part, "distribution", expand=True)
+ layout.row().prop(part, "distribution", expand=True)
row = layout.row()
if part.distribution == 'JIT':
@@ -578,7 +578,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
layout.enabled = particle_panel_enabled(context, psys)
- layout.prop(part, "physics_type", expand=True)
+ layout.row().prop(part, "physics_type", expand=True)
row = layout.row()
col = row.column(align=True)
@@ -628,7 +628,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
split = layout.split()
col = split.column()
- col.label(text="Fluid properties:")
+ col.label(text="Fluid Properties:")
col.prop(fluid, "stiffness", text="Stiffness")
col.prop(fluid, "linear_viscosity", text="Viscosity")
col.prop(fluid, "buoyancy", text="Buoyancy", slider=True)
@@ -749,7 +749,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
if part.physics_type == 'BOIDS':
layout.label(text="Relations:")
elif part.physics_type == 'FLUID':
- layout.label(text="Fluid interaction:")
+ layout.label(text="Fluid Interaction:")
row = layout.row()
row.template_list("UI_UL_list", "particle_targets", psys, "targets",
@@ -785,7 +785,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
sub.prop(key, "object", text="")
sub.prop(key, "system", text="System")
- layout.prop(key, "alliance", expand=True)
+ layout.row().prop(key, "alliance", expand=True)
elif part.physics_type == 'FLUID':
sub = row.row()
# doesn't work yet
@@ -933,7 +933,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
col.prop(part, "show_unborn")
col.prop(part, "use_dead")
- layout.prop(part, "render_type", expand=True)
+ layout.row().prop(part, "render_type", expand=True)
split = layout.split()
@@ -1081,7 +1081,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
col = row.column()
col.prop(part, "trail_count")
if part.trail_count > 1:
- col.prop(part, "use_absolute_path_time", text="Length in frames")
+ col.prop(part, "use_absolute_path_time", text="Length in Frames")
col = row.column()
col.prop(part, "path_end", text="Length", slider=not part.use_absolute_path_time)
col.prop(part, "length_random", text="Random", slider=True)
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 0b98d8738dc..73d3d5fc755 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -79,7 +79,7 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
col = split.column()
- if obj.type in {'MESH', 'LATTICE', 'CURVE'}:
+ if obj.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE', 'FONT'}:
physics_add(self, col, context.soft_body, "Soft Body", 'SOFT_BODY', 'MOD_SOFT', True)
if obj.type == 'MESH':
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index c813350be08..ec7287ef363 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -68,7 +68,7 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
md = context.dynamic_paint
- layout.prop(md, "ui_type", expand=True)
+ layout.row().prop(md, "ui_type", expand=True)
if md.ui_type == 'CANVAS':
canvas = md.canvas_settings
@@ -245,7 +245,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
# paint-map output
row = layout.row()
- row.prop_search(surface, "output_name_a", ob.data, "vertex_colors", text="Paintmap layer")
+ row.prop_search(surface, "output_name_a", ob.data, "vertex_colors", text="Paintmap Layer")
if surface.output_exists(object=ob, index=0):
ic = 'ZOOMOUT'
else:
@@ -255,7 +255,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
# wet-map output
row = layout.row()
- row.prop_search(surface, "output_name_b", ob.data, "vertex_colors", text="Wetmap layer")
+ row.prop_search(surface, "output_name_b", ob.data, "vertex_colors", text="Wetmap Layer")
if surface.output_exists(object=ob, index=1):
ic = 'ZOOMOUT'
else:
@@ -282,7 +282,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
layout.prop(surface, "image_output_path", text="")
row = layout.row()
row.prop(surface, "image_fileformat", text="")
- row.prop(surface, "use_premultiply", text="Premultiply alpha")
+ row.prop(surface, "use_premultiply", text="Premultiply Alpha")
if surface_type == 'PAINT':
split = layout.split(percentage=0.4)
@@ -363,7 +363,7 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
canvas = context.dynamic_paint.canvas_settings
surface = canvas.canvas_surfaces.active
- layout.prop(surface, "effect_ui", expand=True)
+ layout.row().prop(surface, "effect_ui", expand=True)
if surface.effect_ui == 'SPREAD':
layout.prop(surface, "use_spread")
@@ -439,12 +439,12 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
if brush.paint_source == 'PARTICLE_SYSTEM':
col.prop_search(brush, "particle_system", ob, "particle_systems", text="")
if brush.particle_system:
- col.label(text="Particle effect:")
+ col.label(text="Particle Effect:")
sub = col.column()
sub.active = not brush.use_particle_radius
sub.prop(brush, "solid_radius", text="Solid Radius")
col.prop(brush, "use_particle_radius", text="Use Particle's Radius")
- col.prop(brush, "smooth_radius", text="Smooth radius")
+ col.prop(brush, "smooth_radius", text="Smooth Radius")
if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'}:
col.prop(brush, "paint_distance", text="Paint Distance")
diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py
index 2b12fcf982d..3fd47f0b8ca 100644
--- a/release/scripts/startup/bl_ui/properties_physics_field.py
+++ b/release/scripts/startup/bl_ui/properties_physics_field.py
@@ -128,7 +128,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
if field.type not in {'NONE', 'GUIDE'}:
layout.label(text="Falloff:")
- layout.prop(field, "falloff_type", expand=True)
+ layout.row().prop(field, "falloff_type", expand=True)
basic_force_field_falloff_ui(self, context, field)
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index f2e6c1e22e3..4f0d3680834 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -52,7 +52,7 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
md = context.smoke
ob = context.object
- layout.prop(md, "smoke_type", expand=True)
+ layout.row().prop(md, "smoke_type", expand=True)
if md.smoke_type == 'DOMAIN':
domain = md.domain_settings
@@ -322,14 +322,14 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
if cache_file_format == 'POINTCACHE':
layout.label(text="Compression:")
- layout.prop(domain, "point_cache_compress_type", expand=True)
+ layout.row().prop(domain, "point_cache_compress_type", expand=True)
elif cache_file_format == 'OPENVDB':
if not bpy.app.build_options.openvdb:
layout.label("Built without OpenVDB support")
return
layout.label(text="Compression:")
- layout.prop(domain, "openvdb_cache_compress_type", expand=True)
+ layout.row().prop(domain, "openvdb_cache_compress_type", expand=True)
row = layout.row()
row.label("Data Depth:")
row.prop(domain, "data_depth", expand=True, text="Data Depth")
diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py
index 5960428e4ae..5efe105e7d8 100644
--- a/release/scripts/startup/bl_ui/properties_physics_softbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py
@@ -26,6 +26,9 @@ from bl_ui.properties_physics_common import (
)
+COMPAT_OB_TYPES = {'MESH', 'LATTICE', 'CURVE', 'SURFACE', 'FONT'}
+
+
def softbody_panel_enabled(md):
return (md.point_cache.is_baked is False)
@@ -39,7 +42,7 @@ class PhysicButtonsPanel:
def poll(cls, context):
ob = context.object
rd = context.scene.render
- return (ob and (ob.type == 'MESH' or ob.type == 'LATTICE'or ob.type == 'CURVE')) and (rd.engine in cls.COMPAT_ENGINES) and (context.soft_body)
+ return ob and ob.type in COMPAT_OB_TYPES and rd.engine in cls.COMPAT_ENGINES and context.soft_body
class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
@@ -191,7 +194,7 @@ class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, Panel):
layout.active = softbody.use_self_collision and softbody_panel_enabled(md)
layout.label(text="Collision Ball Size Calculation:")
- layout.prop(softbody, "collision_type", expand=True)
+ layout.row().prop(softbody, "collision_type", expand=True)
col = layout.column(align=True)
col.label(text="Ball:")
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index a7e8d9273ad..6101c715991 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -275,6 +275,7 @@ class RENDER_PT_performance(RenderButtonsPanel, Panel):
col.separator()
col.prop(rd, "preview_start_resolution")
+ col.prop(rd, "preview_pixel_size", text="")
col = split.column()
col.label(text="Memory:")
@@ -286,7 +287,7 @@ class RENDER_PT_performance(RenderButtonsPanel, Panel):
sub.prop(rd, "use_free_image_textures")
sub = col.column()
sub.active = rd.use_raytrace
- sub.label(text="Acceleration structure:")
+ sub.label(text="Acceleration Structure:")
sub.prop(rd, "raytrace_method", text="")
if rd.raytrace_method == 'OCTREE':
sub.prop(rd, "octree_resolution", text="Resolution")
@@ -347,7 +348,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
col.active = rd.use_stamp
row = col.row()
row.prop(rd, "stamp_font_size", text="Font Size")
- row.prop(rd, "use_stamp_labels", text="Draw labels")
+ row.prop(rd, "use_stamp_labels", text="Draw Labels")
row = col.row()
row.column().prop(rd, "stamp_foreground", slider=True)
@@ -482,9 +483,9 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
layout.prop(ffmpeg, "gopsize")
# B-Frames
row = layout.row()
- row.prop(ffmpeg, "use_max_b_frames", text='Max B-frames')
+ row.prop(ffmpeg, "use_max_b_frames", text="Max B-frames")
pbox = row.split()
- pbox.prop(ffmpeg, "max_b_frames", text='')
+ pbox.prop(ffmpeg, "max_b_frames", text="")
pbox.enabled = ffmpeg.use_max_b_frames
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index d05527b7ef6..880684997bf 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -165,7 +165,7 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
pin_id = None
if not space.use_pin_id:
- layout.prop(space, "texture_context", expand=True)
+ layout.row().prop(space, "texture_context", expand=True)
pin_id = None
if space.texture_context == 'OTHER':
@@ -318,9 +318,9 @@ class TEXTURE_PT_clouds(TextureTypePanel, Panel):
tex = context.texture
- layout.prop(tex, "cloud_type", expand=True)
+ layout.row().prop(tex, "cloud_type", expand=True)
layout.label(text="Noise:")
- layout.prop(tex, "noise_type", text="Type", expand=True)
+ layout.row().prop(tex, "noise_type", text="Type", expand=True)
layout.prop(tex, "noise_basis", text="Basis")
split = layout.split()
@@ -342,8 +342,8 @@ class TEXTURE_PT_wood(TextureTypePanel, Panel):
tex = context.texture
- layout.prop(tex, "noise_basis_2", expand=True)
- layout.prop(tex, "wood_type", expand=True)
+ layout.row().prop(tex, "noise_basis_2", expand=True)
+ layout.row().prop(tex, "wood_type", expand=True)
col = layout.column()
col.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
@@ -371,10 +371,10 @@ class TEXTURE_PT_marble(TextureTypePanel, Panel):
tex = context.texture
- layout.prop(tex, "marble_type", expand=True)
- layout.prop(tex, "noise_basis_2", expand=True)
+ layout.row().prop(tex, "marble_type", expand=True)
+ layout.row().prop(tex, "noise_basis_2", expand=True)
layout.label(text="Noise:")
- layout.prop(tex, "noise_type", text="Type", expand=True)
+ layout.row().prop(tex, "noise_type", text="Type", expand=True)
layout.prop(tex, "noise_basis", text="Basis")
split = layout.split()
@@ -431,9 +431,9 @@ class TEXTURE_PT_stucci(TextureTypePanel, Panel):
tex = context.texture
- layout.prop(tex, "stucci_type", expand=True)
+ layout.row().prop(tex, "stucci_type", expand=True)
layout.label(text="Noise:")
- layout.prop(tex, "noise_type", text="Type", expand=True)
+ layout.row().prop(tex, "noise_type", text="Type", expand=True)
layout.prop(tex, "noise_basis", text="Basis")
row = layout.row()
@@ -808,7 +808,7 @@ class TEXTURE_PT_pointdensity(TextureButtonsPanel, Panel):
tex = context.texture
pd = tex.point_density
- layout.prop(pd, "point_source", expand=True)
+ layout.row().prop(pd, "point_source", expand=True)
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index 6aa39580d34..107c31567b3 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -175,7 +175,7 @@ class WORLD_PT_gather(WorldButtonsPanel, Panel):
layout.active = light.use_ambient_occlusion or light.use_environment_light or light.use_indirect_light
- layout.prop(light, "gather_method", expand=True)
+ layout.row().prop(light, "gather_method", expand=True)
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 43679727992..57195d22340 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -1033,11 +1033,11 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
if clip.source == 'MOVIE':
col2 = col.column()
- col2.label(text="Use timecode index:")
+ col2.label(text="Use Timecode Index:")
col2.prop(clip.proxy, "timecode", text="")
col2 = col.column()
- col2.label(text="Proxy render size:")
+ col2.label(text="Proxy Render Size:")
col.prop(sc.clip_user, "proxy_render_size", text="")
@@ -1418,7 +1418,7 @@ class CLIP_MT_tracking_specials(Menu):
text="Enable Markers").action = 'ENABLE'
layout.operator("clip.disable_markers",
- text="Disable markers").action = 'DISABLE'
+ text="Disable Markers").action = 'DISABLE'
layout.separator()
layout.operator("clip.set_origin")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index f070161f3da..340a6c807df 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -1086,7 +1086,7 @@ class IMAGE_PT_tools_paint_options(BrushButtonsPanel, Panel):
col.prop(ups, "use_unified_color", text="Color")
-class IMAGE_UV_sculpt_curve(Panel):
+class IMAGE_PT_uv_sculpt_curve(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "UV Sculpt Curve"
@@ -1117,7 +1117,7 @@ class IMAGE_UV_sculpt_curve(Panel):
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
-class IMAGE_UV_sculpt(Panel, ImagePaintPanel):
+class IMAGE_PT_uv_sculpt(Panel, ImagePaintPanel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_category = "Tools"
@@ -1370,8 +1370,8 @@ classes = (
IMAGE_PT_tools_imagepaint_symmetry,
IMAGE_PT_tools_brush_appearance,
IMAGE_PT_tools_paint_options,
- IMAGE_UV_sculpt,
- IMAGE_UV_sculpt_curve,
+ IMAGE_PT_uv_sculpt,
+ IMAGE_PT_uv_sculpt_curve,
IMAGE_PT_view_histogram,
IMAGE_PT_view_waveform,
IMAGE_PT_view_vectorscope,
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index b37b3c5705a..e2056905d93 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -187,10 +187,10 @@ class NODE_MT_view(Menu):
if context.space_data.show_backdrop:
layout.separator()
- layout.operator("node.backimage_move", text="Backdrop move")
- layout.operator("node.backimage_zoom", text="Backdrop zoom in").factor = 1.2
- layout.operator("node.backimage_zoom", text="Backdrop zoom out").factor = 0.83333
- layout.operator("node.backimage_fit", text="Fit backdrop to available space")
+ layout.operator("node.backimage_move", text="Backdrop Move")
+ layout.operator("node.backimage_zoom", text="Backdrop Zoom In").factor = 1.2
+ layout.operator("node.backimage_zoom", text="Backdrop Zoom Out").factor = 0.83333
+ layout.operator("node.backimage_fit", text="Fit Backdrop to Available Space")
layout.separator()
@@ -243,7 +243,7 @@ class NODE_MT_node(Menu):
layout.separator()
- layout.operator("node.join", text="Join in new Frame")
+ layout.operator("node.join", text="Join in New Frame")
layout.operator("node.detach", text="Remove from Frame")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 4eb550bbb35..731ab3d4b14 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -56,7 +56,7 @@ class OUTLINER_HT_header(Header):
row.operator("anim.keyframe_delete", text="", icon='KEY_DEHLT')
else:
row = layout.row()
- row.label(text="No Keying Set active")
+ row.label(text="No Keying Set Active")
elif space.display_mode == 'ORPHAN_DATA':
layout.operator("outliner.orphans_purge")
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 6737b8e1089..06dd90685b7 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -43,7 +43,7 @@ def draw_color_balance(layout, color_balance):
col.separator()
col.separator()
col.prop(color_balance, "lift", text="")
- col.prop(color_balance, "invert_lift", text="Invert", icon="ARROW_LEFTRIGHT")
+ col.prop(color_balance, "invert_lift", text="Invert", icon='ARROW_LEFTRIGHT')
split.template_color_picker(color_balance, "lift", value_slider=True, cubic=True)
box = layout.box()
@@ -53,7 +53,7 @@ def draw_color_balance(layout, color_balance):
col.separator()
col.separator()
col.prop(color_balance, "gamma", text="")
- col.prop(color_balance, "invert_gamma", text="Invert", icon="ARROW_LEFTRIGHT")
+ col.prop(color_balance, "invert_gamma", text="Invert", icon='ARROW_LEFTRIGHT')
split.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
box = layout.box()
@@ -63,7 +63,7 @@ def draw_color_balance(layout, color_balance):
col.separator()
col.separator()
col.prop(color_balance, "gain", text="")
- col.prop(color_balance, "invert_gain", text="Invert", icon="ARROW_LEFTRIGHT")
+ col.prop(color_balance, "invert_gain", text="Invert", icon='ARROW_LEFTRIGHT')
split.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
@@ -197,7 +197,7 @@ class SEQUENCER_MT_view(Menu):
layout.operator_context = 'INVOKE_DEFAULT'
if is_preview:
layout.operator_context = 'INVOKE_REGION_PREVIEW'
- layout.operator("sequencer.view_all_preview", text="Fit preview in window")
+ layout.operator("sequencer.view_all_preview", text="Fit Preview in Window")
layout.separator()
@@ -246,10 +246,10 @@ class SEQUENCER_MT_select(Menu):
layout.operator("sequencer.select_active_side", text="Strips to the Left").side = 'LEFT'
layout.operator("sequencer.select_active_side", text="Strips to the Right").side = 'RIGHT'
- props = layout.operator("sequencer.select", text="All strips to the Left")
+ props = layout.operator("sequencer.select", text="All Strips to the Left")
props.left_right = 'LEFT'
props.linked_time = True
- props = layout.operator("sequencer.select", text="All strips to the Right")
+ props = layout.operator("sequencer.select", text="All Strips to the Right")
props.left_right = 'RIGHT'
props.linked_time = True
@@ -338,21 +338,21 @@ class SEQUENCER_MT_add(Menu):
if len(bpy.data.scenes) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
- layout.operator("sequencer.scene_strip_add", text="Scene")
+ layout.operator("sequencer.scene_strip_add", text="Scene...")
else:
- layout.operator_menu_enum("sequencer.scene_strip_add", "scene", text="Scene...")
+ layout.operator_menu_enum("sequencer.scene_strip_add", "scene", text="Scene")
if len(bpy.data.movieclips) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
- layout.operator("sequencer.movieclip_strip_add", text="Clips")
+ layout.operator("sequencer.movieclip_strip_add", text="Clips...")
else:
- layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip...")
+ layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip")
if len(bpy.data.masks) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
- layout.operator("sequencer.mask_strip_add", text="Masks")
+ layout.operator("sequencer.mask_strip_add", text="Masks...")
else:
- layout.operator_menu_enum("sequencer.mask_strip_add", "mask", text="Mask...")
+ layout.operator_menu_enum("sequencer.mask_strip_add", "mask", text="Mask")
layout.operator("sequencer.movie_strip_add", text="Movie")
layout.operator("sequencer.image_strip_add", text="Image")
@@ -397,15 +397,15 @@ class SEQUENCER_MT_strip(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("transform.transform", text="Grab/Move").mode = 'TRANSLATION'
- layout.operator("transform.transform", text="Grab/Extend from frame").mode = 'TIME_EXTEND'
+ layout.operator("transform.transform", text="Grab/Extend from Frame").mode = 'TIME_EXTEND'
layout.operator("sequencer.gap_remove").all = False
layout.operator("sequencer.gap_insert")
# uiItemO(layout, NULL, 0, "sequencer.strip_snap"); // TODO - add this operator
layout.separator()
- layout.operator("sequencer.cut", text="Cut (hard) at frame").type = 'HARD'
- layout.operator("sequencer.cut", text="Cut (soft) at frame").type = 'SOFT'
+ layout.operator("sequencer.cut", text="Cut (Hard) at Frame").type = 'HARD'
+ layout.operator("sequencer.cut", text="Cut (Soft) at Frame").type = 'SOFT'
layout.operator("sequencer.slip", text="Slip Strip Contents")
layout.operator("sequencer.images_separate")
layout.operator("sequencer.offset_clear")
@@ -631,7 +631,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
if strip.use_as_speed:
layout.prop(strip, "speed_factor")
else:
- layout.prop(strip, "speed_factor", text="Frame number")
+ layout.prop(strip, "speed_factor", text="Frame Number")
layout.prop(strip, "scale_to_length")
elif strip.type == 'TRANSFORM':
@@ -698,7 +698,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
row.label("")
else:
col.separator()
- col.label(text="Two or more channels are needed below this strip", icon="INFO")
+ col.label(text="Two or more channels are needed below this strip", icon='INFO')
elif strip.type == 'TEXT':
@@ -728,7 +728,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
elif strip.type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER', 'ALPHA_UNDER', 'OVER_DROP'}:
col.prop(strip, "use_default_fade", "Default fade")
if not strip.use_default_fade:
- col.prop(strip, "effect_fader", text="Effect fader")
+ col.prop(strip, "effect_fader", text="Effect Fader")
elif strip.type == 'GAUSSIAN_BLUR':
row = col.row(align=True)
row.prop(strip, "size_x")
@@ -784,7 +784,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
split.label(text="Alpha:")
split.prop(strip, "alpha_mode", text="")
- layout.operator("sequencer.change_path", icon="FILESEL").filter_image = True
+ layout.operator("sequencer.change_path", icon='FILESEL').filter_image = True
elif seq_type == 'MOVIE':
split = layout.split(percentage=0.2)
@@ -1056,9 +1056,9 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
proxy = strip.proxy
flow = layout.column_flow()
- flow.prop(sequencer, "proxy_storage", text='Storage')
+ flow.prop(sequencer, "proxy_storage", text="Storage")
if sequencer.proxy_storage == 'PROJECT':
- flow.prop(sequencer, "proxy_dir", text='Directory')
+ flow.prop(sequencer, "proxy_dir", text="Directory")
else:
flow.prop(proxy, "use_proxy_custom_directory")
flow.prop(proxy, "use_proxy_custom_file")
@@ -1077,7 +1077,7 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
layout.prop(proxy, "use_overwrite")
col = layout.column()
- col.prop(proxy, "quality", text="Build JPEG quality")
+ col.prop(proxy, "quality", text="Build JPEG Quality")
if strip.type == 'MOVIE':
col = layout.column()
@@ -1101,9 +1101,6 @@ class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
render = context.scene.render
col = layout.column()
- col.prop(render, "use_sequencer_gl_preview", text="OpenGL Preview")
- col = layout.column()
- #col.active = render.use_sequencer_gl_preview
col.prop(render, "sequencer_gl_preview", text="")
row = col.row()
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index b9a25cd72a0..9930992e9bb 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -250,7 +250,7 @@ def marker_menu_generic(layout):
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("marker.make_links_scene", text="Duplicate Marker to Scene...", icon='OUTLINER_OB_EMPTY')
else:
- layout.operator_menu_enum("marker.make_links_scene", "scene", text="Duplicate Marker to Scene...")
+ layout.operator_menu_enum("marker.make_links_scene", "scene", text="Duplicate Marker to Scene")
layout.operator("marker.delete", text="Delete Marker")
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 5ed481a215a..5ba1f0b8dcb 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -80,7 +80,7 @@ class USERPREF_PT_tabs(Panel):
userpref = context.user_preferences
- layout.prop(userpref, "active_section", expand=True)
+ layout.row().prop(userpref, "active_section", expand=True)
class USERPREF_MT_interaction_presets(Menu):
@@ -127,7 +127,7 @@ class USERPREF_MT_app_templates(Menu):
text=bpy.path.display_name(d),
)
props.use_splash = True
- props.app_template = d;
+ props.app_template = d
if use_install:
layout.separator()
@@ -218,6 +218,7 @@ class USERPREF_PT_interface(Panel):
col = row.column()
col.label(text="Display:")
col.prop(view, "ui_scale", text="Scale")
+ col.prop(view, "ui_line_width", text="Line Width")
col.prop(view, "show_tooltips")
col.prop(view, "show_tooltips_python")
col.prop(view, "show_object_info", text="Object Info")
@@ -249,6 +250,7 @@ class USERPREF_PT_interface(Panel):
col = row.column()
col.label(text="View Manipulation:")
col.prop(view, "use_mouse_depth_cursor")
+ col.prop(view, "use_cursor_lock_adjust")
col.prop(view, "use_mouse_depth_navigate")
col.prop(view, "use_zoom_to_mouse")
col.prop(view, "use_rotate_around_active")
@@ -477,7 +479,7 @@ class USERPREF_PT_system(Panel):
col.label(text="Sound:")
col.row().prop(system, "audio_device", expand=False)
sub = col.column()
- sub.active = system.audio_device != 'NONE' and system.audio_device != 'Null'
+ sub.active = system.audio_device not in {'NONE', 'Null'}
#sub.prop(system, "use_preview_images")
sub.prop(system, "audio_channels", text="Channels")
sub.prop(system, "audio_mixing_buffer", text="Mixing Buffer")
@@ -560,7 +562,7 @@ class USERPREF_PT_system(Panel):
# 3. Column
column = split.column()
- column.label(text="Solid OpenGL lights:")
+ column.label(text="Solid OpenGL Lights:")
split = column.split(percentage=0.1)
split.label()
@@ -1105,29 +1107,29 @@ class USERPREF_MT_ndof_settings(Menu):
layout.prop(input_prefs, "ndof_show_guide")
layout.separator()
- layout.label(text="Orbit style")
+ layout.label(text="Orbit Style")
layout.row().prop(input_prefs, "ndof_view_navigate_method", text="")
layout.row().prop(input_prefs, "ndof_view_rotate_method", text="")
layout.separator()
- layout.label(text="Orbit options")
+ layout.label(text="Orbit Options")
layout.prop(input_prefs, "ndof_rotx_invert_axis")
layout.prop(input_prefs, "ndof_roty_invert_axis")
layout.prop(input_prefs, "ndof_rotz_invert_axis")
# view2d use pan/zoom
layout.separator()
- layout.label(text="Pan options")
+ layout.label(text="Pan Options")
layout.prop(input_prefs, "ndof_panx_invert_axis")
layout.prop(input_prefs, "ndof_pany_invert_axis")
layout.prop(input_prefs, "ndof_panz_invert_axis")
layout.prop(input_prefs, "ndof_pan_yz_swap_axis")
- layout.label(text="Zoom options")
+ layout.label(text="Zoom Options")
layout.prop(input_prefs, "ndof_zoom_invert")
if is_view3d:
layout.separator()
- layout.label(text="Fly/Walk options")
+ layout.label(text="Fly/Walk Options")
layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY')
layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM')
@@ -1452,7 +1454,7 @@ class USERPREF_PT_addons(Panel):
sub = row.row()
sub.active = is_enabled
- sub.label(text='%s: %s' % (info["category"], info["name"]))
+ sub.label(text="%s: %s" % (info["category"], info["name"]))
if info["warning"]:
sub.label(icon='ERROR')
@@ -1480,11 +1482,11 @@ class USERPREF_PT_addons(Panel):
if info["version"]:
split = colsub.row().split(percentage=0.15)
split.label(text="Version:")
- split.label(text='.'.join(str(x) for x in info["version"]), translate=False)
+ split.label(text=".".join(str(x) for x in info["version"]), translate=False)
if info["warning"]:
split = colsub.row().split(percentage=0.15)
split.label(text="Warning:")
- split.label(text=' ' + info["warning"], icon='ERROR')
+ split.label(text=" " + info["warning"], icon='ERROR')
user_addon = USERPREF_PT_addons.is_user_addon(mod, user_addon_paths)
tot_row = bool(info["wiki_url"]) + bool(user_addon)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 42a6d3138a7..0ba64a1177f 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -294,7 +294,8 @@ class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base):
layout.operator("object.origin_set", text="Geometry to Origin").type = 'GEOMETRY_ORIGIN'
layout.operator("object.origin_set", text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
layout.operator("object.origin_set", text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
- layout.operator("object.origin_set", text="Origin to Center of Mass").type = 'ORIGIN_CENTER_OF_MASS'
+ layout.operator("object.origin_set", text="Origin to Center of Mass (Surface)").type = 'ORIGIN_CENTER_OF_MASS'
+ layout.operator("object.origin_set", text="Origin to Center of Mass (Volume)").type = 'ORIGIN_CENTER_OF_VOLUME'
layout.separator()
layout.operator("object.randomize_transform")
@@ -1255,14 +1256,14 @@ class INFO_MT_add(Menu):
layout.menu("INFO_MT_lamp_add", icon='OUTLINER_OB_LAMP')
layout.separator()
- layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_EMPTY')
+ layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_FORCE_FIELD')
layout.separator()
if len(bpy.data.groups) > 10:
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("object.group_instance_add", text="Group Instance...", icon='OUTLINER_OB_EMPTY')
+ layout.operator("object.group_instance_add", text="Group Instance...", icon='OUTLINER_OB_GROUP_INSTANCE')
else:
- layout.operator_menu_enum("object.group_instance_add", "group", text="Group Instance", icon='OUTLINER_OB_EMPTY')
+ layout.operator_menu_enum("object.group_instance_add", "group", text="Group Instance", icon='OUTLINER_OB_GROUP_INSTANCE')
# ********** Object menu **********
@@ -1663,7 +1664,7 @@ class VIEW3D_MT_make_links(Menu):
layout.operator("object.make_links_scene", text="Objects to Scene...", icon='OUTLINER_OB_EMPTY')
else:
layout.operator_context = 'EXEC_REGION_WIN'
- layout.operator_menu_enum("object.make_links_scene", "scene", text="Objects to Scene...")
+ layout.operator_menu_enum("object.make_links_scene", "scene", text="Objects to Scene")
layout.operator_context = operator_context_default
layout.operator_enum("object.make_links_data", "type") # inline
@@ -1710,7 +1711,7 @@ class VIEW3D_MT_brush(Menu):
# skip if no active brush
if not brush:
- layout.label(text="No Brushes currently available", icon="INFO")
+ layout.label(text="No Brushes currently available", icon='INFO')
return
# brush paint modes
@@ -2115,7 +2116,7 @@ class VIEW3D_MT_pose_transform(Menu):
layout.separator()
- layout.operator("pose.user_transforms_clear", text="Reset unkeyed")
+ layout.operator("pose.user_transforms_clear", text="Reset Unkeyed")
class VIEW3D_MT_pose_slide(Menu):
@@ -3536,7 +3537,7 @@ class VIEW3D_PT_view3d_meshstatvis(Panel):
row = layout.row(align=True)
row.prop(statvis, "overhang_min", text="")
row.prop(statvis, "overhang_max", text="")
- layout.prop(statvis, "overhang_axis", expand=True)
+ layout.row().prop(statvis, "overhang_axis", expand=True)
elif statvis_type == 'THICKNESS':
row = layout.row(align=True)
row.prop(statvis, "thickness_min", text="")
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index ca33d54a781..ec2e458ea7a 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -929,16 +929,18 @@ class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel):
col.separator()
col.label("Missing Canvas", icon='INFO')
col.label("Add or assign a canvas image below")
- col.label("Canvas Image")
- col.template_ID(toolsettings, "canvas")
+ col.label("Canvas Image:")
+ # todo this should be combinded into a single row
+ col.template_ID(toolsettings, "canvas", open="image.open")
col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
if toolsettings.missing_stencil:
col.separator()
col.label("Missing Stencil", icon='INFO')
col.label("Add or assign a stencil image below")
- col.label("Stencil Image")
- col.template_ID(toolsettings, "stencil_image")
+ col.label("Stencil Image:")
+ # todo this should be combinded into a single row
+ col.template_ID(toolsettings, "stencil_image", open="image.open")
col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
@@ -980,9 +982,9 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.prop(brush, "steps", slider=True)
col.prop(settings, "default_key_count", slider=True)
elif tool == 'LENGTH':
- layout.prop(brush, "length_mode", expand=True)
+ layout.row().prop(brush, "length_mode", expand=True)
elif tool == 'PUFF':
- layout.prop(brush, "puff_mode", expand=True)
+ layout.row().prop(brush, "puff_mode", expand=True)
layout.prop(brush, "use_puff_volume")
# Sculpt Mode #
@@ -1232,20 +1234,20 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
ob = context.active_object
col = layout.column()
- col.label("Painting Mode")
+ col.label("Painting Mode:")
col.prop(settings, "mode", text="")
col.separator()
if settings.mode == 'MATERIAL':
if len(ob.material_slots) > 1:
- col.label("Materials")
+ col.label("Materials:")
col.template_list("MATERIAL_UL_matslots", "layers",
ob, "material_slots",
ob, "active_material_index", rows=2)
mat = ob.active_material
if mat:
- col.label("Available Paint Slots")
+ col.label("Available Paint Slots:")
col.template_list("TEXTURE_UL_texpaintslots", "",
mat, "texture_paint_images",
mat, "paint_active_slot", rows=2)
@@ -1265,16 +1267,17 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
col.separator()
if slot and slot.index != -1:
- col.label("UV Map")
+ col.label("UV Map:")
col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
elif settings.mode == 'IMAGE':
mesh = ob.data
uv_text = mesh.uv_textures.active.name if mesh.uv_textures.active else ""
- col.label("Canvas Image")
- col.template_ID(settings, "canvas")
+ col.label("Canvas Image:")
+ # todo this should be combinded into a single row
+ col.template_ID(settings, "canvas", open="image.open")
col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
- col.label("UV Map")
+ col.label("UV Map:")
col.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False)
col.separator()
@@ -1308,14 +1311,15 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
col.active = ipaint.use_stencil_layer
stencil_text = mesh.uv_texture_stencil.name if mesh.uv_texture_stencil else ""
- col.label("UV Map")
+ col.label("UV Map:")
col.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
- col.label("Stencil Image")
- col.template_ID(ipaint, "stencil_image")
+ col.label("Stencil Image:")
+ # todo this should be combinded into a single row
+ col.template_ID(ipaint, "stencil_image", open="image.open")
col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
- col.label("Visualization")
+ col.label("Visualization:")
row = col.row(align=True)
row.prop(ipaint, "stencil_color", text="")
row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
@@ -1982,7 +1986,7 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
col = layout.column(align=True)
if pe.is_hair:
col.active = pe.is_editable
- col.prop(pe, "use_emitter_deflect", text="Deflect emitter")
+ col.prop(pe, "use_emitter_deflect", text="Deflect Emitter")
sub = col.row(align=True)
sub.active = pe.use_emitter_deflect
sub.prop(pe, "emitter_distance", text="Distance")
diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index ce0b1b62d44..390c043bb31 100644
--- a/release/scripts/startup/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -494,7 +494,7 @@ class BUILTIN_KSI_WholeCharacter(KeyingSetInfo):
# bendy bone properties
def doBBone(ksi, context, ks, pchan):
bone = pchan.bone
-
+
# This check is crude, but is the best we can do for now
# It simply adds all of these if the bbone has segments
# (and the bone is a control bone). This may lead to some
@@ -643,26 +643,29 @@ class BUILTIN_KSI_DeltaScale(KeyingSetInfo):
###############################
+# Note that this controls order of options in 'insert keyframe' menu.
+# Better try to keep some logical order here beyond mere alphabetical one, also because of menu entries shortcut.
+# See also T51867.
classes = (
BUILTIN_KSI_Available,
- BUILTIN_KSI_BendyBones,
- BUILTIN_KSI_DeltaLocation,
- BUILTIN_KSI_DeltaRotation,
- BUILTIN_KSI_DeltaScale,
+ BUILTIN_KSI_Location,
+ BUILTIN_KSI_Rotation,
+ BUILTIN_KSI_Scaling,
BUILTIN_KSI_LocRot,
BUILTIN_KSI_LocRotScale,
BUILTIN_KSI_LocScale,
- BUILTIN_KSI_Location,
BUILTIN_KSI_RotScale,
- BUILTIN_KSI_Rotation,
- BUILTIN_KSI_Scaling,
+ BUILTIN_KSI_DeltaLocation,
+ BUILTIN_KSI_DeltaRotation,
+ BUILTIN_KSI_DeltaScale,
BUILTIN_KSI_VisualLoc,
+ BUILTIN_KSI_VisualRot,
+ BUILTIN_KSI_VisualScaling,
BUILTIN_KSI_VisualLocRot,
BUILTIN_KSI_VisualLocRotScale,
BUILTIN_KSI_VisualLocScale,
- BUILTIN_KSI_VisualRot,
BUILTIN_KSI_VisualRotScale,
- BUILTIN_KSI_VisualScaling,
+ BUILTIN_KSI_BendyBones,
BUILTIN_KSI_WholeCharacter,
BUILTIN_KSI_WholeCharacterSelected,
)
diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py
index 32c61abace7..8ca748c1d66 100644
--- a/release/scripts/templates_py/custom_nodes.py
+++ b/release/scripts/templates_py/custom_nodes.py
@@ -11,7 +11,7 @@ class MyCustomTree(NodeTree):
# Optional identifier string. If not explicitly defined, the python class name is used.
bl_idname = 'CustomTreeType'
# Label for nice name display
- bl_label = 'Custom Node Tree'
+ bl_label = "Custom Node Tree"
# Icon identifier
bl_icon = 'NODETREE'
@@ -23,24 +23,24 @@ class MyCustomSocket(NodeSocket):
# Optional identifier string. If not explicitly defined, the python class name is used.
bl_idname = 'CustomSocketType'
# Label for nice name display
- bl_label = 'Custom Node Socket'
+ bl_label = "Custom Node Socket"
# Enum items list
- my_items = [
- ("DOWN", "Down", "Where your feet are"),
- ("UP", "Up", "Where your head should be"),
- ("LEFT", "Left", "Not right"),
- ("RIGHT", "Right", "Not left")
- ]
+ my_items = (
+ ('DOWN', "Down", "Where your feet are"),
+ ('UP', "Up", "Where your head should be"),
+ ('LEFT', "Left", "Not right"),
+ ('RIGHT', "Right", "Not left")
+ )
- myEnumProperty = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP')
+ my_enum_prop = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP')
# Optional function for drawing the socket input value
def draw(self, context, layout, node, text):
if self.is_output or self.is_linked:
layout.label(text)
else:
- layout.prop(self, "myEnumProperty", text=text)
+ layout.prop(self, "my_enum_prop", text=text)
# Socket color
def draw_color(self, context, node):
@@ -63,7 +63,7 @@ class MyCustomNode(Node, MyCustomTreeNode):
# Optional identifier string. If not explicitly defined, the python class name is used.
bl_idname = 'CustomNodeType'
# Label for nice name display
- bl_label = 'Custom Node'
+ bl_label = "Custom Node"
# Icon identifier
bl_icon = 'SOUND'
@@ -71,8 +71,8 @@ class MyCustomNode(Node, MyCustomTreeNode):
# These work just like custom properties in ID data blocks
# Extensive information can be found under
# http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties
- myStringProperty = bpy.props.StringProperty()
- myFloatProperty = bpy.props.FloatProperty(default=3.1415926)
+ my_string_prop = bpy.props.StringProperty()
+ my_float_prop = bpy.props.FloatProperty(default=3.1415926)
# === Optional Functions ===
# Initialization function, called when a new node is created.
@@ -99,14 +99,14 @@ class MyCustomNode(Node, MyCustomTreeNode):
# Additional buttons displayed on the node.
def draw_buttons(self, context, layout):
layout.label("Node settings")
- layout.prop(self, "myFloatProperty")
+ layout.prop(self, "my_float_prop")
# Detail buttons in the sidebar.
# If this function is not defined, the draw_buttons function is used instead
def draw_buttons_ext(self, context, layout):
- layout.prop(self, "myFloatProperty")
- # myStringProperty button will only be visible in the sidebar
- layout.prop(self, "myStringProperty")
+ layout.prop(self, "my_float_prop")
+ # my_string_prop button will only be visible in the sidebar
+ layout.prop(self, "my_string_prop")
# Optional: custom label
# Explicit user label overrides this, but here we can define a label dynamically
@@ -122,7 +122,6 @@ class MyCustomNode(Node, MyCustomTreeNode):
import nodeitems_utils
from nodeitems_utils import NodeCategory, NodeItem
-
# our own base class with an appropriate poll function,
# so the categories only show up in our own tree type
class MyNodeCategory(NodeCategory):
@@ -130,44 +129,50 @@ class MyNodeCategory(NodeCategory):
def poll(cls, context):
return context.space_data.tree_type == 'CustomTreeType'
+
# all categories in a list
node_categories = [
# identifier, label, items list
- MyNodeCategory("SOMENODES", "Some Nodes", items=[
+ MyNodeCategory('SOMENODES', "Some Nodes", items=[
# our basic node
NodeItem("CustomNodeType"),
- ]),
- MyNodeCategory("OTHERNODES", "Other Nodes", items=[
+ ]),
+ MyNodeCategory('OTHERNODES', "Other Nodes", items=[
# the node item can have additional settings,
# which are applied to new nodes
# NB: settings values are stored as string expressions,
# for this reason they should be converted to strings using repr()
NodeItem("CustomNodeType", label="Node A", settings={
- "myStringProperty": repr("Lorem ipsum dolor sit amet"),
- "myFloatProperty": repr(1.0),
- }),
+ "my_string_prop": repr("Lorem ipsum dolor sit amet"),
+ "my_float_prop": repr(1.0),
+ }),
NodeItem("CustomNodeType", label="Node B", settings={
- "myStringProperty": repr("consectetur adipisicing elit"),
- "myFloatProperty": repr(2.0),
- }),
- ]),
- ]
-
+ "my_string_prop": repr("consectetur adipisicing elit"),
+ "my_float_prop": repr(2.0),
+ }),
+ ]),
+]
+
+classes = (
+ MyCustomTree,
+ MyCustomSocket,
+ MyCustomNode,
+)
def register():
- bpy.utils.register_class(MyCustomTree)
- bpy.utils.register_class(MyCustomSocket)
- bpy.utils.register_class(MyCustomNode)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
- nodeitems_utils.register_node_categories("CUSTOM_NODES", node_categories)
+ nodeitems_utils.register_node_categories('CUSTOM_NODES', node_categories)
def unregister():
- nodeitems_utils.unregister_node_categories("CUSTOM_NODES")
+ nodeitems_utils.unregister_node_categories('CUSTOM_NODES')
- bpy.utils.unregister_class(MyCustomTree)
- bpy.utils.unregister_class(MyCustomSocket)
- bpy.utils.unregister_class(MyCustomNode)
+ from bpy.utils import unregister_class
+ for cls in reversed(classes):
+ unregister_class(cls)
if __name__ == "__main__":
diff --git a/release/scripts/templates_py/gamelogic.py b/release/scripts/templates_py/gamelogic.py
index 01ac27c56cd..e589ad43e63 100644
--- a/release/scripts/templates_py/gamelogic.py
+++ b/release/scripts/templates_py/gamelogic.py
@@ -62,7 +62,7 @@ def main():
# adding to our objects "life" property
"""
actu_collide = cont.sensors["collision_sens"]
- for ob in actu_collide.objectHitList:
+ for ob in actu_collide.hitObjectList:
# Check to see the object has this property
if "life" in ob:
own["life"] += ob["life"]
diff --git a/release/text/copyright.txt b/release/text/copyright.txt
index 207d6f54ea8..d0490b9ca91 100644
--- a/release/text/copyright.txt
+++ b/release/text/copyright.txt
@@ -21,7 +21,7 @@
Subject to the provisions of the GNU GPL license, BF grants You a
non-exclusive right to use the Software at any computer You own or use.
Artwork you create with the Software - whether it is images, movies,
- scripts, exported 3d files or the .blend files themselves - is your sole
+ exported 3d files or the .blend files themselves - is your sole
property, and can be licensed or sold under any conditions you prefer.
2. Permitted copying and electronic distribution of Software
diff --git a/release/windows/blendthumb/CMakeLists.txt b/release/windows/blendthumb/CMakeLists.txt
new file mode 100644
index 00000000000..1e5f5131a36
--- /dev/null
+++ b/release/windows/blendthumb/CMakeLists.txt
@@ -0,0 +1,42 @@
+# ***** 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): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+#-----------------------------------------------------------------------------
+cmake_minimum_required(VERSION 2.8)
+project(BlendThumb)
+
+#Bring the headers, such as Student.h into the project
+include_directories(${ZLIB_INCLUDE})
+
+#Can manually add the sources using the set command as follows:
+set(SOURCES src/BlenderThumb.cpp
+ src/BlendThumb.def
+ src/BlendThumb.rc
+ src/Dll.cpp
+)
+
+add_library(BlendThumb SHARED ${SOURCES})
+target_link_libraries(BlendThumb ${ZLIB_LIBS})
+install (TARGETS BlendThumb DESTINATION bin)
diff --git a/release/windows/blendthumb/src/BlendThumb.def b/release/windows/blendthumb/src/BlendThumb.def
new file mode 100644
index 00000000000..71f9236735f
--- /dev/null
+++ b/release/windows/blendthumb/src/BlendThumb.def
@@ -0,0 +1,5 @@
+EXPORTS
+ DllGetClassObject PRIVATE
+ DllCanUnloadNow PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE \ No newline at end of file
diff --git a/release/windows/blendthumb/src/BlendThumb.rc b/release/windows/blendthumb/src/BlendThumb.rc
new file mode 100644
index 00000000000..5dfd416b0c5
--- /dev/null
+++ b/release/windows/blendthumb/src/BlendThumb.rc
@@ -0,0 +1,26 @@
+#define IDR_VERSION1 1
+
+IDR_VERSION1 VERSIONINFO
+FILEVERSION 1,4,0,0
+PRODUCTVERSION 2,78,0,0
+FILEOS 0x00000004
+FILETYPE 0x00000002
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "FFFF04B0"
+ BEGIN
+ VALUE "FileVersion", "1.4\0"
+ VALUE "ProductVersion", "2.78\0"
+ VALUE "FileDescription", "Blender Thumbnail Handler\0"
+ VALUE "OriginalFilename", "BlendThumb.dll\0"
+ VALUE "ProductName", "Blender\0"
+ VALUE "LegalCopyright", "GPL2, 2016\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 0x04B0
+ END
+END
+
diff --git a/release/windows/blendthumb/src/BlenderThumb.cpp b/release/windows/blendthumb/src/BlenderThumb.cpp
new file mode 100644
index 00000000000..508b9f74852
--- /dev/null
+++ b/release/windows/blendthumb/src/BlenderThumb.cpp
@@ -0,0 +1,324 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <shlwapi.h>
+#include <thumbcache.h> // For IThumbnailProvider.
+#include <new>
+
+#pragma comment(lib, "shlwapi.lib")
+
+// this thumbnail provider implements IInitializeWithStream to enable being hosted
+// in an isolated process for robustness
+
+class CBlendThumb : public IInitializeWithStream, public IThumbnailProvider
+{
+public:
+ CBlendThumb() : _cRef(1), _pStream(NULL) {}
+
+ virtual ~CBlendThumb()
+ {
+ if (_pStream)
+ {
+ _pStream->Release();
+ }
+ }
+
+ // IUnknown
+ IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
+ {
+ static const QITAB qit[] =
+ {
+ QITABENT(CBlendThumb, IInitializeWithStream),
+ QITABENT(CBlendThumb, IThumbnailProvider),
+ { 0 },
+ };
+ return QISearch(this, qit, riid, ppv);
+ }
+
+ IFACEMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&_cRef);
+ }
+
+ IFACEMETHODIMP_(ULONG) Release()
+ {
+ ULONG cRef = InterlockedDecrement(&_cRef);
+ if (!cRef)
+ {
+ delete this;
+ }
+ return cRef;
+ }
+
+ // IInitializeWithStream
+ IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
+
+ // IThumbnailProvider
+ IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
+
+private:
+ long _cRef;
+ IStream *_pStream; // provided during initialization.
+};
+
+HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv)
+{
+ CBlendThumb *pNew = new (std::nothrow) CBlendThumb();
+ HRESULT hr = pNew ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr))
+ {
+ hr = pNew->QueryInterface(riid, ppv);
+ pNew->Release();
+ }
+ return hr;
+}
+
+// IInitializeWithStream
+IFACEMETHODIMP CBlendThumb::Initialize(IStream *pStream, DWORD)
+{
+ HRESULT hr = E_UNEXPECTED; // can only be inited once
+ if (_pStream == NULL)
+ {
+ // take a reference to the stream if we have not been inited yet
+ hr = pStream->QueryInterface(&_pStream);
+ }
+ return hr;
+}
+
+#include <math.h>
+#include <zlib.h>
+#include "Wincodec.h"
+const unsigned char gzip_magic[3] = { 0x1f, 0x8b, 0x08 };
+
+// IThumbnailProvider
+IFACEMETHODIMP CBlendThumb::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha)
+{
+ ULONG BytesRead;
+ HRESULT hr = S_FALSE;
+ LARGE_INTEGER SeekPos;
+
+ // Compressed?
+ unsigned char in_magic[3];
+ _pStream->Read(&in_magic,3,&BytesRead);
+ bool gzipped = true;
+ for ( int i=0; i < 3; i++ )
+ if ( in_magic[i] != gzip_magic[i] )
+ {
+ gzipped = false;
+ break;
+ }
+
+ if (gzipped)
+ {
+ // Zlib inflate
+ z_stream stream;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ // Get compressed file length
+ SeekPos.QuadPart = 0;
+ _pStream->Seek(SeekPos,STREAM_SEEK_END,NULL);
+
+ // Get compressed and uncompressed size
+ uLong source_size;
+ uLongf dest_size;
+ //SeekPos.QuadPart = -4; // last 4 bytes define size of uncompressed file
+ //ULARGE_INTEGER Tell;
+ //_pStream->Seek(SeekPos,STREAM_SEEK_END,&Tell);
+ //source_size = (uLong)Tell.QuadPart + 4; // src
+ //_pStream->Read(&dest_size,4,&BytesRead); // dest
+ dest_size = 1024*70; // thumbnail is currently always inside the first 65KB...if it moves or enlargens this line will have to change or go!
+ source_size = (uLong)max(SeekPos.QuadPart,dest_size); // for safety, assume no compression
+
+ // Input
+ Bytef* src = new Bytef[source_size];
+ stream.next_in = (Bytef*)src;
+ stream.avail_in = (uInt)source_size;
+
+ // Output
+ Bytef* dest = new Bytef[dest_size];
+ stream.next_out = (Bytef*)dest;
+ stream.avail_out = dest_size;
+
+ // IStream to src
+ SeekPos.QuadPart = 0;
+ _pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
+ _pStream->Read(src,source_size,&BytesRead);
+
+ // Do the inflation
+ int err;
+ err = inflateInit2(&stream,16); // 16 means "gzip"...nice!
+ err = inflate(&stream, Z_FINISH);
+ err = inflateEnd(&stream);
+
+ // Replace the IStream, which is read-only
+ _pStream->Release();
+ _pStream = SHCreateMemStream(dest,dest_size);
+
+ delete[] src;
+ delete[] dest;
+ }
+
+ // Blender version, early out if sub 2.5
+ SeekPos.QuadPart = 9;
+ _pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
+ char version[4];
+ version[3] = '\0';
+ _pStream->Read(&version,3,&BytesRead);
+ if ( BytesRead != 3)
+ return E_UNEXPECTED;
+ int iVersion = atoi(version);
+ if ( iVersion < 250 )
+ return S_FALSE;
+
+ // 32 or 64 bit blend?
+ SeekPos.QuadPart = 7;
+ _pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
+
+ char _PointerSize;
+ _pStream->Read(&_PointerSize,1,&BytesRead);
+
+ int PointerSize = _PointerSize == '_' ? 4 : 8;
+ int HeaderSize = 16 + PointerSize;
+
+ // Find and read thumbnail ("TEST") block
+ SeekPos.QuadPart = 12;
+ _pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
+ int BlockOffset = 12;
+ while ( _pStream )
+ {
+ // Scan current block
+ char BlockName[5];
+ BlockName[4] = '\0';
+ int BlockSize = 0;
+
+ if (_pStream->Read(BlockName,4,&BytesRead) == S_OK && _pStream->Read((void*)&BlockSize,4,&BytesRead) == S_OK)
+ {
+ if ( strcmp (BlockName,"TEST") != 0 )
+ {
+ SeekPos.QuadPart = BlockOffset += HeaderSize + BlockSize;
+ _pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
+ continue;
+ }
+ }
+ else break; // eof
+
+ // Found the block
+ SeekPos.QuadPart = BlockOffset + HeaderSize;
+ _pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
+
+ int width, height;
+ _pStream->Read((char*)&width,4,&BytesRead);
+ _pStream->Read((char*)&height,4,&BytesRead);
+ BlockSize -= 8;
+
+ // Isolate RGBA data
+ char* pRGBA = new char[BlockSize];
+ _pStream->Read(pRGBA,BlockSize,&BytesRead);
+
+ if (BytesRead != (ULONG)BlockSize)
+ return E_UNEXPECTED;
+
+ // Convert to BGRA for Windows
+ for (int i=0; i < BlockSize; i+=4 )
+ {
+ #define RED_BYTE pRGBA[i]
+ #define BLUE_BYTE pRGBA[i+2]
+
+ char red = RED_BYTE;
+ RED_BYTE = BLUE_BYTE;
+ BLUE_BYTE = red;
+ }
+
+ // Flip vertically (Blender stores it upside-down)
+ unsigned int LineSize = width*4;
+ char* FlippedImage = new char[BlockSize];
+ for (int i=0; i<height; i++)
+ {
+ if ( 0 != memcpy_s(&FlippedImage[ (height - i - 1)*LineSize ],LineSize,&pRGBA[ i*LineSize ],LineSize))
+ return E_UNEXPECTED;
+ }
+ delete[] pRGBA;
+ pRGBA = FlippedImage;
+
+ // Create image
+ *phbmp = CreateBitmap(width,height,1,32,pRGBA);
+ if (!*phbmp)
+ return E_FAIL;
+ *pdwAlpha = WTSAT_ARGB; // it's actually BGRA, not sure why this works
+
+ // Scale down if required
+ if ( (unsigned)width > cx || (unsigned)height > cx )
+ {
+ float scale = 1.0f / (max(width,height) / (float)cx);
+ LONG NewWidth = (LONG)(width *scale);
+ LONG NewHeight = (LONG)(height *scale);
+
+#ifdef _DEBUG
+#if 1
+ MessageBox(0,L"Attach now",L"Debugging",MB_OK);
+#endif
+#endif
+ IWICImagingFactory *pImgFac;
+ hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImgFac));
+
+ IWICBitmap* WICBmp;
+ hr = pImgFac->CreateBitmapFromHBITMAP(*phbmp,0,WICBitmapUseAlpha,&WICBmp);
+
+ BITMAPINFO bmi = {};
+ bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
+ bmi.bmiHeader.biWidth = NewWidth;
+ bmi.bmiHeader.biHeight = -NewHeight;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+
+ BYTE *pBits;
+ HBITMAP ResizedHBmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);
+ hr = ResizedHBmp ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr))
+ {
+ IWICBitmapScaler* pIScaler;
+ hr = pImgFac->CreateBitmapScaler(&pIScaler);
+ hr = pIScaler->Initialize(WICBmp,NewWidth,NewHeight,WICBitmapInterpolationModeFant);
+
+ WICRect rect = {0, 0, NewWidth, NewHeight};
+ hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits);
+
+ if (SUCCEEDED(hr))
+ {
+ DeleteObject(*phbmp);
+ *phbmp = ResizedHBmp;
+ }
+ else
+ DeleteObject(ResizedHBmp);
+
+ pIScaler->Release();
+ }
+ WICBmp->Release();
+ pImgFac->Release();
+ }
+ else
+ hr = S_OK;
+ break;
+ }
+ return hr;
+}
diff --git a/release/windows/blendthumb/src/Dll.cpp b/release/windows/blendthumb/src/Dll.cpp
new file mode 100644
index 00000000000..09ccd34ff8e
--- /dev/null
+++ b/release/windows/blendthumb/src/Dll.cpp
@@ -0,0 +1,277 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <objbase.h>
+#include <shlwapi.h>
+#include <thumbcache.h> // For IThumbnailProvider.
+#include <shlobj.h> // For SHChangeNotify
+#include <new>
+
+extern HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv);
+
+#define SZ_CLSID_BLENDTHUMBHANDLER L"{D45F043D-F17F-4e8a-8435-70971D9FA46D}"
+#define SZ_BLENDTHUMBHANDLER L"Blender Thumbnail Handler"
+const CLSID CLSID_BlendThumbHandler = { 0xd45f043d, 0xf17f, 0x4e8a, { 0x84, 0x35, 0x70, 0x97, 0x1d, 0x9f, 0xa4, 0x6d } };
+
+typedef HRESULT (*PFNCREATEINSTANCE)(REFIID riid, void **ppvObject);
+struct CLASS_OBJECT_INIT
+{
+ const CLSID *pClsid;
+ PFNCREATEINSTANCE pfnCreate;
+};
+
+// add classes supported by this module here
+const CLASS_OBJECT_INIT c_rgClassObjectInit[] =
+{
+ { &CLSID_BlendThumbHandler, CBlendThumb_CreateInstance }
+};
+
+
+long g_cRefModule = 0;
+
+// Handle the the DLL's module
+HINSTANCE g_hInst = NULL;
+
+// Standard DLL functions
+STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, void *)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ g_hInst = hInstance;
+ DisableThreadLibraryCalls(hInstance);
+ }
+ return TRUE;
+}
+
+STDAPI DllCanUnloadNow()
+{
+ // Only allow the DLL to be unloaded after all outstanding references have been released
+ return (g_cRefModule == 0) ? S_OK : S_FALSE;
+}
+
+void DllAddRef()
+{
+ InterlockedIncrement(&g_cRefModule);
+}
+
+void DllRelease()
+{
+ InterlockedDecrement(&g_cRefModule);
+}
+
+class CClassFactory : public IClassFactory
+{
+public:
+ static HRESULT CreateInstance(REFCLSID clsid, const CLASS_OBJECT_INIT *pClassObjectInits, size_t cClassObjectInits, REFIID riid, void **ppv)
+ {
+ *ppv = NULL;
+ HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
+ for (size_t i = 0; i < cClassObjectInits; i++)
+ {
+ if (clsid == *pClassObjectInits[i].pClsid)
+ {
+ IClassFactory *pClassFactory = new (std::nothrow) CClassFactory(pClassObjectInits[i].pfnCreate);
+ hr = pClassFactory ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr))
+ {
+ hr = pClassFactory->QueryInterface(riid, ppv);
+ pClassFactory->Release();
+ }
+ break; // match found
+ }
+ }
+ return hr;
+ }
+
+ CClassFactory(PFNCREATEINSTANCE pfnCreate) : _cRef(1), _pfnCreate(pfnCreate)
+ {
+ DllAddRef();
+ }
+
+ // IUnknown
+ IFACEMETHODIMP QueryInterface(REFIID riid, void ** ppv)
+ {
+ static const QITAB qit[] =
+ {
+ QITABENT(CClassFactory, IClassFactory),
+ { 0 }
+ };
+ return QISearch(this, qit, riid, ppv);
+ }
+
+ IFACEMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&_cRef);
+ }
+
+ IFACEMETHODIMP_(ULONG) Release()
+ {
+ long cRef = InterlockedDecrement(&_cRef);
+ if (cRef == 0)
+ {
+ delete this;
+ }
+ return cRef;
+ }
+
+ // IClassFactory
+ IFACEMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
+ {
+ return punkOuter ? CLASS_E_NOAGGREGATION : _pfnCreate(riid, ppv);
+ }
+
+ IFACEMETHODIMP LockServer(BOOL fLock)
+ {
+ if (fLock)
+ {
+ DllAddRef();
+ }
+ else
+ {
+ DllRelease();
+ }
+ return S_OK;
+ }
+
+private:
+ ~CClassFactory()
+ {
+ DllRelease();
+ }
+
+ long _cRef;
+ PFNCREATEINSTANCE _pfnCreate;
+};
+
+STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv)
+{
+ return CClassFactory::CreateInstance(clsid, c_rgClassObjectInit, ARRAYSIZE(c_rgClassObjectInit), riid, ppv);
+}
+
+// A struct to hold the information required for a registry entry
+
+struct REGISTRY_ENTRY
+{
+ HKEY hkeyRoot;
+ PCWSTR pszKeyName;
+ PCWSTR pszValueName;
+ DWORD dwValueType;
+ PCWSTR pszData;
+};
+
+// Creates a registry key (if needed) and sets the default value of the key
+
+HRESULT CreateRegKeyAndSetValue(const REGISTRY_ENTRY *pRegistryEntry)
+{
+ HKEY hKey;
+ HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(pRegistryEntry->hkeyRoot, pRegistryEntry->pszKeyName,
+ 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL));
+ if (SUCCEEDED(hr))
+ {
+ // All this just to support REG_DWORD...
+ DWORD size;
+ DWORD data;
+ BYTE* lpData = (LPBYTE) pRegistryEntry->pszData;
+ switch (pRegistryEntry->dwValueType)
+ {
+ case REG_SZ:
+ size = ((DWORD) wcslen(pRegistryEntry->pszData) + 1) * sizeof(WCHAR);
+ break;
+ case REG_DWORD:
+ size = sizeof(DWORD);
+ data = (DWORD)pRegistryEntry->pszData;
+ lpData = (BYTE*)&data;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+
+ hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, pRegistryEntry->pszValueName, 0, pRegistryEntry->dwValueType,
+ lpData, size ));
+ RegCloseKey(hKey);
+ }
+ return hr;
+}
+
+//
+// Registers this COM server
+//
+STDAPI DllRegisterServer()
+{
+ HRESULT hr;
+
+ WCHAR szModuleName[MAX_PATH];
+
+ if (!GetModuleFileNameW(g_hInst, szModuleName, ARRAYSIZE(szModuleName)))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else
+ {
+ const REGISTRY_ENTRY rgRegistryEntries[] =
+ {
+ // RootKey KeyName ValueName ValueType Data
+ {HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER, NULL, REG_SZ, SZ_BLENDTHUMBHANDLER},
+ {HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32", NULL, REG_SZ, szModuleName},
+ {HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32", L"ThreadingModel", REG_SZ, L"Apartment"},
+ {HKEY_CURRENT_USER, L"Software\\Classes\\.blend\\", L"Treatment", REG_DWORD, 0}, // doesn't appear to do anything...
+ {HKEY_CURRENT_USER, L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}", NULL, REG_SZ, SZ_CLSID_BLENDTHUMBHANDLER},
+ };
+
+ hr = S_OK;
+ for (int i = 0; i < ARRAYSIZE(rgRegistryEntries) && SUCCEEDED(hr); i++)
+ {
+ hr = CreateRegKeyAndSetValue(&rgRegistryEntries[i]);
+ }
+ }
+ if (SUCCEEDED(hr))
+ {
+ // This tells the shell to invalidate the thumbnail cache. This is important because any .blend files
+ // viewed before registering this handler would otherwise show cached blank thumbnails.
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
+ }
+ return hr;
+}
+
+//
+// Unregisters this COM server
+//
+STDAPI DllUnregisterServer()
+{
+ HRESULT hr = S_OK;
+
+ const PCWSTR rgpszKeys[] =
+ {
+ L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER,
+ L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}"
+ };
+
+ // Delete the registry entries
+ for (int i = 0; i < ARRAYSIZE(rgpszKeys) && SUCCEEDED(hr); i++)
+ {
+ hr = HRESULT_FROM_WIN32(RegDeleteTreeW(HKEY_CURRENT_USER, rgpszKeys[i]));
+ if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
+ {
+ // If the registry entry has already been deleted, say S_OK.
+ hr = S_OK;
+ }
+ }
+ return hr;
+}
diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc
index 1d2bc689027..d6e7a80d174 100644
--- a/source/blender/alembic/intern/abc_customdata.cc
+++ b/source/blender/alembic/intern/abc_customdata.cc
@@ -252,7 +252,31 @@ static void read_uvs(const CDStreamConfig &config, void *data,
}
}
-static void read_custom_data_mcols(const ICompoundProperty &arbGeomParams,
+static size_t mcols_out_of_bounds_check(
+ const size_t color_index,
+ const size_t array_size,
+ const std::string & iobject_full_name,
+ const PropertyHeader &prop_header,
+ bool &r_bounds_warning_given)
+{
+ if (color_index < array_size) {
+ return color_index;
+ }
+
+ if (!r_bounds_warning_given) {
+ std::cerr << "Alembic: color index out of bounds "
+ "reading face colors for object "
+ << iobject_full_name
+ << ", property "
+ << prop_header.getName() << std::endl;
+ r_bounds_warning_given = true;
+ }
+
+ return 0;
+}
+
+static void read_custom_data_mcols(const std::string & iobject_full_name,
+ const ICompoundProperty &arbGeomParams,
const PropertyHeader &prop_header,
const CDStreamConfig &config,
const Alembic::Abc::ISampleSelector &iss)
@@ -303,6 +327,8 @@ static void read_custom_data_mcols(const ICompoundProperty &arbGeomParams,
size_t face_index = 0;
size_t color_index;
+ bool bounds_warning_given = false;
+
for (int i = 0; i < config.totpoly; ++i) {
MPoly *poly = &mpolys[i];
MCol *cface = &cfaces[poly->loopstart + poly->totloop];
@@ -311,9 +337,14 @@ static void read_custom_data_mcols(const ICompoundProperty &arbGeomParams,
for (int j = 0; j < poly->totloop; ++j, ++face_index) {
--cface;
--mloop;
- color_index = is_facevarying ? face_index : mloop->v;
if (use_c3f_ptr) {
+ color_index = mcols_out_of_bounds_check(
+ is_facevarying ? face_index : mloop->v,
+ c3f_ptr->size(),
+ iobject_full_name, prop_header,
+ bounds_warning_given);
+
const Imath::C3f &color = (*c3f_ptr)[color_index];
cface->a = FTOCHAR(color[0]);
cface->r = FTOCHAR(color[1]);
@@ -321,6 +352,12 @@ static void read_custom_data_mcols(const ICompoundProperty &arbGeomParams,
cface->b = 255;
}
else {
+ color_index = mcols_out_of_bounds_check(
+ is_facevarying ? face_index : mloop->v,
+ c4f_ptr->size(),
+ iobject_full_name, prop_header,
+ bounds_warning_given);
+
const Imath::C4f &color = (*c4f_ptr)[color_index];
cface->a = FTOCHAR(color[0]);
cface->r = FTOCHAR(color[1]);
@@ -356,7 +393,10 @@ static void read_custom_data_uvs(const ICompoundProperty &prop,
read_uvs(config, cd_data, sample.getVals(), sample.getIndices());
}
-void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss)
+void read_custom_data(const std::string & iobject_full_name,
+ const ICompoundProperty &prop,
+ const CDStreamConfig &config,
+ const Alembic::Abc::ISampleSelector &iss)
{
if (!prop.valid()) {
return;
@@ -386,7 +426,7 @@ void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &confi
continue;
}
- read_custom_data_mcols(prop, prop_header, config, iss);
+ read_custom_data_mcols(iobject_full_name, prop, prop_header, config, iss);
continue;
}
}
diff --git a/source/blender/alembic/intern/abc_customdata.h b/source/blender/alembic/intern/abc_customdata.h
index 9e671fde386..b3072a2c9f7 100644
--- a/source/blender/alembic/intern/abc_customdata.h
+++ b/source/blender/alembic/intern/abc_customdata.h
@@ -96,7 +96,8 @@ void write_custom_data(const OCompoundProperty &prop,
CustomData *data,
int data_type);
-void read_custom_data(const ICompoundProperty &prop,
+void read_custom_data(const std::string & iobject_full_name,
+ const ICompoundProperty &prop,
const CDStreamConfig &config,
const Alembic::Abc::ISampleSelector &iss);
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index 3da67ac0865..4fe65b96f36 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -131,13 +131,12 @@ static bool object_type_is_exportable(Object *ob)
/**
* Returns whether this object should be exported into the Alembic file.
*
- * @param settings export settings, used for options like 'selected only'.
- * @param ob the object in question.
- * @param is_duplicated normally false; true when the object is instanced
- * into the scene by a dupli-object (e.g. part of a
- * dupligroup). This ignores selection and layer
- * visibility, and assumes that the dupli-object itself
- * (e.g. the group-instantiating empty) is exported.
+ * \param settings: export settings, used for options like 'selected only'.
+ * \param ob: the object in question.
+ * \param is_duplicated: Normally false; true when the object is instanced
+ * into the scene by a dupli-object (e.g. part of a dupligroup).
+ * This ignores selection and layer visibility,
+ * and assumes that the dupli-object itself (e.g. the group-instantiating empty) is exported.
*/
static bool export_object(const ExportSettings * const settings, Object *ob,
bool is_duplicated)
@@ -428,7 +427,7 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare
/* check if we have already created a transform writer for this object */
AbcTransformWriter *my_writer = getXForm(name);
- if (my_writer != NULL){
+ if (my_writer != NULL) {
return my_writer;
}
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index 9a4ca6f99a8..6545ced8e4a 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -681,17 +681,17 @@ static void assign_materials(Main *bmain, Object *ob, const std::map<std::string
std::string mat_name = it->first;
mat_iter = mat_map.find(mat_name.c_str());
- Material *assigned_name;
+ Material *assigned_mat;
if (mat_iter == mat_map.end()) {
- assigned_name = BKE_material_add(bmain, mat_name.c_str());
- mat_map[mat_name] = assigned_name;
+ assigned_mat = BKE_material_add(bmain, mat_name.c_str());
+ mat_map[mat_name] = assigned_mat;
}
else {
- assigned_name = mat_iter->second;
+ assigned_mat = mat_iter->second;
}
- assign_material(ob, assigned_name, it->second, BKE_MAT_ASSIGN_OBDATA);
+ assign_material(ob, assigned_mat, it->second, BKE_MAT_ASSIGN_OBDATA);
}
}
}
@@ -943,7 +943,8 @@ static void get_weight_and_index(CDStreamConfig &config,
config.ceil_index = i1;
}
-static void read_mesh_sample(ImportSettings *settings,
+static void read_mesh_sample(const std::string & iobject_full_name,
+ ImportSettings *settings,
const IPolyMeshSchema &schema,
const ISampleSelector &selector,
CDStreamConfig &config,
@@ -981,10 +982,9 @@ static void read_mesh_sample(ImportSettings *settings,
}
if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
- read_custom_data(schema.getArbGeomParams(), config, selector);
+ read_custom_data(iobject_full_name,
+ schema.getArbGeomParams(), config, selector);
}
-
- /* TODO: face sets */
}
CDStreamConfig get_config(DerivedMesh *dm)
@@ -1112,7 +1112,8 @@ DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm,
config.time = sample_sel.getRequestedTime();
bool do_normals = false;
- read_mesh_sample(&settings, m_schema, sample_sel, config, do_normals);
+ read_mesh_sample(m_iobject.getFullName(),
+ &settings, m_schema, sample_sel, config, do_normals);
if (new_dm) {
/* Check if we had ME_SMOOTH flag set to restore it. */
@@ -1123,6 +1124,16 @@ DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm,
CDDM_calc_normals(new_dm);
CDDM_calc_edges(new_dm);
+ /* Here we assume that the number of materials doesn't change, i.e. that
+ * the material slots that were created when the object was loaded from
+ * Alembic are still valid now. */
+ size_t num_polys = new_dm->getNumPolys(new_dm);
+ if (num_polys > 0) {
+ MPoly *dmpolies = new_dm->getPolyArray(new_dm);
+ std::map<std::string, int> mat_map;
+ assign_facesets_to_mpoly(sample_sel, 0, dmpolies, num_polys, mat_map);
+ }
+
return new_dm;
}
@@ -1133,8 +1144,11 @@ DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm,
return dm;
}
-void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
- const ISampleSelector &sample_sel)
+void AbcMeshReader::assign_facesets_to_mpoly(
+ const ISampleSelector &sample_sel,
+ size_t poly_start,
+ MPoly *mpoly, int totpoly,
+ std::map<std::string, int> & r_mat_map)
{
std::vector<std::string> face_sets;
m_schema.getFaceSetNames(face_sets);
@@ -1143,21 +1157,21 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_star
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++;
+ if (r_mat_map.find(grp_name) == r_mat_map.end()) {
+ r_mat_map[grp_name] = 1 + current_mat++;
}
- const int assigned_mat = mat_map[grp_name];
+ const int assigned_mat = r_mat_map[grp_name];
const IFaceSet faceset = m_schema.getFaceSet(grp_name);
if (!faceset.valid()) {
+ std::cerr << " Face set " << grp_name << " invalid for " << m_object_name << "\n";
continue;
}
@@ -1169,16 +1183,25 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_star
for (size_t l = 0; l < num_group_faces; l++) {
size_t pos = (*group_faces)[l] + poly_start;
- if (pos >= mesh->totpoly) {
+ if (pos >= totpoly) {
std::cerr << "Faceset overflow on " << faceset.getName() << '\n';
break;
}
- MPoly &poly = mesh->mpoly[pos];
+ MPoly &poly = mpoly[pos];
poly.mat_nr = assigned_mat - 1;
}
}
+}
+
+void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
+ const ISampleSelector &sample_sel)
+{
+ std::map<std::string, int> mat_map;
+ assign_facesets_to_mpoly(sample_sel,
+ poly_start, mesh->mpoly, mesh->totpoly,
+ mat_map);
utils::assign_materials(bmain, m_object, mat_map);
}
@@ -1197,7 +1220,8 @@ ABC_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2)
return NULL;
}
-static void read_subd_sample(ImportSettings *settings,
+static void read_subd_sample(const std::string & iobject_full_name,
+ ImportSettings *settings,
const ISubDSchema &schema,
const ISampleSelector &selector,
CDStreamConfig &config)
@@ -1232,10 +1256,9 @@ static void read_subd_sample(ImportSettings *settings,
}
if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
- read_custom_data(schema.getArbGeomParams(), config, selector);
+ read_custom_data(iobject_full_name,
+ schema.getArbGeomParams(), config, selector);
}
-
- /* TODO: face sets */
}
/* ************************************************************************** */
@@ -1364,7 +1387,8 @@ DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm,
/* Only read point data when streaming meshes, unless we need to create new ones. */
CDStreamConfig config = get_config(new_dm ? new_dm : dm);
config.time = sample_sel.getRequestedTime();
- read_subd_sample(&settings, m_schema, sample_sel, config);
+ read_subd_sample(m_iobject.getFullName(),
+ &settings, m_schema, sample_sel, config);
if (new_dm) {
/* Check if we had ME_SMOOTH flag set to restore it. */
diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h
index 6bf1dde3d1d..5c1eb01d8e0 100644
--- a/source/blender/alembic/intern/abc_mesh.h
+++ b/source/blender/alembic/intern/abc_mesh.h
@@ -112,6 +112,11 @@ public:
private:
void readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
const Alembic::AbcGeom::ISampleSelector &sample_sel);
+
+ void assign_facesets_to_mpoly(const Alembic::Abc::ISampleSelector &sample_sel,
+ size_t poly_start,
+ MPoly *mpoly, int totpoly,
+ std::map<std::string, int> & r_mat_map);
};
/* ************************************************************************** */
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index 04f6da48711..6c4cb60d63c 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -140,6 +140,38 @@ AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings
else {
m_object_name = m_data_name = parts[parts.size() - 1];
}
+
+ determine_inherits_xform();
+}
+
+/* Determine whether we can inherit our parent's XForm */
+void AbcObjectReader::determine_inherits_xform()
+{
+ m_inherits_xform = false;
+
+ IXform ixform = xform();
+ if (!ixform) {
+ return;
+ }
+
+ const IXformSchema & schema(ixform.getSchema());
+ if (!schema.valid()) {
+ std::cerr << "Alembic object " << ixform.getFullName()
+ << " has an invalid schema." << std::endl;
+ return;
+ }
+
+ m_inherits_xform = schema.getInheritsXforms();
+
+ IObject ixform_parent = ixform.getParent();
+ if (!ixform_parent.getParent()) {
+ /* The archive top object certainly is not a transform itself, so handle
+ * it as "no parent". */
+ m_inherits_xform = false;
+ }
+ else {
+ m_inherits_xform = ixform_parent && m_inherits_xform;
+ }
}
AbcObjectReader::~AbcObjectReader()
@@ -286,32 +318,10 @@ void AbcObjectReader::read_matrix(float r_mat[4][4], const float time,
return;
}
- bool has_alembic_parent;
- IObject ixform_parent = ixform.getParent();
- if (!ixform_parent.getParent()) {
- /* The archive top object certainly is not a transform itself, so handle
- * it as "no parent". */
- has_alembic_parent = false;
- }
- else {
- has_alembic_parent = ixform_parent && schema.getInheritsXforms();
-
- if (has_alembic_parent && m_object->parent == NULL) {
- /* TODO Sybren: This happened in some files. I think I solved it,
- * but I'll leave this check in here anyway until we've tested it
- * more thoroughly. Better than crashing on a null parent anyway. */
- std::cerr << "Alembic object " << m_iobject.getFullName()
- << " with transform " << ixform.getFullName()
- << " has an Alembic parent but no parent Blender object."
- << std::endl;
- has_alembic_parent = false;
- }
- }
-
const Imath::M44d matrix = get_matrix(schema, time);
convert_matrix(matrix, m_object, r_mat);
- if (has_alembic_parent) {
+ if (m_inherits_xform) {
/* In this case, the matrix in Alembic is in local coordinates, so
* convert to world matrix. To prevent us from reading and accumulating
* all parent matrices in the Alembic file, we assume that the Blender
diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h
index 1462f93a422..852ef451f23 100644
--- a/source/blender/alembic/intern/abc_object.h
+++ b/source/blender/alembic/intern/abc_object.h
@@ -90,7 +90,7 @@ struct ImportSettings {
/* Length and frame offset of file sequences. */
int sequence_len;
- int offset;
+ int sequence_offset;
/* From MeshSeqCacheModifierData.read_flag */
int read_flag;
@@ -107,7 +107,7 @@ struct ImportSettings {
, is_sequence(false)
, set_frame_range(false)
, sequence_len(1)
- , offset(0)
+ , sequence_offset(0)
, read_flag(0)
, validate_meshes(false)
, cache_file(NULL)
@@ -143,6 +143,8 @@ protected:
* modifiers and/or constraints. */
int m_refcount;
+ bool m_inherits_xform;
+
public:
AbcObjectReader *parent_reader;
@@ -167,6 +169,7 @@ public:
const std::string & name() const { return m_name; }
const std::string & object_name() const { return m_object_name; }
const std::string & data_name() const { return m_data_name; }
+ bool inherits_xform() const { return m_inherits_xform; }
virtual bool valid() const = 0;
virtual bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
@@ -194,6 +197,9 @@ public:
void read_matrix(float r_mat[4][4], const float time,
const float scale, bool &is_constant);
+
+protected:
+ void determine_inherits_xform();
};
Imath::M44d get_matrix(const Alembic::AbcGeom::IXformSchema &schema, const float time);
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index 67d2d3b1eb2..24a508e8292 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -142,7 +142,7 @@ void create_swapped_rotation_matrix(
float rz;
/* Apply transformation */
- switch(mode) {
+ switch (mode) {
case ABC_ZUP_FROM_YUP:
ry = -euler[2];
rz = euler[1];
@@ -217,7 +217,7 @@ void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMod
copy_m4_m3(dst_mat, dst_rot);
/* Apply translation */
- switch(mode) {
+ switch (mode) {
case ABC_ZUP_FROM_YUP:
copy_zup_from_yup(dst_mat[3], src_trans);
break;
@@ -370,10 +370,10 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe
reader = new AbcCurveReader(object, settings);
}
else {
- std::cerr << "Alembic: unknown how to handle objects of schema "
+ std::cerr << "Alembic: unknown how to handle objects of schema '"
<< md.get("schemaObjTitle")
- << ", skipping object "
- << object.getFullName() << std::endl;
+ << "', skipping object '"
+ << object.getFullName() << "'" << std::endl;
}
return reader;
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index 74d0faf97d3..2526958111a 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -33,7 +33,7 @@
#endif
/**
- * @brief The CacheReader struct is only used for anonymous pointers,
+ * \brief The CacheReader struct is only used for anonymous pointers,
* to interface between C and C++ code. This library only creates
* pointers to AbcObjectReader (or subclasses thereof).
*/
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 5ac73175e5b..5503dcb1527 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -452,7 +452,8 @@ static std::pair<bool, AbcObjectReader *> visit_object(
else {
if (child_claims_this_object) {
claiming_child_readers.push_back(child_reader);
- } else {
+ }
+ else {
nonclaiming_child_readers.push_back(child_reader);
}
}
@@ -742,7 +743,7 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
Scene *scene = data->scene;
if (data->settings.is_sequence) {
- SFRA = data->settings.offset;
+ SFRA = data->settings.sequence_offset;
EFRA = SFRA + (data->settings.sequence_len - 1);
CFRA = SFRA;
}
@@ -759,7 +760,7 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
const AbcObjectReader *parent_reader = reader->parent_reader;
Object *ob = reader->object();
- if (parent_reader == NULL) {
+ if (parent_reader == NULL || !reader->inherits_xform()) {
ob->parent = NULL;
}
else {
@@ -869,7 +870,7 @@ bool ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
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.sequence_offset = offset;
job->settings.validate_meshes = validate_meshes;
job->error_code = ABC_NO_ERROR;
job->was_cancelled = false;
@@ -989,6 +990,10 @@ CacheReader *CacheReader_open_alembic_object(AbcArchiveHandle *handle, CacheRead
ImportSettings settings;
AbcObjectReader *abc_reader = create_reader(iobject, settings);
+ if (abc_reader == NULL) {
+ /* This object is not supported */
+ return NULL;
+ }
abc_reader->object(object);
abc_reader->incref();
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 1f38d64924c..8c8aef3de57 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -38,7 +38,7 @@ struct rctf;
struct ColorManagedDisplay;
struct ResultBLF;
-int BLF_init(int points, int dpi);
+int BLF_init(void);
void BLF_exit(void);
void BLF_default_dpi(int dpi);
void BLF_default_set(int fontid);
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 132a0ec3808..5bd62980b6d 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -96,15 +96,16 @@ static FontBLF *blf_get(int fontid)
return NULL;
}
-int BLF_init(int points, int dpi)
+int BLF_init(void)
{
int i;
for (i = 0; i < BLF_MAX_FONT; i++)
global_font[i] = NULL;
- global_font_points = points;
- global_font_dpi = dpi;
+ global_font_points = 11;
+ global_font_dpi = 72;
+
return blf_font_init();
}
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 789bc8df7e5..e2577689101 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -201,7 +201,7 @@ struct DerivedMesh {
/* use for converting to BMesh which doesn't store bevel weight and edge crease by default */
char cd_flag;
- char tangent_mask; /* which tangent layers are calculated */
+ short tangent_mask; /* which tangent layers are calculated */
/** Calculate vert and face normals */
void (*calcNormals)(DerivedMesh *dm);
@@ -220,7 +220,7 @@ struct DerivedMesh {
/** Recalculates mesh tessellation */
void (*recalcTessellation)(DerivedMesh *dm);
- /** Loop tessellation cache */
+ /** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */
void (*recalcLoopTri)(DerivedMesh *dm);
/** accessor functions */
const struct MLoopTri *(*getLoopTriArray)(DerivedMesh * dm);
@@ -625,7 +625,6 @@ void DM_ensure_normals(DerivedMesh *dm);
void DM_ensure_tessface(DerivedMesh *dm);
void DM_ensure_looptri_data(DerivedMesh *dm);
-void DM_ensure_looptri(DerivedMesh *dm);
void DM_verttri_from_looptri(MVertTri *verttri, const MLoop *mloop, const MLoopTri *looptri, int looptri_num);
void DM_update_tessface_data(DerivedMesh *dm);
@@ -791,11 +790,13 @@ void DM_calc_tangents_names_from_gpu(
void DM_add_named_tangent_layer_for_uv(
CustomData *uv_data, CustomData *tan_data, int numLoopData,
const char *layer_name);
+
+#define DM_TANGENT_MASK_ORCO (1 << 9)
void DM_calc_loop_tangents_step_0(
const CustomData *loopData, bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME], int tangent_names_count,
bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
- char *ract_uv_name, char *rren_uv_name, char *rtangent_mask);
+ char *ract_uv_name, char *rren_uv_name, short *rtangent_mask);
void DM_calc_loop_tangents(
DerivedMesh *dm, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME],
int tangent_names_count);
@@ -830,11 +831,5 @@ struct MEdge *DM_get_edge_array(struct DerivedMesh *dm, bool *r_allocated);
struct MLoop *DM_get_loop_array(struct DerivedMesh *dm, bool *r_allocated);
struct MPoly *DM_get_poly_array(struct DerivedMesh *dm, bool *r_allocated);
struct MFace *DM_get_tessface_array(struct DerivedMesh *dm, bool *r_allocated);
-const MLoopTri *DM_get_looptri_array(
- DerivedMesh *dm,
- const MVert *mvert,
- const MPoly *mpoly, int mpoly_len,
- const MLoop *mloop, int mloop_len,
- bool *r_allocated);
#endif /* __BKE_DERIVEDMESH_H__ */
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 6527ba7f94f..28be2b04c71 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -57,8 +57,9 @@ extern "C" {
/* Allocate a new bAction with the given name */
struct bAction *add_empty_action(struct Main *bmain, const char name[]);
-/* Allocate a copy of the given Action and all its data */
-struct bAction *BKE_action_copy(struct Main *bmain, struct bAction *src);
+void BKE_action_copy_data(struct Main *bmain, struct bAction *act_dst, const struct bAction *act_src, const int flag);
+/* Allocate a copy of the given Action and all its data */
+struct bAction *BKE_action_copy(struct Main *bmain, const struct bAction *act_src);
/* Deallocate all of the Action's data, but not the Action itself */
void BKE_action_free(struct bAction *act);
@@ -150,7 +151,8 @@ void BKE_pose_free_data_ex(struct bPose *pose, bool do_id_user);
void BKE_pose_free_data(struct bPose *pose);
void BKE_pose_free(struct bPose *pose);
void BKE_pose_free_ex(struct bPose *pose, bool do_id_user);
-void BKE_pose_copy_data(struct bPose **dst, struct bPose *src, const bool copy_constraints);
+void BKE_pose_copy_data_ex(struct bPose **dst, const struct bPose *src, const int flag, const bool copy_constraints);
+void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool copy_constraints);
void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from);
struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name);
struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index a67e903877a..534a57765f6 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -67,10 +67,10 @@ bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct b
void BKE_animdata_free(struct ID *id, const bool do_id_user);
/* Copy AnimData */
-struct AnimData *BKE_animdata_copy(struct AnimData *adt, const bool do_action);
+struct AnimData *BKE_animdata_copy(struct Main *bmain, struct AnimData *adt, const bool do_action);
/* Copy AnimData */
-bool BKE_animdata_copy_id(struct ID *id_to, struct ID *id_from, const bool do_action);
+bool BKE_animdata_copy_id(struct Main *bmain, struct ID *id_to, struct ID *id_from, const bool do_action);
/* Copy AnimData Actions */
void BKE_animdata_copy_id_action(struct ID *id, const bool set_newid);
@@ -89,12 +89,6 @@ typedef enum eAnimData_MergeCopy_Modes {
void BKE_animdata_merge_copy(struct ID *dst_id, struct ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers);
-/* Make Local */
-void BKE_animdata_make_local(struct AnimData *adt);
-
-/* Re-Assign ID's */
-void BKE_animdata_relink(struct AnimData *adt);
-
/* ************************************* */
/* KeyingSets API */
@@ -108,7 +102,7 @@ struct KS_Path *BKE_keyingset_add_path(struct KeyingSet *ks, struct ID *id, cons
struct KS_Path *BKE_keyingset_find_path(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode);
/* Copy all KeyingSets in the given list */
-void BKE_keyingsets_copy(struct ListBase *newlist, struct ListBase *list);
+void BKE_keyingsets_copy(struct ListBase *newlist, const struct ListBase *list);
/* Free the given Keying Set path */
void BKE_keyingset_free_path(struct KeyingSet *ks, struct KS_Path *ksp);
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 23bb526073b..1cc42f788d5 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -77,7 +77,8 @@ int BKE_armature_bonelist_count(struct ListBase *lb);
void BKE_armature_bonelist_free(struct ListBase *lb);
void BKE_armature_free(struct bArmature *arm);
void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool lib_local);
-struct bArmature *BKE_armature_copy(struct Main *bmain, struct bArmature *arm);
+void BKE_armature_copy_data(struct Main *bmain, struct bArmature *arm_dst, const struct bArmature *arm_src, const int flag);
+struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature *arm);
/* Bounding box. */
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index d55926ffb1e..ec0bfa6f5fa 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -50,7 +50,6 @@ void BKE_blender_version_string(
void BKE_blender_userdef_set_data(struct UserDef *userdef);
void BKE_blender_userdef_free_data(struct UserDef *userdef);
-void BKE_blender_userdef_refresh(void);
void BKE_blender_userdef_set_app_template(struct UserDef *userdef);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 207631d36bd..f95b1963a91 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 278
-#define BLENDER_SUBVERSION 5
+#define BLENDER_VERSION 279
+#define BLENDER_SUBVERSION 1
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6
diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h
index 582cd0cef8d..24f19951efe 100644
--- a/source/blender/blenkernel/BKE_boids.h
+++ b/source/blender/blenkernel/BKE_boids.h
@@ -61,6 +61,6 @@ BoidRule *boid_new_rule(int type);
BoidState *boid_new_state(BoidSettings *boids);
BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state);
void boid_free_settings(BoidSettings *boids);
-BoidSettings *boid_copy_settings(BoidSettings *boids);
+BoidSettings *boid_copy_settings(const BoidSettings *boids);
BoidState *boid_get_current_state(BoidSettings *boids);
#endif
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 8bd4bdf89e1..dedb75a080a 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -44,7 +44,8 @@ void BKE_brush_system_exit(void);
void BKE_brush_init(struct Brush *brush);
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
-struct Brush *BKE_brush_copy(struct Main *bmain, struct Brush *brush);
+void BKE_brush_copy_data(struct Main *bmain, struct Brush *brush_dst, const struct Brush *brush_src, const int flag);
+struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush);
void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local);
void BKE_brush_unlink(struct Main *bmain, struct Brush *brush);
void BKE_brush_free(struct Brush *brush);
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index 0d4ed2083b1..e9712681090 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -47,7 +47,9 @@ 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_copy_data(
+ struct Main *bmain, struct CacheFile *cache_file_dst, const struct CacheFile *cache_file_src, const int flag);
+struct CacheFile *BKE_cachefile_copy(struct Main *bmain, const struct CacheFile *cache_file);
void BKE_cachefile_make_local(struct Main *bmain, struct CacheFile *cache_file, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 31a732cf7e5..04dee70faa6 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -52,7 +52,8 @@ struct GPUFXSettings;
void BKE_camera_init(struct Camera *cam);
void *BKE_camera_add(struct Main *bmain, const char *name);
-struct Camera *BKE_camera_copy(struct Main *bmain, struct Camera *cam);
+void BKE_camera_copy_data(struct Main *bmain, struct Camera *cam_dst, const struct Camera *cam_src, const int flag);
+struct Camera *BKE_camera_copy(struct Main *bmain, const struct Camera *cam);
void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool lib_local);
void BKE_camera_free(struct Camera *ca);
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index 5b4f5910821..f68c4a2757b 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -46,8 +46,8 @@ void curvemapping_set_defaults(struct CurveMapping *cumap, int to
struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
void curvemapping_free_data(struct CurveMapping *cumap);
void curvemapping_free(struct CurveMapping *cumap);
-void curvemapping_copy_data(struct CurveMapping *target, struct CurveMapping *cumap);
-struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap);
+void curvemapping_copy_data(struct CurveMapping *target, const struct CurveMapping *cumap);
+struct CurveMapping *curvemapping_copy(const struct CurveMapping *cumap);
void curvemapping_set_black_white_ex(const float black[3], const float white[3], float r_bwmul[3]);
void curvemapping_set_black_white(struct CurveMapping *cumap, const float black[3], const float white[3]);
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 047d1787f76..4e0eb5c65ac 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -120,6 +120,7 @@ void BKE_constraint_unique_name(struct bConstraint *con, struct ListBase *list);
void BKE_constraints_free(struct ListBase *list);
void BKE_constraints_free_ex(struct ListBase *list, bool do_id_user);
void BKE_constraints_copy(struct ListBase *dst, const struct ListBase *src, bool do_extern);
+void BKE_constraints_copy_ex(struct ListBase *dst, const struct ListBase *src, const int flag, bool do_extern);
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, void *userdata);
void BKE_constraint_free_data(struct bConstraint *con);
void BKE_constraint_free_data_ex(struct bConstraint *con, bool do_id_user);
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index e111bd0e16b..a900ba43443 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -78,7 +78,8 @@ void BKE_curve_free(struct Curve *cu);
void BKE_curve_editfont_free(struct Curve *cu);
void BKE_curve_init(struct Curve *cu);
struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
-struct Curve *BKE_curve_copy(struct Main *bmain, struct Curve *cu);
+void BKE_curve_copy_data(struct Main *bmain, struct Curve *cu_dst, const struct Curve *cu_src, const int flag);
+struct Curve *BKE_curve_copy(struct Main *bmain, const struct Curve *cu);
void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool lib_local);
short BKE_curve_type_get(struct Curve *cu);
void BKE_curve_type_test(struct Object *ob);
@@ -92,8 +93,8 @@ void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], fl
bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]);
bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
-void BKE_curve_transform_ex(struct Curve *cu, float mat[4][4], const bool do_keys, const float unit_scale);
-void BKE_curve_transform(struct Curve *cu, float mat[4][4], const bool do_keys);
+void BKE_curve_transform_ex(struct Curve *cu, float mat[4][4], const bool do_keys, const bool do_props, const float unit_scale);
+void BKE_curve_transform(struct Curve *cu, float mat[4][4], const bool do_keys, const bool do_props);
void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys);
void BKE_curve_material_index_remove(struct Curve *cu, int index);
void BKE_curve_material_index_clear(struct Curve *cu);
@@ -142,7 +143,7 @@ int BKE_nurbList_verts_count(struct ListBase *nurb);
int BKE_nurbList_verts_count_without_handles(struct ListBase *nurb);
void BKE_nurbList_free(struct ListBase *lb);
-void BKE_nurbList_duplicate(struct ListBase *lb1, struct ListBase *lb2);
+void BKE_nurbList_duplicate(struct ListBase *lb1, const struct ListBase *lb2);
void BKE_nurbList_handles_set(struct ListBase *editnurb, const char code);
void BKE_nurbList_handles_recalculate(struct ListBase *editnurb, const bool calc_length, const char flag);
@@ -150,7 +151,7 @@ void BKE_nurbList_handles_autocalc(ListBase *editnurb, int flag);
void BKE_nurbList_flag_set(ListBase *editnurb, short flag);
void BKE_nurb_free(struct Nurb *nu);
-struct Nurb *BKE_nurb_duplicate(struct Nurb *nu);
+struct Nurb *BKE_nurb_duplicate(const struct Nurb *nu);
struct Nurb *BKE_nurb_copy(struct Nurb *src, int pntsu, int pntsv);
void BKE_nurb_test2D(struct Nurb *nu);
@@ -198,6 +199,7 @@ void BKE_nurb_bezt_calc_normal(struct Nurb *nu, struct BezTriple *bezt, float r_
void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3]);
void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_normal[3]);
+void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, struct BPoint *bp, float r_plane[3]);
void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next,
const bool is_fcurve);
@@ -216,7 +218,4 @@ struct EvaluationContext;
void BKE_curve_eval_geometry(struct EvaluationContext *eval_ctx,
struct Curve *curve);
-void BKE_curve_eval_path(struct EvaluationContext *eval_ctx,
- struct Curve *curve);
-
#endif /* __BKE_CURVE_H__ */
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index 3ce08a14177..a20c5a4240c 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -44,8 +44,8 @@ struct MLoop;
struct MPoly;
struct bDeformGroup *BKE_defgroup_new(struct Object *ob, const char *name);
-void defgroup_copy_list(struct ListBase *lb1, struct ListBase *lb2);
-struct bDeformGroup *defgroup_duplicate(struct bDeformGroup *ingroup);
+void defgroup_copy_list(struct ListBase *lb1, const struct ListBase *lb2);
+struct bDeformGroup *defgroup_duplicate(const struct bDeformGroup *ingroup);
struct bDeformGroup *defgroup_find_name(struct Object *ob, const char *name);
int *defgroup_flip_map(struct Object *ob, int *flip_map_len, const bool use_default);
int *defgroup_flip_map_single(struct Object *ob, int *flip_map_len, const bool use_default, int defgroup);
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 3a45097efc5..b38f1299763 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -92,7 +92,7 @@ void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt);
/* ---------------------- */
void fcurve_free_driver(struct FCurve *fcu);
-struct ChannelDriver *fcurve_copy_driver(struct ChannelDriver *driver);
+struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list);
@@ -138,7 +138,7 @@ typedef struct FModifierTypeInfo {
/* free any data that is allocated separately (optional) */
void (*free_data)(struct FModifier *fcm);
/* copy any special data that is allocated separately (optional) */
- void (*copy_data)(struct FModifier *fcm, struct FModifier *src);
+ void (*copy_data)(struct FModifier *fcm, const struct FModifier *src);
/* set settings for data that will be used for FCuModifier.data (memory already allocated using MEM_callocN) */
void (*new_data)(void *mdata);
/* verifies that the modifier settings are valid */
@@ -183,14 +183,14 @@ typedef enum eFMI_Requirement_Flags {
} eFMI_Requirement_Flags;
/* Function Prototypes for FModifierTypeInfo's */
-const FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm);
-const FModifierTypeInfo *get_fmodifier_typeinfo(int type);
+const FModifierTypeInfo *fmodifier_get_typeinfo(const struct FModifier *fcm);
+const FModifierTypeInfo *get_fmodifier_typeinfo(const int type);
/* ---------------------- */
struct FModifier *add_fmodifier(ListBase *modifiers, int type);
-struct FModifier *copy_fmodifier(struct FModifier *src);
-void copy_fmodifiers(ListBase *dst, ListBase *src);
+struct FModifier *copy_fmodifier(const struct FModifier *src);
+void copy_fmodifiers(ListBase *dst, const ListBase *src);
bool remove_fmodifier(ListBase *modifiers, struct FModifier *fcm);
void free_fmodifiers(ListBase *modifiers);
@@ -216,7 +216,7 @@ int BKE_fcm_envelope_find_index(struct FCM_EnvelopeData *array, float frame, int
/* -------- Data Management -------- */
void free_fcurve(struct FCurve *fcu);
-struct FCurve *copy_fcurve(struct FCurve *fcu);
+struct FCurve *copy_fcurve(const struct FCurve *fcu);
void free_fcurves(ListBase *list);
void copy_fcurves(ListBase *dst, ListBase *src);
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
index e7ae0f606e7..60ad061bf77 100644
--- a/source/blender/blenkernel/BKE_font.h
+++ b/source/blender/blenkernel/BKE_font.h
@@ -78,6 +78,7 @@ void BKE_vfont_builtin_register(void *mem, int size);
void BKE_vfont_free_data(struct VFont *vfont);
void BKE_vfont_free(struct VFont *sc);
void BKE_vfont_init(struct VFont *vfont);
+void BKE_vfont_copy_data(struct Main *bmain, struct VFont *vfont_dst, const struct VFont *vfont_src, const int flag);
struct VFont *BKE_vfont_builtin_get(void);
struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath);
struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);
diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h
index 50407f3bdfc..1045fde0039 100644
--- a/source/blender/blenkernel/BKE_freestyle.h
+++ b/source/blender/blenkernel/BKE_freestyle.h
@@ -50,7 +50,7 @@ typedef struct FreestyleModuleSettings FreestyleModuleSettings;
/* FreestyleConfig */
void BKE_freestyle_config_init(FreestyleConfig *config);
void BKE_freestyle_config_free(FreestyleConfig *config);
-void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config);
+void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag);
/* FreestyleConfig.modules */
FreestyleModuleConfig *BKE_freestyle_module_add(FreestyleConfig *config);
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 3378f4acc60..b6de922c245 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -60,7 +60,8 @@ struct bGPdata *BKE_gpencil_data_addnew(const char name[]);
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_copy_data(struct Main *bmain, struct bGPdata *gpd_dst, const struct bGPdata *gpd_src, const int flag);
+struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, const struct bGPdata *gpd, bool internal_copy);
void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 09a069ee36f..404d1704c78 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -42,7 +42,8 @@ struct Scene;
void BKE_group_free(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
-struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
+void BKE_group_copy_data(struct Main *bmain, struct Group *group_dst, const struct Group *group_src, const int flag);
+struct Group *BKE_group_copy(struct Main *bmain, const struct Group *group);
void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 6944c5ccd28..39e6b145755 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -88,7 +88,7 @@ void BKE_previewimg_clear(struct PreviewImage *prv);
void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size);
/* get the preview from any pointer */
-struct PreviewImage **BKE_previewimg_id_get_p(struct ID *id);
+struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id);
/* free the preview image belonging to the id */
void BKE_previewimg_id_free(struct ID *id);
@@ -97,9 +97,9 @@ void BKE_previewimg_id_free(struct ID *id);
struct PreviewImage *BKE_previewimg_create(void);
/* create a copy of the preview image */
-struct PreviewImage *BKE_previewimg_copy(struct PreviewImage *prv);
+struct PreviewImage *BKE_previewimg_copy(const struct PreviewImage *prv);
-void BKE_previewimg_id_copy(struct ID *new_id, struct ID *old_id);
+void BKE_previewimg_id_copy(struct ID *new_id, const struct ID *old_id);
/* retrieve existing or create new preview image */
struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id);
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index ab8728faedb..5d8cd02756d 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -58,7 +58,7 @@ typedef union IDPropertyTemplate {
/* ----------- Property Array Type ---------- */
IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-IDProperty *IDP_CopyIDPArray(const IDProperty *array) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* shallow copies item */
void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL();
@@ -103,6 +103,7 @@ IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *na
/*-------- Main Functions --------*/
struct IDProperty *IDP_GetProperties(struct ID *id, const bool create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
struct IDProperty *IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+struct IDProperty *IDP_CopyProperty_ex(const struct IDProperty *prop, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is_strict) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 132c73209d1..3c716f39dd0 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -58,6 +58,7 @@ void BKE_images_exit(void);
void BKE_image_free_packedfiles(struct Image *image);
void BKE_image_free_views(struct Image *image);
void BKE_image_free_buffers(struct Image *image);
+void BKE_image_free_buffers_ex(struct Image *image, bool do_lock);
/* call from library */
void BKE_image_free(struct Image *image);
@@ -250,7 +251,8 @@ void BKE_image_packfiles_from_mem(struct ReportList *reports, struct Image *ima,
void BKE_image_print_memlist(void);
/* empty image block, of similar type and filename */
-struct Image *BKE_image_copy(struct Main *bmain, struct Image *ima);
+void BKE_image_copy_data(struct Main *bmain, struct Image *ima_dst, const struct Image *ima_src, const int flag);
+struct Image *BKE_image_copy(struct Main *bmain, const struct Image *ima);
/* merge source into dest, and free source */
void BKE_image_merge(struct Image *dest, struct Image *source);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index e590ff148d7..5eef44ef896 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -51,7 +51,8 @@ extern "C" {
void BKE_key_free(struct Key *sc);
void BKE_key_free_nolib(struct Key *key);
struct Key *BKE_key_add(struct ID *id);
-struct Key *BKE_key_copy(struct Main *bmain, struct Key *key);
+void BKE_key_copy_data(struct Main *bmain, struct Key *key_dst, const struct Key *key_src, const int flag);
+struct Key *BKE_key_copy(struct Main *bmain, const struct Key *key);
struct Key *BKE_key_copy_nolib(struct Key *key);
void BKE_key_sort(struct Key *key);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index 4d53850c572..b68da654520 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -44,7 +44,8 @@ struct Scene;
void BKE_lamp_init(struct Lamp *la);
struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
-struct Lamp *BKE_lamp_copy(struct Main *bmain, struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
+void BKE_lamp_copy_data(struct Main *bmain, struct Lamp *la_dst, const struct Lamp *la_src, const int flag);
+struct Lamp *BKE_lamp_copy(struct Main *bmain, const struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local);
void BKE_lamp_free(struct Lamp *la);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 226c82da295..f7d006785d2 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -47,7 +47,8 @@ struct MDeformVert;
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb);
void BKE_lattice_init(struct Lattice *lt);
struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
-struct Lattice *BKE_lattice_copy(struct Main *bmain, struct Lattice *lt);
+void BKE_lattice_copy_data(struct Main *bmain, struct Lattice *lt_dst, const struct Lattice *lt_src, const int flag);
+struct Lattice *BKE_lattice_copy(struct Main *bmain, const struct Lattice *lt);
void BKE_lattice_free(struct Lattice *lt);
void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool lib_local);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 6649cfbb585..b5104b35b3c 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -50,12 +50,40 @@ struct bContext;
struct PointerRNA;
struct PropertyRNA;
+size_t BKE_libblock_get_alloc_info(short type, const char **name);
void *BKE_libblock_alloc_notest(short type);
-void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BKE_libblock_init_empty(struct ID *id);
-void *BKE_libblock_copy(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void *BKE_libblock_copy_nolib(struct ID *id, const bool do_action) ATTR_NONNULL();
-void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
+
+/**
+ * New ID creation/copying options.
+ */
+enum {
+ /* *** Generic options (should be handled by all ID types copying, ID creation, etc.). *** */
+ /* Create datablock outside of any main database - similar to 'localize' functions of materials etc. */
+ LIB_ID_CREATE_NO_MAIN = 1 << 0,
+ /* Do not affect user refcount of datablocks used by new one (which also gets zero usercount then).
+ * Implies LIB_ID_CREATE_NO_MAIN. */
+ LIB_ID_CREATE_NO_USER_REFCOUNT = 1 << 1,
+ /* Assume given 'newid' already points to allocated memory for whole datablock (ID + data) - USE WITH CAUTION!
+ * Implies LIB_ID_CREATE_NO_MAIN. */
+ LIB_ID_CREATE_NO_ALLOCATE = 1 << 2,
+
+ LIB_ID_CREATE_NO_DEG_TAG = 1 << 8, /* Do not tag new ID for update in depsgraph. */
+
+ /* Specific options to some ID types or usages, may be ignored by unrelated ID copying functions. */
+ LIB_ID_COPY_NO_PROXY_CLEAR = 1 << 16, /* Object only, needed by make_local code. */
+ LIB_ID_COPY_NO_PREVIEW = 1 << 17, /* Do not copy preview data, when supported. */
+ LIB_ID_COPY_CACHES = 1 << 18, /* Copy runtime data caches. */
+ /* XXX TODO Do we want to keep that? would rather try to get rid of it... */
+ LIB_ID_COPY_ACTIONS = 1 << 19, /* EXCEPTION! Deep-copy actions used by animdata of copied ID. */
+};
+
+void BKE_libblock_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag);
+void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/* "Deprecated" old API. */
+void *BKE_libblock_copy_nolib(const struct ID *id, const bool do_action) ATTR_NONNULL();
+
void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL();
void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL();
@@ -63,12 +91,45 @@ struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const
struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* library_remap.c (keep here since they're general functions) */
-void BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL();
+/**
+ * New freeing logic options.
+ */
+enum {
+ /* *** Generic options (should be handled by all ID types freeing). *** */
+ /* Do not try to remove freed ID from given Main (passed Main may be NULL). */
+ LIB_ID_FREE_NO_MAIN = 1 << 0,
+ /* Do not affect user refcount of datablocks used by freed one.
+ * Implies LIB_ID_FREE_NO_MAIN. */
+ LIB_ID_FREE_NO_USER_REFCOUNT = 1 << 1,
+ /* Assume freed ID datablock memory is managed elsewhere, do not free it
+ * (still calls relevant ID type's freeing function though) - USE WITH CAUTION!
+ * Implies LIB_ID_FREE_NO_MAIN. */
+ LIB_ID_FREE_NOT_ALLOCATED = 1 << 2,
+
+ LIB_ID_FREE_NO_DEG_TAG = 1 << 8, /* Do not tag freed ID for update in depsgraph. */
+ LIB_ID_FREE_NO_UI_USER = 1 << 9, /* Do not attempt to remove freed ID from UI data/notifiers/... */
+};
+
+void BKE_id_free_ex(struct Main *bmain, void *idv, int flag, const bool use_flag_from_idtag);
+void BKE_id_free(struct Main *bmain, void *idv);
+/* Those three naming are bad actually, should be BKE_id_free... (since it goes beyond mere datablock). */
+/* "Deprecated" old API */
void BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) ATTR_NONNULL();
+void BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL();
void BKE_libblock_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
-void BKE_libblock_free_data(struct Main *bmain, struct ID *id, const bool do_id_user) ATTR_NONNULL();
+
+void BKE_libblock_management_main_add(struct Main *bmain, void *idv);
+void BKE_libblock_management_main_remove(struct Main *bmain, void *idv);
+
+void BKE_libblock_management_usercounts_set(struct Main *bmain, void *idv);
+void BKE_libblock_management_usercounts_clear(struct Main *bmain, void *idv);
+
+/* TODO should be named "BKE_id_delete()". */
void BKE_libblock_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
+void BKE_libblock_free_datablock(struct ID *id, const int flag) ATTR_NONNULL();
+void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL();
+
void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
void id_lib_extern(struct ID *id);
void BKE_library_filepath_set(struct Library *lib, const char *filepath);
@@ -84,10 +145,11 @@ void BKE_id_clear_newpoin(struct ID *id);
void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_in_mainlist, const bool lib_local);
bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
-bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test);
+bool id_copy(struct Main *bmain, const struct ID *id, struct ID **newid, bool test);
+bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag, const bool test);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
void BKE_id_expand_local(struct Main *bmain, struct ID *id);
-void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id);
+void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id);
bool new_id(struct ListBase *lb, struct ID *id, const char *name);
void id_clear_lib_data(struct Main *bmain, struct ID *id);
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index 6cf18e28e17..d6e7d98f371 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -83,6 +83,8 @@ enum {
IDWALK_NOP = 0,
IDWALK_READONLY = (1 << 0),
IDWALK_RECURSE = (1 << 1), /* Also implies IDWALK_READONLY. */
+
+ IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */
};
/* Loop over all of the ID's this datablock links to. */
diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h
index 53d438a0fdd..fd37fd762f4 100644
--- a/source/blender/blenkernel/BKE_library_remap.h
+++ b/source/blender/blenkernel/BKE_library_remap.h
@@ -46,6 +46,11 @@ enum {
/* This tells the callback func to force setting IDs using target one with a 'never NULL' pointer to NULL.
* WARNING! Use with extreme care, this will leave database in broken state and can cause crashes very easily! */
ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3,
+ /* Do not consider proxy/_group pointers of local objects as indirect usages...
+ * Our oh-so-beloved proxies again... Do not consider data used by local proxy object as indirect usage.
+ * This is needed e.g. in reload scenario, since we have to ensure remapping of Armature data of local proxy
+ * is also performed. Usual nightmare... */
+ ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4,
};
/* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
index af9bf58ce77..3ba4fbe0338 100644
--- a/source/blender/blenkernel/BKE_linestyle.h
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -52,7 +52,10 @@ struct bContext;
void BKE_linestyle_init(struct FreestyleLineStyle *linestyle);
FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name);
void BKE_linestyle_free(FreestyleLineStyle *linestyle);
-FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle);
+void BKE_linestyle_copy_data(
+ struct Main *bmain, struct FreestyleLineStyle *linestyle_dst, const struct FreestyleLineStyle *linestyle_src,
+ const int flag);
+FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle);
void BKE_linestyle_make_local(struct Main *bmain, struct FreestyleLineStyle *linestyle, const bool lib_local);
@@ -63,10 +66,14 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl
LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type);
LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type);
-LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+LineStyleModifier *BKE_linestyle_color_modifier_copy(
+ FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag);
+LineStyleModifier *BKE_linestyle_alpha_modifier_copy(
+ FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag);
+LineStyleModifier *BKE_linestyle_thickness_modifier_copy(
+ FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag);
+LineStyleModifier *BKE_linestyle_geometry_modifier_copy(
+ FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag);
int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 3349bffac85..6e154241af7 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -77,14 +77,14 @@ void BKE_mask_layer_free(struct MaskLayer *masklay);
void BKE_mask_layer_free_list(struct ListBase *masklayers);
void BKE_mask_spline_free(struct MaskSpline *spline);
void BKE_mask_spline_free_list(struct ListBase *splines);
-struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline);
+struct MaskSpline *BKE_mask_spline_copy(const struct MaskSpline *spline);
void BKE_mask_point_free(struct MaskSplinePoint *point);
void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay);
void BKE_mask_layer_rename(struct Mask *mask, struct MaskLayer *masklay, char *oldname, char *newname);
-struct MaskLayer *BKE_mask_layer_copy(struct MaskLayer *layer);
-void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, struct ListBase *masklayers);
+struct MaskLayer *BKE_mask_layer_copy(const struct MaskLayer *layer);
+void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, const struct ListBase *masklayers);
/* splines */
struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay);
@@ -122,8 +122,9 @@ void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const eMask
/* general */
struct Mask *BKE_mask_new(struct Main *bmain, const char *name);
+void BKE_mask_copy_data(struct Main *bmain, struct Mask *mask_dst, const struct Mask *mask_src, const int flag);
struct Mask *BKE_mask_copy_nolib(struct Mask *mask);
-struct Mask *BKE_mask_copy(struct Main *bmain, struct Mask *mask);
+struct Mask *BKE_mask_copy(struct Main *bmain, const struct Mask *mask);
void BKE_mask_make_local(struct Main *bmain, struct Mask *mask, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 8ae5c2b3c45..c6ebda2c399 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -54,7 +54,8 @@ 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);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
-struct Material *BKE_material_copy(struct Main *bmain, struct Material *ma);
+void BKE_material_copy_data(struct Main *bmain, struct Material *ma_dst, const struct Material *ma_src, const int flag);
+struct Material *BKE_material_copy(struct Main *bmain, const struct Material *ma);
struct Material *localize_material(struct Material *ma);
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 64320a20281..f02704ba903 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -41,7 +41,8 @@ struct MetaElem;
void BKE_mball_free(struct MetaBall *mb);
void BKE_mball_init(struct MetaBall *mb);
struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name);
-struct MetaBall *BKE_mball_copy(struct Main *bmain, struct MetaBall *mb);
+void BKE_mball_copy_data(struct Main *bmain, struct MetaBall *mb_dst, const struct MetaBall *mb_src, const int flag);
+struct MetaBall *BKE_mball_copy(struct Main *bmain, const struct MetaBall *mb);
void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool lib_local);
@@ -59,7 +60,7 @@ bool BKE_mball_minmax_ex(struct MetaBall *mb, float min[3], float max[3],
float obmat[4][4], const short flag);
bool BKE_mball_center_median(struct MetaBall *mb, float r_cent[3]);
bool BKE_mball_center_bounds(struct MetaBall *mb, float r_cent[3]);
-void BKE_mball_transform(struct MetaBall *mb, float mat[4][4]);
+void BKE_mball_transform(struct MetaBall *mb, float mat[4][4], const bool do_props);
void BKE_mball_translate(struct MetaBall *mb, const float offset[3]);
struct MetaElem *BKE_mball_element_add(struct MetaBall *mb, const int type);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index b83bec5a302..f3b2b653e3d 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -87,7 +87,8 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
void BKE_mesh_free(struct Mesh *me);
void BKE_mesh_init(struct Mesh *me);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
-struct Mesh *BKE_mesh_copy(struct Main *bmain, struct Mesh *me);
+void BKE_mesh_copy_data(struct Main *bmain, struct Mesh *me_dst, const struct Mesh *me_src, const int flag);
+struct Mesh *BKE_mesh_copy(struct Main *bmain, const struct Mesh *me);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
@@ -110,7 +111,8 @@ int BKE_mesh_nurbs_displist_to_mdata(
struct MEdge **r_alledge, int *r_totedge,
struct MLoop **r_allloop, struct MPoly **r_allpoly,
struct MLoopUV **r_alluv, int *r_totloop, int *r_totpoly);
-void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv);
+void BKE_mesh_from_nurbs_displist(
+ struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv, const char *obdata_name);
void BKE_mesh_from_nurbs(struct Object *ob);
void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test);
void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
@@ -278,7 +280,8 @@ void BKE_mesh_poly_edgebitmap_insert(
bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_bounds(const struct Mesh *me, float r_cent[3]);
-bool BKE_mesh_center_centroid(const struct Mesh *me, float r_cent[3]);
+bool BKE_mesh_center_of_surface(const struct Mesh *me, float r_cent[3]);
+bool BKE_mesh_center_of_volume(const struct Mesh *me, float r_cent[3]);
void BKE_mesh_calc_volume(
const struct MVert *mverts, const int mverts_num,
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index b241b5ca5b7..30c47a4b192 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -344,6 +344,7 @@ bool modifier_unique_name(struct ListBase *modifiers, struct ModifierDa
void modifier_copyData_generic(const struct ModifierData *md, struct ModifierData *target);
void modifier_copyData(struct ModifierData *md, struct ModifierData *target);
+void modifier_copyData_ex(struct ModifierData *md, struct ModifierData *target, const int flag);
bool modifier_dependsOnTime(struct ModifierData *md);
bool modifier_supportsMapping(struct ModifierData *md);
bool modifier_supportsCage(struct Scene *scene, struct ModifierData *md);
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index 3237c146bc5..3ddf75f204e 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -41,7 +41,8 @@ struct MovieDistortion;
void BKE_movieclip_free(struct MovieClip *clip);
-struct MovieClip *BKE_movieclip_copy(struct Main *bmain, struct MovieClip *clip);
+void BKE_movieclip_copy_data(struct Main *bmain, struct MovieClip *clip_dst, const struct MovieClip *clip_src, const int flag);
+struct MovieClip *BKE_movieclip_copy(struct Main *bmain, const struct MovieClip *clip);
void BKE_movieclip_make_local(struct Main *bmain, struct MovieClip *clip, const bool lib_local);
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 41028c73014..81de70ca8a4 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -335,8 +335,9 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree(struct bNodeTree *ntree);
-struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user);
-struct bNodeTree *ntreeCopyTree(struct Main *bmain, struct bNodeTree *ntree);
+void BKE_node_tree_copy_data(struct Main *bmain, struct bNodeTree *ntree_dst, const struct bNodeTree *ntree_src, const int flag);
+struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user);
+struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntree);
/* node->id user count */
void ntreeUserIncrefID(struct bNodeTree *ntree);
void ntreeUserDecrefID(struct bNodeTree *ntree);
@@ -452,6 +453,7 @@ void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
+struct bNode *BKE_node_copy_ex(struct bNodeTree *ntree, struct bNode *node_src, const int flag);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index b6633ea6198..d1a4033957b 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -53,10 +53,10 @@ void BKE_object_workob_clear(struct Object *workob);
void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob);
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
-struct SoftBody *copy_softbody(const struct SoftBody *sb, bool copy_caches);
-struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
-struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys);
-void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src);
+struct SoftBody *copy_softbody(const struct SoftBody *sb, const int flag);
+struct BulletSoftBody *copy_bulletsoftbody(const struct BulletSoftBody *sb, const int flag);
+struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys, const int flag);
+void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src, const int flag);
void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
@@ -105,8 +105,8 @@ bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene);
struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene);
struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
-struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches);
-struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob);
+void BKE_object_copy_data(struct Main *bmain, struct Object *ob_dst, const struct Object *ob_src, const int flag);
+struct Object *BKE_object_copy(struct Main *bmain, const struct Object *ob);
void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local);
void BKE_object_make_local_ex(struct Main *bmain, struct Object *ob, const bool lib_local, const bool clear_proxy);
bool BKE_object_is_libdata(struct Object *ob);
@@ -189,10 +189,6 @@ void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx,
struct Object *ob);
void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob);
-void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob,
- struct ModifierData *md);
void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 1cc5ba3a928..405f2ad9772 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -99,7 +99,9 @@ void BKE_paint_set_overlay_override(enum OverlayFlags flag);
/* palettes */
void BKE_palette_free(struct Palette *palette);
struct Palette *BKE_palette_add(struct Main *bmain, const char *name);
-struct Palette *BKE_palette_copy(struct Main *bmain, struct Palette *palette);
+void BKE_palette_copy_data(
+ struct Main *bmain, struct Palette *palette_dst, const struct Palette *palette_src, const int flag);
+struct Palette *BKE_palette_copy(struct Main *bmain, const struct Palette *palette);
void BKE_palette_make_local(struct Main *bmain, struct Palette *palette, const bool lib_local);
struct PaletteColor *BKE_palette_color_add(struct Palette *palette);
bool BKE_palette_is_empty(const struct Palette *palette);
@@ -109,12 +111,14 @@ void BKE_palette_clear(struct Palette *palette);
/* paint curves */
struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name);
void BKE_paint_curve_free(struct PaintCurve *pc);
-struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, struct PaintCurve *pc);
+void BKE_paint_curve_copy_data(
+ struct Main *bmain, struct PaintCurve *pc_dst, const struct PaintCurve *pc_src, const int flag);
+struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, const struct PaintCurve *pc);
void BKE_paint_curve_make_local(struct Main *bmain, struct PaintCurve *pc, const bool lib_local);
void BKE_paint_init(struct Scene *sce, PaintMode mode, const char col[3]);
void BKE_paint_free(struct Paint *p);
-void BKE_paint_copy(struct Paint *src, struct Paint *tar);
+void BKE_paint_copy(struct Paint *src, struct Paint *tar, const int flag);
void BKE_paint_cavity_curve_preset(struct Paint *p, int preset);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 2b6a84a2f87..ddb4f9c37bd 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -324,7 +324,10 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P
struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name);
void object_remove_particle_system(struct Scene *scene, struct Object *ob);
struct ParticleSettings *psys_new_settings(const char *name, struct Main *main);
-struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, struct ParticleSettings *part);
+void BKE_particlesettings_copy_data(
+ struct Main *bmain, struct ParticleSettings *part_dst, const struct ParticleSettings *part_src,
+ const int flag);
+struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, const struct ParticleSettings *part);
void BKE_particlesettings_make_local(struct Main *bmain, struct ParticleSettings *part, const bool lib_local);
void psys_reset(struct ParticleSystem *psys, int mode);
@@ -473,9 +476,8 @@ typedef struct ParticleRenderData {
struct EvaluationContext;
-void BKE_particle_system_eval(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob,
- struct ParticleSystem *psys);
+void BKE_particle_system_eval_init(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
#endif
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 02f6c435ee2..f0819c8d79d 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -314,7 +314,7 @@ struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches);
void BKE_ptcache_free_mem(struct ListBase *mem_cache);
void BKE_ptcache_free(struct PointCache *cache);
void BKE_ptcache_free_list(struct ListBase *ptcaches);
-struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, bool copy_data);
+struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, const int flag);
/********************** Baking *********************/
diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h
index 99e60757f15..c787e8e8ed1 100644
--- a/source/blender/blenkernel/BKE_property.h
+++ b/source/blender/blenkernel/BKE_property.h
@@ -37,8 +37,8 @@ struct Object;
void BKE_bproperty_free(struct bProperty *prop);
void BKE_bproperty_free_list(struct ListBase *lb);
-struct bProperty *BKE_bproperty_copy(struct bProperty *prop);
-void BKE_bproperty_copy_list(struct ListBase *lbn, struct ListBase *lbo);
+struct bProperty *BKE_bproperty_copy(const struct bProperty *prop);
+void BKE_bproperty_copy_list(struct ListBase *lbn, const struct ListBase *lbo);
void BKE_bproperty_init(struct bProperty *prop);
struct bProperty *BKE_bproperty_new(int type);
void BKE_bproperty_unique(struct bProperty *first, struct bProperty *prop, int force);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 443c3b2b5b2..3c7274ca3c5 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -49,8 +49,8 @@ void BKE_rigidbody_free_constraint(struct Object *ob);
/* ...... */
-struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
-struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
+struct RigidBodyOb *BKE_rigidbody_copy_object(const struct Object *ob, const int flag);
+struct RigidBodyCon *BKE_rigidbody_copy_constraint(const struct Object *ob, const int flag);
/* Callback format for performing operations on ID-pointers for rigidbody world. */
typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cb_flag);
@@ -66,7 +66,7 @@ struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Obje
struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type);
/* copy */
-struct RigidBodyWorld *BKE_rigidbody_world_copy(struct RigidBodyWorld *rbw);
+struct RigidBodyWorld *BKE_rigidbody_world_copy(struct RigidBodyWorld *rbw, const int flag);
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw);
/* 'validate' (i.e. make new or replace old) Physics-Engine objects */
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index 1579a0c7bb3..35bcd91a9b1 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -52,16 +52,16 @@ void free_actuators(struct ListBase *lb);
void free_sensor(struct bSensor *sens);
void free_sensors(struct ListBase *lb);
-struct bSensor *copy_sensor(struct bSensor *sens);
-void copy_sensors(struct ListBase *lbn, struct ListBase *lbo);
+struct bSensor *copy_sensor(struct bSensor *sens, const int flag);
+void copy_sensors(struct ListBase *lbn, const struct ListBase *lbo, const int flag);
void init_sensor(struct bSensor *sens);
struct bSensor *new_sensor(int type);
-struct bController *copy_controller(struct bController *cont);
-void copy_controllers(struct ListBase *lbn, struct ListBase *lbo);
+struct bController *copy_controller(struct bController *cont, const int flag);
+void copy_controllers(struct ListBase *lbn, const struct ListBase *lbo, const int flag);
void init_controller(struct bController *cont);
struct bController *new_controller(int type);
-struct bActuator *copy_actuator(struct bActuator *act);
-void copy_actuators(struct ListBase *lbn, struct ListBase *lbo);
+struct bActuator *copy_actuator(struct bActuator *act, const int flag);
+void copy_actuators(struct ListBase *lbn, const struct ListBase *lbo, const int flag);
void init_actuator(struct bActuator *act);
struct bActuator *new_actuator(int type);
void clear_sca_new_poins_ob(struct Object *ob);
@@ -70,7 +70,7 @@ void set_sca_new_poins_ob(struct Object *ob);
void set_sca_new_poins(void);
void BKE_sca_logic_links_remap(struct Main *bmain, struct Object *ob_old, struct Object *ob_new);
-void BKE_sca_logic_copy(struct Object *ob_new, struct Object *ob);
+void BKE_sca_logic_copy(struct Object *ob_new, const struct Object *ob, const int flag);
void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up);
void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index d2152950bff..b7ecb85819e 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -98,6 +98,7 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene);
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
+void BKE_scene_copy_data(struct Main *bmain, struct Scene *sce_dst, const struct Scene *sce_src, const int flag);
struct Scene *BKE_scene_copy(struct Main *bmain, struct Scene *sce, int type);
void BKE_scene_groups_relink(struct Scene *sce);
@@ -151,6 +152,8 @@ bool BKE_scene_check_rigidbody_active(const struct Scene *scene);
int BKE_scene_num_threads(const struct Scene *scene);
int BKE_render_num_threads(const struct RenderData *r);
+int BKE_render_preview_pixel_size(const struct RenderData *r);
+
double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value);
/* multiview */
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 811e9136fc9..657e99f05d1 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -335,7 +335,8 @@ bool BKE_sequence_base_shuffle(
bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene);
bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase);
void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, bool for_render);
-struct Sequence *BKE_sequence_dupli_recursive(struct Scene *scene, struct Scene *scene_to, struct Sequence *seq, int dupe_flag);
+struct Sequence *BKE_sequence_dupli_recursive(
+ const struct Scene *scene_src, struct Scene *scene_dst, struct Sequence *seq, int dupe_flag);
int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str);
bool BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur);
@@ -352,8 +353,8 @@ void BKE_sequencer_refresh_sound_length(struct Scene *scene);
void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq);
void BKE_sequence_base_dupli_recursive(
- struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase,
- int dupe_flag);
+ const struct Scene *scene_src, struct Scene *scene_dst, struct ListBase *nseqbase, const struct ListBase *seqbase,
+ int dupe_flag, const int flag);
bool BKE_sequence_is_valid_check(struct Sequence *seq);
void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce);
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index a5c626e74d7..6f8274fabc8 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -80,6 +80,8 @@ void BKE_sound_load(struct Main *main, struct bSound *sound);
void BKE_sound_free(struct bSound *sound);
+void BKE_sound_copy_data(struct Main *bmain, struct bSound *sound_dst, const struct bSound *sound_src, const int flag);
+
void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool lib_local);
#if defined(__AUD_C_API_H__) || defined(WITH_SYSTEM_AUDASPACE)
diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h
index b91b64c4b74..57f4c37f129 100644
--- a/source/blender/blenkernel/BKE_speaker.h
+++ b/source/blender/blenkernel/BKE_speaker.h
@@ -33,7 +33,8 @@ struct Speaker;
void BKE_speaker_init(struct Speaker *spk);
void *BKE_speaker_add(struct Main *bmain, const char *name);
-struct Speaker *BKE_speaker_copy(struct Main *bmain, struct Speaker *spk);
+void BKE_speaker_copy_data(struct Main *bmain, struct Speaker *spk_dst, const struct Speaker *spk_src, const int flag);
+struct Speaker *BKE_speaker_copy(struct Main *bmain, const struct Speaker *spk);
void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool lib_local);
void BKE_speaker_free(struct Speaker *spk);
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 081b7589af6..14d3318e059 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -52,7 +52,8 @@ bool BKE_text_reload(struct Text *text);
struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const char *relpath,
const bool is_internal);
struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath);
-struct Text *BKE_text_copy (struct Main *bmain, struct Text *ta);
+void BKE_text_copy_data(struct Main *bmain, struct Text *ta_dst, const struct Text *ta_src, const int flag);
+struct Text *BKE_text_copy (struct Main *bmain, const struct Text *ta);
void BKE_text_make_local (struct Main *bmain, struct Text *text, const bool lib_local);
void BKE_text_clear (struct Text *text);
void BKE_text_write (struct Text *text, const char *str);
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 9a60eb29957..8a9171673ea 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -70,7 +70,8 @@ void colorband_update_sort(struct ColorBand *coba);
void BKE_texture_free(struct Tex *tex);
void BKE_texture_default(struct Tex *tex);
-struct Tex *BKE_texture_copy(struct Main *bmain, struct Tex *tex);
+void BKE_texture_copy_data(struct Main *bmain, struct Tex *tex_dst, const struct Tex *tex_src, const int flag);
+struct Tex *BKE_texture_copy(struct Main *bmain, const struct Tex *tex);
struct Tex *BKE_texture_add(struct Main *bmain, const char *name);
struct Tex *BKE_texture_localize(struct Tex *tex);
void BKE_texture_make_local(struct Main *bmain, struct Tex *tex, const bool lib_local);
@@ -114,13 +115,13 @@ void BKE_texture_colormapping_default(struct ColorMapping *color
void BKE_texture_envmap_free_data(struct EnvMap *env);
void BKE_texture_envmap_free(struct EnvMap *env);
struct EnvMap *BKE_texture_envmap_add(void);
-struct EnvMap *BKE_texture_envmap_copy(struct EnvMap *env);
+struct EnvMap *BKE_texture_envmap_copy(const struct EnvMap *env, const int flag);
void BKE_texture_pointdensity_init_data(struct PointDensity *pd);
void BKE_texture_pointdensity_free_data(struct PointDensity *pd);
void BKE_texture_pointdensity_free(struct PointDensity *pd);
struct PointDensity *BKE_texture_pointdensity_add(void);
-struct PointDensity *BKE_texture_pointdensity_copy(struct PointDensity *pd);
+struct PointDensity *BKE_texture_pointdensity_copy(const struct PointDensity *pd, const int flag);
void BKE_texture_voxeldata_free_data(struct VoxelData *vd);
void BKE_texture_voxeldata_free(struct VoxelData *vd);
@@ -129,7 +130,7 @@ struct VoxelData *BKE_texture_voxeldata_copy(struct VoxelData *vd);
void BKE_texture_ocean_free(struct OceanTex *ot);
struct OceanTex *BKE_texture_ocean_add(void);
-struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot);
+struct OceanTex *BKE_texture_ocean_copy(const struct OceanTex *ot, const int flag);
bool BKE_texture_dependsOnTime(const struct Tex *texture);
bool BKE_texture_is_image_user(const struct Tex *tex);
@@ -144,6 +145,8 @@ void BKE_texture_get_value(
const struct Scene *scene, struct Tex *texture,
float *tex_co, struct TexResult *texres, bool use_color_management);
+void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 30873567297..d05ed1800fb 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -52,7 +52,7 @@ struct rcti;
/* **** Common functions **** */
void BKE_tracking_free(struct MovieTracking *tracking);
-void BKE_tracking_copy(struct MovieTracking *tracking_dst, struct MovieTracking *tracking_src);
+void BKE_tracking_copy(struct MovieTracking *tracking_dst, const struct MovieTracking *tracking_src, const int flag);
void BKE_tracking_settings_init(struct MovieTracking *tracking);
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
index 23bf9ec3d22..2a811496bb9 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -39,7 +39,8 @@ struct World;
void BKE_world_free(struct World *sc);
void BKE_world_init(struct World *wrld);
struct World *add_world(struct Main *bmian, const char *name);
-struct World *BKE_world_copy(struct Main *bmain, struct World *wrld);
+void BKE_world_copy_data(struct Main *bmain, struct World *wrld_dst, const struct World *wrld_src, const int flag);
+struct World *BKE_world_copy(struct Main *bmain, const struct World *wrld);
struct World *localize_world(struct World *wrld);
void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool lib_local);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 22d2eff6672..539a995078f 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -93,6 +93,10 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
# define ASSERT_IS_VALID_DM(dm)
#endif
+
+static ThreadMutex loops_cache_lock = BLI_MUTEX_INITIALIZER;
+
+
static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob);
static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid);
@@ -235,6 +239,23 @@ static int dm_getNumLoopTri(DerivedMesh *dm)
return numlooptris;
}
+static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm)
+{
+ if (dm->looptris.array) {
+ BLI_assert(dm->getNumLoopTri(dm) == dm->looptris.num);
+ }
+ else {
+ BLI_mutex_lock(&loops_cache_lock);
+ /* We need to ensure array is still NULL inside mutex-protected code, some other thread might have already
+ * recomputed those looptris. */
+ if (dm->looptris.array == NULL) {
+ dm->recalcLoopTri(dm);
+ }
+ BLI_mutex_unlock(&loops_cache_lock);
+ }
+ return dm->looptris.array;
+}
+
static CustomData *dm_getVertCData(DerivedMesh *dm)
{
return &dm->vertData;
@@ -278,6 +299,8 @@ void DM_init_funcs(DerivedMesh *dm)
dm->dupLoopArray = dm_dupLoopArray;
dm->dupPolyArray = dm_dupPolyArray;
+ dm->getLoopTriArray = dm_getLoopTriArray;
+
/* subtypes handle getting actual data */
dm->getNumLoopTri = dm_getNumLoopTri;
@@ -497,19 +520,6 @@ void DM_ensure_looptri_data(DerivedMesh *dm)
}
}
-/**
- * The purpose of this function is that we can call:
- * `dm->getLoopTriArray(dm)` and get the array returned.
- */
-void DM_ensure_looptri(DerivedMesh *dm)
-{
- const int numPolys = dm->getNumPolys(dm);
-
- if ((dm->looptris.num == 0) && (numPolys != 0)) {
- dm->recalcLoopTri(dm);
- }
-}
-
void DM_verttri_from_looptri(MVertTri *verttri, const MLoop *mloop, const MLoopTri *looptri, int looptri_num)
{
int i;
@@ -2201,7 +2211,6 @@ static void mesh_calc_modifiers(
if (dataMask & CD_MASK_MFACE) {
DM_ensure_tessface(finaldm);
}
- DM_ensure_looptri(finaldm);
/* without this, drawing ngon tri's faces will show ugly tessellated face
* normals and will also have to calculate normals on the fly, try avoid
@@ -3322,7 +3331,8 @@ void DM_calc_loop_tangents_step_0(
const CustomData *loopData, bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME], int tangent_names_count,
bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
- char *ract_uv_name, char *rren_uv_name, char *rtangent_mask) {
+ char *ract_uv_name, char *rren_uv_name, short *rtangent_mask)
+{
/* Active uv in viewport */
int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
*ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
@@ -3376,21 +3386,22 @@ void DM_calc_loop_tangents_step_0(
if (add)
*rtangent_mask |= 1 << n;
}
+
+ if (uv_layer_num == 0)
+ *rtangent_mask |= DM_TANGENT_MASK_ORCO;
}
void DM_calc_loop_tangents(
DerivedMesh *dm, bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME], int tangent_names_count)
{
- if (CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV) == 0)
- return;
int act_uv_n = -1;
int ren_uv_n = -1;
bool calc_act = false;
bool calc_ren = false;
char act_uv_name[MAX_NAME];
char ren_uv_name[MAX_NAME];
- char tangent_mask = 0;
+ short tangent_mask = 0;
DM_calc_loop_tangents_step_0(
&dm->loopData, calc_active_tangent, tangent_names, tangent_names_count,
&calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
@@ -3403,6 +3414,8 @@ void DM_calc_loop_tangents(
for (int i = 0; i < tangent_names_count; i++)
if (tangent_names[i][0])
DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, tangent_names[i]);
+ if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1)
+ CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, "");
if (calc_act && act_uv_name[0])
DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, act_uv_name);
if (calc_ren && ren_uv_name[0])
@@ -3464,19 +3477,24 @@ void DM_calc_loop_tangents(
mesh2tangent->orco = NULL;
mesh2tangent->mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name);
+
+ /* Fill the resulting tangent_mask */
if (!mesh2tangent->mloopuv) {
mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO);
if (!mesh2tangent->orco)
continue;
+
+ dm->tangent_mask |= DM_TANGENT_MASK_ORCO;
+ }
+ else {
+ int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name);
+ int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV);
+ BLI_assert(uv_ind != -1 && uv_start != -1);
+ BLI_assert(uv_ind - uv_start < MAX_MTFACE);
+ dm->tangent_mask |= 1 << (uv_ind - uv_start);
}
- mesh2tangent->tangent = dm->loopData.layers[index].data;
- /* Fill the resulting tangent_mask */
- int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name);
- int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV);
- BLI_assert(uv_ind != -1 && uv_start != -1);
- BLI_assert(uv_ind - uv_start < MAX_MTFACE);
- dm->tangent_mask |= 1 << (uv_ind - uv_start);
+ mesh2tangent->tangent = dm->loopData.layers[index].data;
BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
}
@@ -3492,21 +3510,19 @@ void DM_calc_loop_tangents(
#endif
- int uv_index, tan_index;
-
/* Update active layer index */
- uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n);
- if (uv_index != -1) {
- tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name);
+ int act_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n);
+ if (act_uv_index != -1) {
+ int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[act_uv_index].name);
CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
- }
+ } /* else tangent has been built from orco */
/* Update render layer index */
- uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n);
- if (uv_index != -1) {
- tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name);
+ int ren_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n);
+ if (ren_uv_index != -1) {
+ int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[ren_uv_index].name);
CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
- }
+ } /* else tangent has been built from orco */
}
}
@@ -4379,35 +4395,3 @@ MFace *DM_get_tessface_array(DerivedMesh *dm, bool *r_allocated)
return mface;
}
-
-const MLoopTri *DM_get_looptri_array(
- DerivedMesh *dm,
- const MVert *mvert,
- const MPoly *mpoly, int mpoly_len,
- const MLoop *mloop, int mloop_len,
- bool *r_allocated)
-{
- const MLoopTri *looptri = dm->getLoopTriArray(dm);
- *r_allocated = false;
-
- if (looptri == NULL) {
- if (mpoly_len > 0) {
- const int looptris_num = poly_to_tri_count(mpoly_len, mloop_len);
- MLoopTri *looptri_data;
-
- looptri_data = MEM_mallocN(sizeof(MLoopTri) * looptris_num, __func__);
-
- BKE_mesh_recalc_looptri(
- mloop, mpoly,
- mvert,
- mloop_len, mpoly_len,
- looptri_data);
-
- looptri = looptri_data;
-
- *r_allocated = true;
- }
- }
-
- return looptri;
-}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 1e33fe4ab46..bb4e09364d4 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -88,7 +88,7 @@ bAction *add_empty_action(Main *bmain, const char name[])
{
bAction *act;
- act = BKE_libblock_alloc(bmain, ID_AC, name);
+ act = BKE_libblock_alloc(bmain, ID_AC, name, 0);
return act;
}
@@ -120,46 +120,56 @@ void BKE_action_free(bAction *act)
/* .................................. */
-bAction *BKE_action_copy(Main *bmain, bAction *src)
+/**
+ * Only copy internal data of Action ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_action_copy_data(Main *UNUSED(bmain), bAction *act_dst, const bAction *act_src, const int UNUSED(flag))
{
- bAction *dst = NULL;
- bActionGroup *dgrp, *sgrp;
- FCurve *dfcu, *sfcu;
-
- if (src == NULL)
- return NULL;
- dst = BKE_libblock_copy(bmain, &src->id);
-
+ bActionGroup *grp_dst, *grp_src;
+ FCurve *fcu_dst, *fcu_src;
+
/* duplicate the lists of groups and markers */
- BLI_duplicatelist(&dst->groups, &src->groups);
- BLI_duplicatelist(&dst->markers, &src->markers);
-
+ BLI_duplicatelist(&act_dst->groups, &act_src->groups);
+ BLI_duplicatelist(&act_dst->markers, &act_src->markers);
+
/* copy F-Curves, fixing up the links as we go */
- BLI_listbase_clear(&dst->curves);
-
- for (sfcu = src->curves.first; sfcu; sfcu = sfcu->next) {
+ BLI_listbase_clear(&act_dst->curves);
+
+ for (fcu_src = act_src->curves.first; fcu_src; fcu_src = fcu_src->next) {
/* duplicate F-Curve */
- dfcu = copy_fcurve(sfcu);
- BLI_addtail(&dst->curves, dfcu);
-
+ fcu_dst = copy_fcurve(fcu_src); /* XXX TODO pass subdata flag? But surprisingly does not seem to be doing any ID refcounting... */
+ BLI_addtail(&act_dst->curves, fcu_dst);
+
/* fix group links (kindof bad list-in-list search, but this is the most reliable way) */
- for (dgrp = dst->groups.first, sgrp = src->groups.first; dgrp && sgrp; dgrp = dgrp->next, sgrp = sgrp->next) {
- if (sfcu->grp == sgrp) {
- dfcu->grp = dgrp;
-
- if (dgrp->channels.first == sfcu)
- dgrp->channels.first = dfcu;
- if (dgrp->channels.last == sfcu)
- dgrp->channels.last = dfcu;
-
+ for (grp_dst = act_dst->groups.first, grp_src = act_src->groups.first;
+ grp_dst && grp_src;
+ grp_dst = grp_dst->next, grp_src = grp_src->next)
+ {
+ if (fcu_src->grp == grp_src) {
+ fcu_dst->grp = grp_dst;
+
+ if (grp_dst->channels.first == fcu_src) {
+ grp_dst->channels.first = fcu_dst;
+ }
+ if (grp_dst->channels.last == fcu_src) {
+ grp_dst->channels.last = fcu_dst;
+ }
break;
}
}
}
-
- BKE_id_copy_ensure_local(bmain, &src->id, &dst->id);
+}
- return dst;
+bAction *BKE_action_copy(Main *bmain, const bAction *act_src)
+{
+ bAction *act_copy;
+ BKE_id_copy_ex(bmain, &act_src->id, (ID **)&act_copy, 0, false);
+ return act_copy;
}
/* *************** Action Groups *************** */
@@ -523,7 +533,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose)
*
* \param dst Should be freed already, makes entire duplicate.
*/
-void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
+void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const bool copy_constraints)
{
bPose *outPose;
bPoseChannel *pchan;
@@ -553,9 +563,8 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
outPose->avs = src->avs;
for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {
-
- if (pchan->custom) {
- id_us_plus(&pchan->custom->id);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)pchan->custom);
}
/* warning, O(n2) here, if done without the hash, but these are rarely used features. */
@@ -570,13 +579,13 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
}
if (copy_constraints) {
- BKE_constraints_copy(&listb, &pchan->constraints, true); // BKE_constraints_copy NULLs listb
+ BKE_constraints_copy_ex(&listb, &pchan->constraints, flag, true); // BKE_constraints_copy NULLs listb
pchan->constraints = listb;
pchan->mpath = NULL; /* motion paths should not get copied yet... */
}
if (pchan->prop) {
- pchan->prop = IDP_CopyProperty(pchan->prop);
+ pchan->prop = IDP_CopyProperty_ex(pchan->prop, flag);
}
}
@@ -588,6 +597,11 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
*dst = outPose;
}
+void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constraints)
+{
+ BKE_pose_copy_data_ex(dst, src, 0, copy_constraints);
+}
+
void BKE_pose_itasc_init(bItasc *itasc)
{
if (itasc) {
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 0b637355ecf..64b33326aa9 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -259,7 +259,7 @@ void BKE_animdata_free(ID *id, const bool do_id_user)
/* Copying -------------------------------------------- */
/* Make a copy of the given AnimData - to be used when copying datablocks */
-AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action)
+AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action)
{
AnimData *dadt;
@@ -270,8 +270,9 @@ AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action)
/* make a copy of action - at worst, user has to delete copies... */
if (do_action) {
- dadt->action = BKE_action_copy(G.main, adt->action);
- dadt->tmpact = BKE_action_copy(G.main, adt->tmpact);
+ BLI_assert(bmain != NULL);
+ BKE_id_copy_ex(bmain, (ID *)dadt->action, (ID **)&dadt->action, 0, false);
+ BKE_id_copy_ex(bmain, (ID *)dadt->tmpact, (ID **)&dadt->tmpact, 0, false);
}
else {
id_us_plus((ID *)dadt->action);
@@ -291,7 +292,7 @@ AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action)
return dadt;
}
-bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action)
+bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const bool do_action)
{
AnimData *adt;
@@ -303,7 +304,7 @@ bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action)
adt = BKE_animdata_from_id(id_from);
if (adt) {
IdAdtTemplate *iat = (IdAdtTemplate *)id_to;
- iat->adt = BKE_animdata_copy(adt, do_action);
+ iat->adt = BKE_animdata_copy(bmain, adt, do_action);
}
return true;
@@ -397,73 +398,6 @@ void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes a
}
}
-/* Make Local -------------------------------------------- */
-
-static void make_local_strips(ListBase *strips)
-{
- NlaStrip *strip;
-
- for (strip = strips->first; strip; strip = strip->next) {
- if (strip->act) BKE_action_make_local(G.main, strip->act, false);
- if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target, false);
-
- make_local_strips(&strip->strips);
- }
-}
-
-/* Use local copy instead of linked copy of various ID-blocks */
-void BKE_animdata_make_local(AnimData *adt)
-{
- NlaTrack *nlt;
-
- /* Actions - Active and Temp */
- if (adt->action) BKE_action_make_local(G.main, adt->action, false);
- if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact, false);
- /* Remaps */
- if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target, false);
-
- /* Drivers */
- /* TODO: need to remap the ID-targets too? */
-
- /* NLA Data */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next)
- make_local_strips(&nlt->strips);
-}
-
-
-/* When duplicating data (i.e. objects), drivers referring to the original data will
- * get updated to point to the duplicated data (if drivers belong to the new data)
- */
-void BKE_animdata_relink(AnimData *adt)
-{
- /* sanity check */
- if (adt == NULL)
- return;
-
- /* drivers */
- if (adt->drivers.first) {
- FCurve *fcu;
-
- /* check each driver against all the base paths to see if any should go */
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
-
- /* driver variables */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- /* only change the used targets, since the others will need fixing manually anyway */
- DRIVER_TARGETS_USED_LOOPER(dvar)
- {
- if (dtar->id && dtar->id->newid) {
- dtar->id = dtar->id->newid;
- }
- }
- DRIVER_TARGETS_LOOPER_END
- }
- }
- }
-}
-
/* Sub-ID Regrouping ------------------------------------------- */
/**
@@ -690,6 +624,8 @@ char *BKE_animdata_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *p
}
break;
}
+ default:
+ break;
}
/* fix RNA pointer, as we've now changed the ID root by changing the paths */
@@ -1414,7 +1350,7 @@ void BKE_keyingset_free_path(KeyingSet *ks, KS_Path *ksp)
}
/* Copy all KeyingSets in the given list */
-void BKE_keyingsets_copy(ListBase *newlist, ListBase *list)
+void BKE_keyingsets_copy(ListBase *newlist, const ListBase *list)
{
KeyingSet *ksn;
KS_Path *kspn;
@@ -1586,7 +1522,8 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
}
case PROP_INT:
{
- const int value_coerce = (int)value;
+ int value_coerce = (int)value;
+ RNA_property_int_clamp(ptr, prop, &value_coerce);
if (array_index != -1) {
if (RNA_property_int_get_index(ptr, prop, array_index) != value_coerce) {
RNA_property_int_set_index(ptr, prop, array_index, value_coerce);
@@ -1603,15 +1540,17 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
}
case PROP_FLOAT:
{
+ float value_coerce = value;
+ RNA_property_float_clamp(ptr, prop, &value_coerce);
if (array_index != -1) {
- if (RNA_property_float_get_index(ptr, prop, array_index) != value) {
- RNA_property_float_set_index(ptr, prop, array_index, value);
+ if (RNA_property_float_get_index(ptr, prop, array_index) != value_coerce) {
+ RNA_property_float_set_index(ptr, prop, array_index, value_coerce);
written = true;
}
}
else {
- if (RNA_property_float_get(ptr, prop) != value) {
- RNA_property_float_set(ptr, prop, value);
+ if (RNA_property_float_get(ptr, prop) != value_coerce) {
+ RNA_property_float_set(ptr, prop, value_coerce);
written = true;
}
}
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index 43fd47981b1..f39d8006f76 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -106,7 +106,8 @@ const char *BKE_appdir_folder_default(void)
static char *blender_version_decimal(const int ver)
{
static char version_str[5];
- sprintf(version_str, "%d.%02d", ver / 100, ver % 100);
+ BLI_assert(ver < 1000);
+ BLI_snprintf(version_str, sizeof(version_str), "%d.%02d", ver / 100, ver % 100);
return version_str;
}
@@ -212,8 +213,10 @@ static bool get_path_local(
/* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
#ifdef __APPLE__
/* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
- static char osx_resourses[FILE_MAX];
- sprintf(osx_resourses, "%s../Resources", bprogdir);
+ char osx_resourses[FILE_MAX];
+ BLI_snprintf(osx_resourses, sizeof(osx_resourses), "%s../Resources", bprogdir);
+ /* Remove the '/../' added above. */
+ BLI_cleanup_path(NULL, osx_resourses);
return test_path(targetpath, targetpath_len, osx_resourses, blender_version_decimal(ver), relfolder);
#else
return test_path(targetpath, targetpath_len, bprogdir, blender_version_decimal(ver), relfolder);
@@ -591,6 +594,9 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name)
else {
BLI_path_program_search(fullname, maxlen, name);
}
+ /* Remove "/./" and "/../" so string comparisons can be used on the path. */
+ BLI_cleanup_path(NULL, fullname);
+
#if defined(DEBUG)
if (!STREQ(name, fullname)) {
printf("guessing '%s' == '%s'\n", name, fullname);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index d7ea534068d..669344e18d7 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -83,7 +83,7 @@ bArmature *BKE_armature_add(Main *bmain, const char *name)
{
bArmature *arm;
- arm = BKE_libblock_alloc(bmain, ID_AR, name);
+ arm = BKE_libblock_alloc(bmain, ID_AR, name, 0);
arm->deformflag = ARM_DEF_VGROUP | ARM_DEF_ENVELOPE;
arm->flag = ARM_COL_CUSTOM; /* custom bone-group colors */
arm->layer = 1;
@@ -150,54 +150,70 @@ void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local)
BKE_id_make_local_generic(bmain, &arm->id, true, lib_local);
}
-static void copy_bonechildren(Bone *newBone, Bone *oldBone, Bone *actBone, Bone **newActBone)
+static void copy_bonechildren(
+ Bone *bone_dst, const Bone *bone_src, const Bone *bone_src_act, Bone **r_bone_dst_act, const int flag)
{
- Bone *curBone, *newChildBone;
+ Bone *bone_src_child, *bone_dst_child;
- if (oldBone == actBone)
- *newActBone = newBone;
+ if (bone_src == bone_src_act) {
+ *r_bone_dst_act = bone_dst;
+ }
- if (oldBone->prop)
- newBone->prop = IDP_CopyProperty(oldBone->prop);
+ if (bone_src->prop) {
+ bone_dst->prop = IDP_CopyProperty_ex(bone_src->prop, flag);
+ }
/* Copy this bone's list */
- BLI_duplicatelist(&newBone->childbase, &oldBone->childbase);
+ BLI_duplicatelist(&bone_dst->childbase, &bone_src->childbase);
/* For each child in the list, update it's children */
- newChildBone = newBone->childbase.first;
- for (curBone = oldBone->childbase.first; curBone; curBone = curBone->next) {
- newChildBone->parent = newBone;
- copy_bonechildren(newChildBone, curBone, actBone, newActBone);
- newChildBone = newChildBone->next;
+ for (bone_src_child = bone_src->childbase.first, bone_dst_child = bone_dst->childbase.first;
+ bone_src_child;
+ bone_src_child = bone_src_child->next, bone_dst_child = bone_dst_child->next)
+ {
+ bone_dst_child->parent = bone_dst;
+ copy_bonechildren(bone_dst_child, bone_src_child, bone_src_act, r_bone_dst_act, flag);
}
}
-bArmature *BKE_armature_copy(Main *bmain, bArmature *arm)
+/**
+ * Only copy internal data of Armature ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_armature_copy_data(Main *UNUSED(bmain), bArmature *arm_dst, const bArmature *arm_src, const int flag)
{
- bArmature *newArm;
- Bone *oldBone, *newBone;
- Bone *newActBone = NULL;
+ Bone *bone_src, *bone_dst;
+ Bone *bone_dst_act = NULL;
+
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
- newArm = BKE_libblock_copy(bmain, &arm->id);
- BLI_duplicatelist(&newArm->bonebase, &arm->bonebase);
+ BLI_duplicatelist(&arm_dst->bonebase, &arm_src->bonebase);
/* Duplicate the childrens' lists */
- newBone = newArm->bonebase.first;
- for (oldBone = arm->bonebase.first; oldBone; oldBone = oldBone->next) {
- newBone->parent = NULL;
- copy_bonechildren(newBone, oldBone, arm->act_bone, &newActBone);
- newBone = newBone->next;
+ bone_dst = arm_dst->bonebase.first;
+ for (bone_src = arm_src->bonebase.first; bone_src; bone_src = bone_src->next) {
+ bone_dst->parent = NULL;
+ copy_bonechildren(bone_dst, bone_src, arm_src->act_bone, &bone_dst_act, flag_subdata);
+ bone_dst = bone_dst->next;
}
- newArm->act_bone = newActBone;
-
- newArm->edbo = NULL;
- newArm->act_edbone = NULL;
- newArm->sketch = NULL;
+ arm_dst->act_bone = bone_dst_act;
- BKE_id_copy_ensure_local(bmain, &arm->id, &newArm->id);
+ arm_dst->edbo = NULL;
+ arm_dst->act_edbone = NULL;
+ arm_dst->sketch = NULL;
+}
- return newArm;
+bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm)
+{
+ bArmature *arm_copy;
+ BKE_id_copy_ex(bmain, &arm->id, (ID **)&arm_copy, 0, false);
+ return arm_copy;
}
static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name)
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index df0bddede3b..a4714041edf 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -702,4 +702,8 @@ void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob)
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
}
+ /* Rest of operations are NO-OP in depsgraph, so can clear
+ * flag now.
+ */
+ ob->recalc &= ~OB_RECALC_ALL;
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index ceb641073e0..2624019e63a 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -226,19 +226,6 @@ void BKE_blender_userdef_free_data(UserDef *userdef)
}
/**
- * Handle changes in settings that need refreshing.
- */
-void BKE_blender_userdef_refresh(void)
-{
- /* prevent accidents */
- if (U.pixelsize == 0) U.pixelsize = 1;
-
- BLF_default_dpi(U.pixelsize * U.dpi);
- U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72;
-
-}
-
-/**
* Write U from userdef.
* This function defines which settings a template will override for the user preferences.
*/
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index a521d671ea4..980df05aca2 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -114,6 +114,7 @@ static void setup_app_data(
const char *filepath, ReportList *reports)
{
Scene *curscene = NULL;
+ const bool is_startup = (bfd->filename[0] == '\0');
const bool recover = (G.fileflags & G_FILE_RECOVER) != 0;
enum {
LOAD_UI = 1,
@@ -129,7 +130,7 @@ static void setup_app_data(
else if (BLI_listbase_is_empty(&bfd->main->screen)) {
mode = LOAD_UNDO;
}
- else if (G.fileflags & G_FILE_NO_UI) {
+ else if ((G.fileflags & G_FILE_NO_UI) && (is_startup == false)) {
mode = LOAD_UI_OFF;
}
else {
@@ -250,7 +251,9 @@ static void setup_app_data(
CTX_data_scene_set(C, curscene);
}
else {
- G.fileflags = bfd->fileflags;
+ /* Keep state from preferences. */
+ const int fileflags_skip = G_FILE_FLAGS_RUNTIME;
+ G.fileflags = (G.fileflags & fileflags_skip) | (bfd->fileflags & ~fileflags_skip);
CTX_wm_manager_set(C, G.main->wm.first);
CTX_wm_screen_set(C, bfd->curscreen);
CTX_data_scene_set(C, bfd->curscene);
@@ -413,9 +416,9 @@ bool BKE_blendfile_read_from_memfile(
if (bfd) {
/* remove the unused screens and wm */
while (bfd->main->wm.first)
- BKE_libblock_free_ex(bfd->main, bfd->main->wm.first, true, true);
+ BKE_libblock_free(bfd->main, bfd->main->wm.first);
while (bfd->main->screen.first)
- BKE_libblock_free_ex(bfd->main, bfd->main->screen.first, true, true);
+ BKE_libblock_free(bfd->main, bfd->main->screen.first);
setup_app_data(C, bfd, "<memory1>", reports);
}
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index b4bc83bf94c..7ca4e07076d 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -1581,7 +1581,7 @@ void boid_free_settings(BoidSettings *boids)
MEM_freeN(boids);
}
}
-BoidSettings *boid_copy_settings(BoidSettings *boids)
+BoidSettings *boid_copy_settings(const BoidSettings *boids)
{
BoidSettings *nboids = NULL;
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 57b707a31d3..03b0710c8fc 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -152,7 +152,7 @@ Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
{
Brush *brush;
- brush = BKE_libblock_alloc(bmain, ID_BR, name);
+ brush = BKE_libblock_alloc(bmain, ID_BR, name, 0);
BKE_brush_init(brush);
@@ -172,34 +172,38 @@ struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode)
return NULL;
}
-Brush *BKE_brush_copy(Main *bmain, Brush *brush)
+/**
+ * Only copy internal data of Brush ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_brush_copy_data(Main *UNUSED(bmain), Brush *brush_dst, const Brush *brush_src, const int flag)
{
- Brush *brushn;
-
- brushn = BKE_libblock_copy(bmain, &brush->id);
-
- if (brush->mtex.tex)
- id_us_plus((ID *)brush->mtex.tex);
-
- if (brush->mask_mtex.tex)
- id_us_plus((ID *)brush->mask_mtex.tex);
-
- if (brush->paint_curve)
- id_us_plus((ID *)brush->paint_curve);
-
- if (brush->icon_imbuf)
- brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf);
+ if (brush_src->icon_imbuf) {
+ brush_dst->icon_imbuf = IMB_dupImBuf(brush_src->icon_imbuf);
+ }
- brushn->preview = NULL;
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
+ BKE_previewimg_id_copy(&brush_dst->id, &brush_src->id);
+ }
+ else {
+ brush_dst->preview = NULL;
+ }
- brushn->curve = curvemapping_copy(brush->curve);
+ brush_dst->curve = curvemapping_copy(brush_src->curve);
/* enable fake user by default */
- id_fake_user_set(&brush->id);
-
- BKE_id_copy_ensure_local(bmain, &brush->id, &brushn->id);
+ id_fake_user_set(&brush_dst->id);
+}
- return brushn;
+Brush *BKE_brush_copy(Main *bmain, const Brush *brush)
+{
+ Brush *brush_copy;
+ BKE_id_copy_ex(bmain, &brush->id, (ID **)&brush_copy, 0, false);
+ return brush_copy;
}
/** Free (or release) any data used by this brush (does not free the brush itself). */
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index c0e4ef37a93..775499304d4 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -917,10 +917,10 @@ BVHTree *bvhtree_from_mesh_faces(
/**
* Builds a bvh tree where nodes are the given tessellated faces (note: does not copy given mfaces!).
- * \param vert_allocated if true, vert freeing will be done when freeing data.
- * \param face_allocated if true, face freeing will be done when freeing data.
+ * \param vert_allocated: if true, vert freeing will be done when freeing data.
+ * \param face_allocated: if true, face freeing will be done when freeing data.
* \param faces_mask: if not null, true elements give which faces to add to BVH tree.
- * \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
+ * \param faces_num_active: if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_faces_ex(
BVHTreeFromMesh *data, const MVert *vert, const bool vert_allocated,
@@ -1137,7 +1137,6 @@ BVHTree *bvhtree_from_mesh_looptri(
const MLoopTri *looptri = NULL;
bool vert_allocated = false;
bool loop_allocated = false;
- bool looptri_allocated = false;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
tree = bvhcache_find(dm->bvhCache, BVHTREE_FROM_LOOPTRI);
@@ -1150,12 +1149,7 @@ BVHTree *bvhtree_from_mesh_looptri(
mpoly = DM_get_poly_array(dm, &poly_allocated);
mloop = DM_get_loop_array(dm, &loop_allocated);
- looptri = DM_get_looptri_array(
- dm,
- mvert,
- mpoly, dm->getNumPolys(dm),
- mloop, dm->getNumLoops(dm),
- &looptri_allocated);
+ looptri = dm->getLoopTriArray(dm);
if (poly_allocated) {
MEM_freeN(mpoly);
@@ -1193,7 +1187,7 @@ BVHTree *bvhtree_from_mesh_looptri(
data, tree, true, epsilon,
mvert, vert_allocated,
mloop, loop_allocated,
- looptri, looptri_allocated);
+ looptri, false);
}
else {
if (vert_allocated) {
@@ -1202,9 +1196,6 @@ BVHTree *bvhtree_from_mesh_looptri(
if (loop_allocated) {
MEM_freeN(mloop);
}
- if (looptri_allocated) {
- MEM_freeN((void *)looptri);
- }
memset(data, 0, sizeof(*data));
}
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index 67c66d4e40b..1916531b066 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -66,7 +66,7 @@ void BKE_cachefiles_exit(void)
void *BKE_cachefile_add(Main *bmain, const char *name)
{
- CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, name);
+ CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, name, 0);
BKE_cachefile_init(cache_file);
@@ -100,16 +100,26 @@ void BKE_cachefile_free(CacheFile *cache_file)
BLI_freelistN(&cache_file->object_paths);
}
-CacheFile *BKE_cachefile_copy(Main *bmain, CacheFile *cache_file)
+/**
+ * Only copy internal data of CacheFile ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_cachefile_copy_data(
+ Main *UNUSED(bmain), CacheFile *cache_file_dst, const CacheFile *UNUSED(cache_file_src), const int UNUSED(flag))
{
- 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);
+ cache_file_dst->handle = NULL;
+ BLI_listbase_clear(&cache_file_dst->object_paths);
+}
- return new_cache_file;
+CacheFile *BKE_cachefile_copy(Main *bmain, const CacheFile *cache_file)
+{
+ CacheFile *cache_file_copy;
+ BKE_id_copy_ex(bmain, &cache_file->id, (ID **)&cache_file_copy, 0, false);
+ return cache_file_copy;
}
void BKE_cachefile_make_local(Main *bmain, CacheFile *cache_file, const bool lib_local)
@@ -166,10 +176,12 @@ void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, co
const float time = BKE_cachefile_time_offset(cache_file, ctime, fps);
if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) {
+ BKE_cachefile_clean(scene, cache_file);
#ifdef WITH_ALEMBIC
ABC_free_handle(cache_file->handle);
cache_file->handle = ABC_create_handle(filename, NULL);
#endif
+ break;
}
}
}
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 9cb553aa27b..719125b3317 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -86,22 +86,31 @@ void *BKE_camera_add(Main *bmain, const char *name)
{
Camera *cam;
- cam = BKE_libblock_alloc(bmain, ID_CA, name);
+ cam = BKE_libblock_alloc(bmain, ID_CA, name, 0);
BKE_camera_init(cam);
return cam;
}
-Camera *BKE_camera_copy(Main *bmain, Camera *cam)
+/**
+ * Only copy internal data of Camera ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *UNUSED(cam_dst), const Camera *UNUSED(cam_src), const int UNUSED(flag))
{
- Camera *camn;
-
- camn = BKE_libblock_copy(bmain, &cam->id);
-
- BKE_id_copy_ensure_local(bmain, &cam->id, &camn->id);
+ /* Nothing to do! */
+}
- return camn;
+Camera *BKE_camera_copy(Main *bmain, const Camera *cam)
+{
+ Camera *cam_copy;
+ BKE_id_copy_ex(bmain, &cam->id, (ID **)&cam_copy, 0, false);
+ return cam_copy;
}
void BKE_camera_make_local(Main *bmain, Camera *cam, const bool lib_local)
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index ee3a763e4c8..42f818b8c92 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1935,19 +1935,6 @@ void CDDM_recalc_looptri(DerivedMesh *dm)
cddm->dm.looptris.array);
}
-static const MLoopTri *cdDM_getLoopTriArray(DerivedMesh *dm)
-{
- if (dm->looptris.array) {
- BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
- }
- else {
- dm->recalcLoopTri(dm);
-
- /* ccdm is an exception here, that recalcLoopTri will fill in the array too */
- }
- return dm->looptris.array;
-}
-
static void cdDM_free_internal(CDDerivedMesh *cddm)
{
if (cddm->pmap) MEM_freeN(cddm->pmap);
@@ -1998,8 +1985,6 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getEdgeDataArray = DM_get_edge_data_layer;
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
- dm->getLoopTriArray = cdDM_getLoopTriArray;
-
dm->calcNormals = CDDM_calc_normals;
dm->calcLoopNormals = CDDM_calc_loop_normals;
dm->calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
@@ -3192,7 +3177,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
MPoly *target_poly = cddm->mpoly + *(cddm->pmap[v_target].indices + i_poly);
if (cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, +1) ||
- cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1))
+ cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1))
{
found = true;
break;
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index ee0fde1ea61..dd93606a67c 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -807,7 +807,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
if ( !dm )
return 0;
- DM_ensure_looptri(dm);
cloth_from_mesh ( clmd, dm );
// create springs
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index b3a0895d063..ee0f904c3a6 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -130,7 +130,7 @@ void curvemapping_free(CurveMapping *cumap)
}
}
-void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap)
+void curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
{
int a;
@@ -146,7 +146,7 @@ void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap)
}
}
-CurveMapping *curvemapping_copy(CurveMapping *cumap)
+CurveMapping *curvemapping_copy(const CurveMapping *cumap)
{
if (cumap) {
CurveMapping *cumapn = MEM_dupallocN(cumap);
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 9bc1ce16284..7ad2ed91e87 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -790,7 +790,7 @@ static void default_get_tarmat(bConstraint *con, bConstraintOb *UNUSED(cob), bCo
ct = ctn; \
} \
} (void)0
-
+
/* --------- ChildOf Constraint ------------ */
static void childof_new_data(void *cdata)
@@ -1019,7 +1019,7 @@ static void vectomat(const float vec[3], const float target_up[3], short axis, s
}
/* project the up vector onto the plane specified by n */
- project_v3_v3v3(proj, u, n); /* first u onto n... */
+ project_v3_v3v3_normalized(proj, u, n); /* first u onto n... */
sub_v3_v3v3(proj, u, proj); /* then onto the plane */
/* proj specifies the transformation of the up axis */
@@ -1930,7 +1930,7 @@ static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *
/* calculate normalizing scale factor for non-essential values */
if (obsize[data->flag] != 0)
- fac = sqrtf(volume / obsize[data->flag]) / obsize[data->flag];
+ fac = sqrtf(volume / obsize[data->flag]);
/* apply scaling factor to the channels not being kept */
switch (data->flag) {
@@ -4737,29 +4737,30 @@ static void con_fix_copied_refs_cb(bConstraint *UNUSED(con), ID **idpoin, bool i
}
/* duplicate all of the constraints in a constraint stack */
-void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern)
+void BKE_constraints_copy_ex(ListBase *dst, const ListBase *src, const int flag, bool do_extern)
{
bConstraint *con, *srccon;
-
+
BLI_listbase_clear(dst);
BLI_duplicatelist(dst, src);
-
+
for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
-
+
/* make a new copy of the constraint's data */
con->data = MEM_dupallocN(con->data);
-
+
/* only do specific constraints if required */
if (cti) {
/* perform custom copying operations if needed */
if (cti->copy_data)
cti->copy_data(con, srccon);
-
- /* fix usercounts for all referenced data in referenced data */
- if (cti->id_looper)
+
+ /* Fix usercounts for all referenced data that need it. */
+ if (cti->id_looper && (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
cti->id_looper(con, con_fix_copied_refs_cb, NULL);
-
+ }
+
/* for proxies we don't want to make extern */
if (do_extern) {
/* go over used ID-links for this constraint to ensure that they are valid for proxies */
@@ -4770,6 +4771,11 @@ void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern)
}
}
+void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern)
+{
+ BKE_constraints_copy_ex(dst, src, 0, do_extern);
+}
+
/* ......... */
bConstraint *BKE_constraints_find_name(ListBase *list, const char *name)
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 439abb1d593..795feb58bf6 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -179,7 +179,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
{
Curve *cu;
- cu = BKE_libblock_alloc(bmain, ID_CU, name);
+ cu = BKE_libblock_alloc(bmain, ID_CU, name, 0);
cu->type = type;
BKE_curve_init(cu);
@@ -187,42 +187,39 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
return cu;
}
-Curve *BKE_curve_copy(Main *bmain, Curve *cu)
+/**
+ * Only copy internal data of Curve ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_curve_copy_data(Main *bmain, Curve *cu_dst, const Curve *cu_src, const int flag)
{
- Curve *cun;
- int a;
-
- cun = BKE_libblock_copy(bmain, &cu->id);
+ BLI_listbase_clear(&cu_dst->nurb);
+ BKE_nurbList_duplicate(&(cu_dst->nurb), &(cu_src->nurb));
- BLI_listbase_clear(&cun->nurb);
- BKE_nurbList_duplicate(&(cun->nurb), &(cu->nurb));
+ cu_dst->mat = MEM_dupallocN(cu_src->mat);
- cun->mat = MEM_dupallocN(cu->mat);
- for (a = 0; a < cun->totcol; a++) {
- id_us_plus((ID *)cun->mat[a]);
- }
-
- cun->str = MEM_dupallocN(cu->str);
- cun->strinfo = MEM_dupallocN(cu->strinfo);
- cun->tb = MEM_dupallocN(cu->tb);
- cun->bb = MEM_dupallocN(cu->bb);
+ cu_dst->str = MEM_dupallocN(cu_src->str);
+ cu_dst->strinfo = MEM_dupallocN(cu_src->strinfo);
+ cu_dst->tb = MEM_dupallocN(cu_src->tb);
+ cu_dst->bb = MEM_dupallocN(cu_src->bb);
- if (cu->key) {
- cun->key = BKE_key_copy(bmain, cu->key);
- cun->key->from = (ID *)cun;
+ if (cu_src->key) {
+ BKE_id_copy_ex(bmain, &cu_src->key->id, (ID **)&cu_dst->key, flag, false);
}
- cun->editnurb = NULL;
- cun->editfont = NULL;
-
- id_us_plus((ID *)cun->vfont);
- id_us_plus((ID *)cun->vfontb);
- id_us_plus((ID *)cun->vfonti);
- id_us_plus((ID *)cun->vfontbi);
-
- BKE_id_copy_ensure_local(bmain, &cu->id, &cun->id);
+ cu_dst->editnurb = NULL;
+ cu_dst->editfont = NULL;
+}
- return cun;
+Curve *BKE_curve_copy(Main *bmain, const Curve *cu)
+{
+ Curve *cu_copy;
+ BKE_id_copy_ex(bmain, &cu->id, (ID **)&cu_copy, 0, false);
+ return cu_copy;
}
void BKE_curve_make_local(Main *bmain, Curve *cu, const bool lib_local)
@@ -468,7 +465,7 @@ void BKE_nurbList_free(ListBase *lb)
BLI_listbase_clear(lb);
}
-Nurb *BKE_nurb_duplicate(Nurb *nu)
+Nurb *BKE_nurb_duplicate(const Nurb *nu)
{
Nurb *newnu;
int len;
@@ -532,7 +529,7 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
return newnu;
}
-void BKE_nurbList_duplicate(ListBase *lb1, ListBase *lb2)
+void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2)
{
Nurb *nu, *nun;
@@ -744,6 +741,7 @@ BezTriple *BKE_nurb_bezt_get_prev(Nurb *nu, BezTriple *bezt)
BezTriple *bezt_prev;
BLI_assert(ARRAY_HAS_ITEM(bezt, nu->bezt, nu->pntsu));
+ BLI_assert(nu->pntsv == 1);
if (bezt == nu->bezt) {
if (nu->flagu & CU_NURB_CYCLIC) {
@@ -765,6 +763,7 @@ BPoint *BKE_nurb_bpoint_get_prev(Nurb *nu, BPoint *bp)
BPoint *bp_prev;
BLI_assert(ARRAY_HAS_ITEM(bp, nu->bp, nu->pntsu));
+ BLI_assert(nu->pntsv == 1);
if (bp == nu->bp) {
if (nu->flagu & CU_NURB_CYCLIC) {
@@ -781,7 +780,7 @@ BPoint *BKE_nurb_bpoint_get_prev(Nurb *nu, BPoint *bp)
return bp_prev;
}
-void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), struct BezTriple *bezt, float r_normal[3])
+void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), BezTriple *bezt, float r_normal[3])
{
/* calculate the axis matrix from the spline */
float dir_prev[3], dir_next[3];
@@ -796,7 +795,7 @@ void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), struct BezTriple *bezt,
normalize_v3(r_normal);
}
-void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3])
+void BKE_nurb_bezt_calc_plane(struct Nurb *nu, BezTriple *bezt, float r_plane[3])
{
float dir_prev[3], dir_next[3];
@@ -833,7 +832,7 @@ void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_p
normalize_v3(r_plane);
}
-void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_normal[3])
+void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, BPoint *bp, float r_normal[3])
{
BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
@@ -856,6 +855,34 @@ void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_nor
normalize_v3(r_normal);
}
+void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3])
+{
+ BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
+ BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
+
+ float dir_prev[3] = {0.0f}, dir_next[3] = {0.0f};
+
+ if (bp_prev) {
+ sub_v3_v3v3(dir_prev, bp_prev->vec, bp->vec);
+ normalize_v3(dir_prev);
+ }
+ if (bp_next) {
+ sub_v3_v3v3(dir_next, bp->vec, bp_next->vec);
+ normalize_v3(dir_next);
+ }
+ cross_v3_v3v3(r_plane, dir_prev, dir_next);
+
+ /* matches with bones more closely */
+ {
+ float dir_mid[3], tvec[3];
+ add_v3_v3v3(dir_mid, dir_prev, dir_next);
+ cross_v3_v3v3(tvec, r_plane, dir_mid);
+ copy_v3_v3(r_plane, tvec);
+ }
+
+ normalize_v3(r_plane);
+}
+
/* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */
@@ -4415,7 +4442,9 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3])
}
-void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, const float unit_scale)
+void BKE_curve_transform_ex(
+ Curve *cu, float mat[4][4],
+ const bool do_keys, const bool do_props, const float unit_scale)
{
Nurb *nu;
BPoint *bp;
@@ -4429,7 +4458,9 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, cons
mul_m4_v3(mat, bezt->vec[0]);
mul_m4_v3(mat, bezt->vec[1]);
mul_m4_v3(mat, bezt->vec[2]);
- bezt->radius *= unit_scale;
+ if (do_props) {
+ bezt->radius *= unit_scale;
+ }
}
BKE_nurb_handles_calc(nu);
}
@@ -4437,7 +4468,9 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, cons
i = nu->pntsu * nu->pntsv;
for (bp = nu->bp; i--; bp++) {
mul_m4_v3(mat, bp->vec);
- bp->radius *= unit_scale;
+ if (do_props) {
+ bp->radius *= unit_scale;
+ }
}
}
}
@@ -4453,10 +4486,12 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, cons
}
}
-void BKE_curve_transform(Curve *cu, float mat[4][4], const bool do_keys)
+void BKE_curve_transform(
+ Curve *cu, float mat[4][4],
+ const bool do_keys, const bool do_props)
{
float unit_scale = mat4_to_scale(mat);
- BKE_curve_transform_ex(cu, mat, do_keys, unit_scale);
+ BKE_curve_transform_ex(cu, mat, do_keys, do_props, unit_scale);
}
void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys)
@@ -4645,14 +4680,3 @@ void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
BKE_curve_texspace_calc(curve);
}
}
-
-void BKE_curve_eval_path(EvaluationContext *UNUSED(eval_ctx),
- Curve *curve)
-{
- /* TODO(sergey): This will probably need to be a part of
- * the modifier stack still.
- */
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, curve->id.name);
- }
-}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 13b1aab5e1c..eec8d2478da 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -76,7 +76,7 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
return defgroup;
}
-void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
+void defgroup_copy_list(ListBase *outbase, const ListBase *inbase)
{
bDeformGroup *defgroup, *defgroupn;
@@ -88,7 +88,7 @@ void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
}
}
-bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup)
+bDeformGroup *defgroup_duplicate(const bDeformGroup *ingroup)
{
bDeformGroup *outgroup;
@@ -621,8 +621,17 @@ float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
*/
float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup)
{
- if (defgroup == -1 || dvert == NULL)
+ /* Invalid defgroup index means the vgroup selected is invalid, does not exist, in that case it is OK to return 1.0
+ * (i.e. maximum weight, as if no vgroup was selected).
+ * But in case of valid defgroup and NULL dvert data pointer, it means that vgroup **is** valid,
+ * and just totally empty, so we shall return '0.0' value then!
+ */
+ if (defgroup == -1) {
return 1.0f;
+ }
+ else if (dvert == NULL) {
+ return 0.0f;
+ }
return defvert_find_weight(dvert + index, defgroup);
}
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 1db69d23607..ae896176b6d 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2060,9 +2060,6 @@ DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scen
if (pmd->canvas) {
DerivedMesh *ret;
- /* For now generate looptris in every case */
- DM_ensure_looptri(dm);
-
/* Update canvas data for a new frame */
dynamicPaint_frameUpdate(pmd, scene, ob, dm);
@@ -2072,9 +2069,6 @@ DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scen
return ret;
}
else {
- /* For now generate looptris in every case */
- DM_ensure_looptri(dm);
-
/* Update canvas data for a new frame */
dynamicPaint_frameUpdate(pmd, scene, ob, dm);
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 5591ee2a0d4..f29af28a782 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -149,6 +149,8 @@ static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm)
const float (*vertexCos)[3];
vertexCos = bmdm->vertexCos;
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
BM_face_calc_center_mean_vcos(bm, efa, polyCos[i], vertexCos);
}
@@ -487,8 +489,6 @@ static void emDM_calc_loop_tangents(
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMEditMesh *em = bmdm->em;
BMesh *bm = bmdm->em->bm;
- if (CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV) == 0)
- return;
int act_uv_n = -1;
int ren_uv_n = -1;
@@ -496,7 +496,7 @@ static void emDM_calc_loop_tangents(
bool calc_ren = false;
char act_uv_name[MAX_NAME];
char ren_uv_name[MAX_NAME];
- char tangent_mask = 0;
+ short tangent_mask = 0;
DM_calc_loop_tangents_step_0(
&bm->ldata, calc_active_tangent, tangent_names, tangent_names_count,
@@ -506,6 +506,8 @@ static void emDM_calc_loop_tangents(
for (int i = 0; i < tangent_names_count; i++)
if (tangent_names[i][0])
DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, tangent_names[i]);
+ if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1)
+ CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, "");
if (calc_act && act_uv_name[0])
DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, act_uv_name);
if (calc_ren && ren_uv_name[0])
@@ -572,7 +574,17 @@ static void emDM_calc_loop_tangents(
continue;
/* needed for orco lookups */
htype_index |= BM_VERT;
+ dm->tangent_mask |= DM_TANGENT_MASK_ORCO;
+ }
+ else {
+ /* Fill the resulting tangent_mask */
+ int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name);
+ int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
+ BLI_assert(uv_ind != -1 && uv_start != -1);
+ BLI_assert(uv_ind - uv_start < MAX_MTFACE);
+ dm->tangent_mask |= 1 << (uv_ind - uv_start);
}
+
if (mesh2tangent->precomputedFaceNormals) {
/* needed for face normal lookups */
htype_index |= BM_FACE;
@@ -582,12 +594,6 @@ static void emDM_calc_loop_tangents(
mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
mesh2tangent->tangent = dm->loopData.layers[index].data;
- /* Fill the resulting tangent_mask */
- int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name);
- int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
- BLI_assert(uv_ind != -1 && uv_start != -1);
- BLI_assert(uv_ind - uv_start < MAX_MTFACE);
- dm->tangent_mask |= 1 << (uv_ind - uv_start);
BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
}
@@ -602,15 +608,20 @@ static void emDM_calc_loop_tangents(
#undef USE_LOOPTRI_DETECT_QUADS
#endif
}
+
/* Update active layer index */
- int uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[uv_index].name);
- CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
+ int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
+ if (act_uv_index >= 0) {
+ int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
+ CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
+ } /* else tangent has been built from orco */
/* Update render layer index */
- uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
- tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[uv_index].name);
- CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
+ int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
+ if (ren_uv_index >= 0) {
+ int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
+ CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
+ } /* else tangent has been built from orco */
}
/** \} */
@@ -650,18 +661,6 @@ static void emDM_recalcLoopTri(DerivedMesh *dm)
}
}
-static const MLoopTri *emDM_getLoopTriArray(DerivedMesh *dm)
-{
- if (dm->looptris.array) {
- BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
- }
- else {
- dm->recalcLoopTri(dm);
- }
-
- return dm->looptris.array;
-}
-
static void emDM_foreachMappedVert(
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
@@ -2248,8 +2247,6 @@ DerivedMesh *getEditDerivedBMesh(
bmdm->dm.getNumLoops = emDM_getNumLoops;
bmdm->dm.getNumPolys = emDM_getNumPolys;
- bmdm->dm.getLoopTriArray = emDM_getLoopTriArray;
-
bmdm->dm.getVert = emDM_getVert;
bmdm->dm.getVertCo = emDM_getVertCo;
bmdm->dm.getVertNo = emDM_getVertNo;
@@ -2630,7 +2627,7 @@ static void statvis_calc_distort(
vertexCos[BM_elem_index_get(l_iter->next->v)]);
}
else {
- BM_loop_calc_face_normal(l_iter, no_corner);
+ BM_loop_calc_face_normal_safe(l_iter, no_corner);
}
/* simple way to detect (what is most likely) concave */
if (dot_v3v3(f_no, no_corner) < 0.0f) {
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 4eee24b378f..38f5c00941c 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -986,19 +986,19 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected
*/
void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse)
{
-/*
- * Modifies the force on a particle according to its
- * relation with the effector object
- * Different kind of effectors include:
- * Forcefields: Gravity-like attractor
- * (force power is related to the inverse of distance to the power of a falloff value)
- * Vortex fields: swirling effectors
- * (particles rotate around Z-axis of the object. otherwise, same relation as)
- * (Forcefields, but this is not done through a force/acceleration)
- * Guide: particles on a path
- * (particles are guided along a curve bezier or old nurbs)
- * (is independent of other effectors)
- */
+ /*
+ * Modifies the force on a particle according to its
+ * relation with the effector object
+ * Different kind of effectors include:
+ * Forcefields: Gravity-like attractor
+ * (force power is related to the inverse of distance to the power of a falloff value)
+ * Vortex fields: swirling effectors
+ * (particles rotate around Z-axis of the object. otherwise, same relation as)
+ * (Forcefields, but this is not done through a force/acceleration)
+ * Guide: particles on a path
+ * (particles are guided along a curve bezier or old nurbs)
+ * (is independent of other effectors)
+ */
EffectorCache *eff;
EffectorData efd;
int p=0, tot = 1, step = 1;
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 7dbc43e0a32..db6c533ab57 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -126,7 +126,7 @@ void free_fcurves(ListBase *list)
/* ---------------------- Copy --------------------------- */
/* duplicate an F-Curve */
-FCurve *copy_fcurve(FCurve *fcu)
+FCurve *copy_fcurve(const FCurve *fcu)
{
FCurve *fcu_d;
@@ -1805,7 +1805,7 @@ void fcurve_free_driver(FCurve *fcu)
}
/* This makes a copy of the given driver */
-ChannelDriver *fcurve_copy_driver(ChannelDriver *driver)
+ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver)
{
ChannelDriver *ndriver;
@@ -1945,7 +1945,7 @@ float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const fl
BLI_mutex_unlock(&python_driver_lock);
}
#else /* WITH_PYTHON*/
- (void)evaltime;
+ UNUSED_VARS(anim_rna, evaltime);
#endif /* WITH_PYTHON*/
break;
}
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 8247336d915..8e98a9f672d 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -80,8 +80,6 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex);
- DM_ensure_looptri(dm);
-
mvert = dm->getVertArray(dm);
mloop = dm->getLoopArray(dm);
looptri = dm->getLoopTriArray(dm);
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 2c301c04100..f1732ee7a9a 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -116,7 +116,7 @@ static void fcm_generator_free(FModifier *fcm)
MEM_freeN(data->coefficients);
}
-static void fcm_generator_copy(FModifier *fcm, FModifier *src)
+static void fcm_generator_copy(FModifier *fcm, const FModifier *src)
{
FMod_Generator *gen = (FMod_Generator *)fcm->data;
FMod_Generator *ogen = (FMod_Generator *)src->data;
@@ -386,7 +386,7 @@ static void fcm_envelope_free(FModifier *fcm)
MEM_freeN(env->data);
}
-static void fcm_envelope_copy(FModifier *fcm, FModifier *src)
+static void fcm_envelope_copy(FModifier *fcm, const FModifier *src)
{
FMod_Envelope *env = (FMod_Envelope *)fcm->data;
FMod_Envelope *oenv = (FMod_Envelope *)src->data;
@@ -877,7 +877,7 @@ static void fcm_python_new_data(void *mdata)
data->prop->type = IDP_GROUP;
}
-static void fcm_python_copy(FModifier *fcm, FModifier *src)
+static void fcm_python_copy(FModifier *fcm, const FModifier *src)
{
FMod_Python *pymod = (FMod_Python *)fcm->data;
FMod_Python *opymod = (FMod_Python *)src->data;
@@ -1040,7 +1040,7 @@ static void fmods_init_typeinfo(void)
/* This function should be used for getting the appropriate type-info when only
* a F-Curve modifier type is known
*/
-const FModifierTypeInfo *get_fmodifier_typeinfo(int type)
+const FModifierTypeInfo *get_fmodifier_typeinfo(const int type)
{
/* initialize the type-info list? */
if (FMI_INIT) {
@@ -1065,7 +1065,7 @@ const FModifierTypeInfo *get_fmodifier_typeinfo(int type)
/* This function should always be used to get the appropriate type-info, as it
* has checks which prevent segfaults in some weird cases.
*/
-const FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm)
+const FModifierTypeInfo *fmodifier_get_typeinfo(const FModifier *fcm)
{
/* only return typeinfo for valid modifiers */
if (fcm)
@@ -1117,7 +1117,7 @@ FModifier *add_fmodifier(ListBase *modifiers, int type)
}
/* Make a copy of the specified F-Modifier */
-FModifier *copy_fmodifier(FModifier *src)
+FModifier *copy_fmodifier(const FModifier *src)
{
const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src);
FModifier *dst;
@@ -1142,7 +1142,7 @@ FModifier *copy_fmodifier(FModifier *src)
}
/* Duplicate all of the F-Modifiers in the Modifier stacks */
-void copy_fmodifiers(ListBase *dst, ListBase *src)
+void copy_fmodifiers(ListBase *dst, const ListBase *src)
{
FModifier *fcm, *srcfcm;
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 401fed74c52..d6b28cfaf70 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -106,6 +106,23 @@ void BKE_vfont_free(struct VFont *vf)
}
}
+void BKE_vfont_copy_data(Main *UNUSED(bmain), VFont *vfont_dst, const VFont *UNUSED(vfont_src), const int flag)
+{
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+
+ /* Just to be sure, should not have any value actually after reading time. */
+ vfont_dst->temp_pf = NULL;
+
+ if (vfont_dst->packedfile) {
+ vfont_dst->packedfile = dupPackedFile(vfont_dst->packedfile);
+ }
+
+ if (vfont_dst->data) {
+ vfont_dst->data = BLI_vfontdata_copy(vfont_dst->data, flag_subdata);
+ }
+}
+
static void *builtin_font_data = NULL;
static int builtin_font_size = 0;
@@ -249,7 +266,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath)
vfd = BLI_vfontdata_from_freetypefont(pf);
if (vfd) {
- vfont = BKE_libblock_alloc(bmain, ID_VF, filename);
+ vfont = BKE_libblock_alloc(bmain, ID_VF, filename, 0);
vfont->data = vfd;
/* if there's a font name, use it for the ID name */
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 0a0b023df82..e45a938a4fc 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -44,7 +44,7 @@
// function declarations
static FreestyleLineSet *alloc_lineset(void);
-static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset);
+static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag);
static FreestyleModuleConfig *alloc_module(void);
static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module);
@@ -79,7 +79,7 @@ void BKE_freestyle_config_free(FreestyleConfig *config)
BLI_freelistN(&config->modules);
}
-void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config)
+void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag)
{
FreestyleLineSet *lineset, *new_lineset;
FreestyleModuleConfig *module, *new_module;
@@ -93,7 +93,7 @@ void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *con
BLI_listbase_clear(&new_config->linesets);
for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
new_lineset = alloc_lineset();
- copy_lineset(new_lineset, lineset);
+ copy_lineset(new_lineset, lineset, flag);
BLI_addtail(&new_config->linesets, (void *)new_lineset);
}
@@ -105,11 +105,9 @@ void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *con
}
}
-static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset)
+static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag)
{
new_lineset->linestyle = lineset->linestyle;
- if (new_lineset->linestyle)
- id_us_plus(&new_lineset->linestyle->id);
new_lineset->flags = lineset->flags;
new_lineset->selection = lineset->selection;
new_lineset->qi = lineset->qi;
@@ -118,10 +116,12 @@ static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *linese
new_lineset->edge_types = lineset->edge_types;
new_lineset->exclude_edge_types = lineset->exclude_edge_types;
new_lineset->group = lineset->group;
- if (new_lineset->group) {
- id_us_plus(&new_lineset->group->id);
- }
strcpy(new_lineset->name, lineset->name);
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)new_lineset->linestyle);
+ id_us_plus((ID *)new_lineset->group);
+ }
}
static FreestyleModuleConfig *alloc_module(void)
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 30fc8915d46..ee0d0b41898 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -627,7 +627,7 @@ bGPdata *BKE_gpencil_data_addnew(const char name[])
bGPdata *gpd;
/* allocate memory for a new block */
- gpd = BKE_libblock_alloc(G.main, ID_GD, name);
+ gpd = BKE_libblock_alloc(G.main, ID_GD, name, 0);
/* initial settings */
gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
@@ -753,47 +753,62 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
return gpl_dst;
}
-/* make a copy of a given gpencil datablock */
-bGPdata *BKE_gpencil_data_duplicate(Main *bmain, bGPdata *gpd_src, bool internal_copy)
+/**
+ * Only copy internal data of GreasePencil ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_gpencil_copy_data(Main *UNUSED(bmain), bGPdata *gpd_dst, const bGPdata *gpd_src, const int UNUSED(flag))
{
- const bGPDlayer *gpl_src;
- bGPDlayer *gpl_dst;
- bGPdata *gpd_dst;
+ /* copy layers */
+ BLI_listbase_clear(&gpd_dst->layers);
+ for (const bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
+ /* make a copy of source layer and its data */
+ bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); /* TODO here too could add unused flags... */
+ BLI_addtail(&gpd_dst->layers, gpl_dst);
+ }
- /* error checking */
- if (gpd_src == NULL) {
- return NULL;
+ /* copy palettes */
+ BLI_listbase_clear(&gpd_dst->palettes);
+ for (const bGPDpalette *palette_src = gpd_src->palettes.first; palette_src; palette_src = palette_src->next) {
+ bGPDpalette *palette_dst = BKE_gpencil_palette_duplicate(palette_src); /* TODO here too could add unused flags... */
+ BLI_addtail(&gpd_dst->palettes, palette_dst);
}
-
- /* make a copy of the base-data */
+}
+
+/* make a copy of a given gpencil datablock */
+bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
+{
+ /* Yuck and super-uber-hyper yuck!!!
+ * Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it,
+ * so for now keep old code for that one. */
if (internal_copy) {
+ const bGPDlayer *gpl_src;
+ bGPDlayer *gpl_dst;
+ bGPdata *gpd_dst;
+
/* make a straight copy for undo buffers used during stroke drawing */
gpd_dst = MEM_dupallocN(gpd_src);
+
+ /* copy layers */
+ 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 = BKE_gpencil_layer_duplicate(gpl_src);
+ BLI_addtail(&gpd_dst->layers, gpl_dst);
+ }
+
+ /* return new */
+ return gpd_dst;
}
else {
- /* make a copy when others use this */
- gpd_dst = BKE_libblock_copy(bmain, &gpd_src->id);
+ bGPdata *gpd_copy;
+ BKE_id_copy_ex(bmain, &gpd_src->id, (ID **)&gpd_copy, 0, false);
+ return gpd_copy;
}
-
- /* copy layers */
- 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 = BKE_gpencil_layer_duplicate(gpl_src);
- BLI_addtail(&gpd_dst->layers, gpl_dst);
- }
- if (!internal_copy) {
- /* copy palettes */
- 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 = BKE_gpencil_palette_duplicate(palette_src);
- BLI_addtail(&gpd_dst->palettes, palette_dst);
- }
- }
-
- /* return new */
- return gpd_dst;
}
void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 9b011dbb003..fd6e9681e64 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -79,7 +79,9 @@ Group *BKE_group_add(Main *bmain, const char *name)
{
Group *group;
- group = BKE_libblock_alloc(bmain, ID_GR, name);
+ group = BKE_libblock_alloc(bmain, ID_GR, name, 0);
+ id_us_min(&group->id);
+ id_us_ensure_real(&group->id);
group->layer = (1 << 20) - 1;
group->preview = NULL;
@@ -87,19 +89,32 @@ Group *BKE_group_add(Main *bmain, const char *name)
return group;
}
-Group *BKE_group_copy(Main *bmain, Group *group)
+/**
+ * Only copy internal data of Group ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *group_src, const int flag)
{
- Group *groupn;
-
- groupn = BKE_libblock_copy(bmain, &group->id);
- BLI_duplicatelist(&groupn->gobject, &group->gobject);
+ BLI_duplicatelist(&group_dst->gobject, &group_src->gobject);
/* Do not copy group's preview (same behavior as for objects). */
- groupn->preview = NULL;
-
- BKE_id_copy_ensure_local(bmain, &group->id, &groupn->id);
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
+ BKE_previewimg_id_copy(&group_dst->id, &group_src->id);
+ }
+ else {
+ group_dst->preview = NULL;
+ }
+}
- return groupn;
+Group *BKE_group_copy(Main *bmain, const Group *group)
+{
+ Group *group_copy;
+ BKE_id_copy_ex(bmain, &group->id, (ID **)&group_copy, 0, false);
+ return group_copy;
}
void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local)
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 7669c4ba112..a98a1b13402 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -204,7 +204,7 @@ void BKE_previewimg_clear(struct PreviewImage *prv)
}
}
-PreviewImage *BKE_previewimg_copy(PreviewImage *prv)
+PreviewImage *BKE_previewimg_copy(const PreviewImage *prv)
{
PreviewImage *prv_img = NULL;
int i;
@@ -222,7 +222,7 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv)
}
/** Duplicate preview image from \a id and clear icon_id, to be used by datablock copy functions. */
-void BKE_previewimg_id_copy(ID *new_id, ID *old_id)
+void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
{
PreviewImage **old_prv_p = BKE_previewimg_id_get_p(old_id);
PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id);
@@ -239,7 +239,7 @@ void BKE_previewimg_id_copy(ID *new_id, ID *old_id)
}
}
-PreviewImage **BKE_previewimg_id_get_p(ID *id)
+PreviewImage **BKE_previewimg_id_get_p(const ID *id)
{
switch (GS(id->name)) {
#define ID_PRV_CASE(id_code, id_struct) case id_code: { return &((id_struct *)id)->preview; } ((void)0)
@@ -253,6 +253,8 @@ PreviewImage **BKE_previewimg_id_get_p(ID *id)
ID_PRV_CASE(ID_GR, Group);
ID_PRV_CASE(ID_SCE, Scene);
#undef ID_PRV_CASE
+ default:
+ break;
}
return NULL;
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index e98181be444..45b41fa01ed 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -90,7 +90,7 @@ IDProperty *IDP_NewIDPArray(const char *name)
return prop;
}
-IDProperty *IDP_CopyIDPArray(const IDProperty *array)
+IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag)
{
/* don't use MEM_dupallocN because this may be part of an array */
IDProperty *narray, *tmp;
@@ -109,7 +109,7 @@ IDProperty *IDP_CopyIDPArray(const IDProperty *array)
* then free it. this makes for more maintainable
* code than simply reimplementing the copy functions
* in this loop.*/
- tmp = IDP_CopyProperty(GETPROP(narray, i));
+ tmp = IDP_CopyProperty_ex(GETPROP(narray, i), flag);
memcpy(GETPROP(narray, i), tmp, sizeof(IDProperty));
MEM_freeN(tmp);
}
@@ -285,9 +285,9 @@ void IDP_FreeArray(IDProperty *prop)
}
-static IDProperty *idp_generic_copy(const IDProperty *prop)
+static IDProperty *idp_generic_copy(const IDProperty *prop, const int UNUSED(flag))
{
- IDProperty *newp = MEM_callocN(sizeof(IDProperty), "IDProperty array dup");
+ IDProperty *newp = MEM_callocN(sizeof(IDProperty), __func__);
BLI_strncpy(newp->name, prop->name, MAX_IDPROP_NAME);
newp->type = prop->type;
@@ -298,9 +298,9 @@ static IDProperty *idp_generic_copy(const IDProperty *prop)
return newp;
}
-static IDProperty *IDP_CopyArray(const IDProperty *prop)
+static IDProperty *IDP_CopyArray(const IDProperty *prop, const int flag)
{
- IDProperty *newp = idp_generic_copy(prop);
+ IDProperty *newp = idp_generic_copy(prop, flag);
if (prop->data.pointer) {
newp->data.pointer = MEM_dupallocN(prop->data.pointer);
@@ -310,7 +310,7 @@ static IDProperty *IDP_CopyArray(const IDProperty *prop)
int a;
for (a = 0; a < prop->len; a++)
- array[a] = IDP_CopyProperty(array[a]);
+ array[a] = IDP_CopyProperty_ex(array[a], flag);
}
}
newp->len = prop->len;
@@ -363,12 +363,12 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
return prop;
}
-static IDProperty *IDP_CopyString(const IDProperty *prop)
+static IDProperty *IDP_CopyString(const IDProperty *prop, const int flag)
{
IDProperty *newp;
BLI_assert(prop->type == IDP_STRING);
- newp = idp_generic_copy(prop);
+ newp = idp_generic_copy(prop, flag);
if (prop->data.pointer)
newp->data.pointer = MEM_dupallocN(prop->data.pointer);
@@ -442,15 +442,17 @@ void IDP_FreeString(IDProperty *prop)
/** \name IDProperty ID API
* \{ */
-static IDProperty *IDP_CopyID(const IDProperty *prop)
+static IDProperty *IDP_CopyID(const IDProperty *prop, const int flag)
{
IDProperty *newp;
BLI_assert(prop->type == IDP_ID);
- newp = idp_generic_copy(prop);
+ newp = idp_generic_copy(prop, flag);
newp->data.pointer = prop->data.pointer;
- id_us_plus(IDP_Id(newp));
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus(IDP_Id(newp));
+ }
return newp;
}
@@ -467,16 +469,16 @@ static IDProperty *IDP_CopyID(const IDProperty *prop)
/**
* Checks if a property with the same name as prop exists, and if so replaces it.
*/
-static IDProperty *IDP_CopyGroup(const IDProperty *prop)
+static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag)
{
IDProperty *newp, *link;
BLI_assert(prop->type == IDP_GROUP);
- newp = idp_generic_copy(prop);
+ newp = idp_generic_copy(prop, flag);
newp->len = prop->len;
for (link = prop->data.group.first; link; link = link->next) {
- BLI_addtail(&newp->data.group, IDP_CopyProperty(link));
+ BLI_addtail(&newp->data.group, IDP_CopyProperty_ex(link, flag));
}
return newp;
@@ -730,18 +732,23 @@ static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user)
/** \name IDProperty Main API
* \{ */
-IDProperty *IDP_CopyProperty(const IDProperty *prop)
+IDProperty *IDP_CopyProperty_ex(const IDProperty *prop, const int flag)
{
switch (prop->type) {
- case IDP_GROUP: return IDP_CopyGroup(prop);
- case IDP_STRING: return IDP_CopyString(prop);
- case IDP_ID: return IDP_CopyID(prop);
- case IDP_ARRAY: return IDP_CopyArray(prop);
- case IDP_IDPARRAY: return IDP_CopyIDPArray(prop);
- default: return idp_generic_copy(prop);
+ case IDP_GROUP: return IDP_CopyGroup(prop, flag);
+ case IDP_STRING: return IDP_CopyString(prop, flag);
+ case IDP_ID: return IDP_CopyID(prop, flag);
+ case IDP_ARRAY: return IDP_CopyArray(prop, flag);
+ case IDP_IDPARRAY: return IDP_CopyIDPArray(prop, flag);
+ default: return idp_generic_copy(prop, flag);
}
}
+IDProperty *IDP_CopyProperty(const IDProperty *prop)
+{
+ return IDP_CopyProperty_ex(prop, 0);
+}
+
/* Updates ID pointers after an object has been copied */
/* TODO Nuke this once its only user has been correctly converted to use generic ID management from BKE_library! */
void IDP_RelinkProperty(struct IDProperty *prop)
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 026e8aea74f..902076c2d14 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -62,6 +62,7 @@
#include "BLI_blenlib.h"
#include "BLI_math_vector.h"
+#include "BLI_mempool.h"
#include "BLI_threads.h"
#include "BLI_timecode.h" /* for stamp timecode format */
#include "BLI_utildefines.h"
@@ -302,8 +303,11 @@ static void image_free_anims(Image *ima)
* Simply free the image data from memory,
* on display the image can load again (except for render buffers).
*/
-void BKE_image_free_buffers(Image *ima)
+void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
{
+ if (do_lock) {
+ BLI_spin_lock(&image_spin);
+ }
image_free_cached_frames(ima);
image_free_anims(ima);
@@ -322,6 +326,15 @@ void BKE_image_free_buffers(Image *ima)
}
ima->ok = IMA_OK;
+
+ if (do_lock) {
+ BLI_spin_unlock(&image_spin);
+ }
+}
+
+void BKE_image_free_buffers(Image *ima)
+{
+ BKE_image_free_buffers_ex(ima, false);
}
/** Free (or release) any data used by this image (does not free the image itself). */
@@ -381,7 +394,7 @@ static Image *image_alloc(Main *bmain, const char *name, short source, short typ
{
Image *ima;
- ima = BKE_libblock_alloc(bmain, ID_IM, name);
+ ima = BKE_libblock_alloc(bmain, ID_IM, name, 0);
if (ima) {
image_init(ima, source, type);
}
@@ -432,39 +445,53 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
}
}
-/* empty image block, of similar type and filename */
-Image *BKE_image_copy(Main *bmain, Image *ima)
+/**
+ * Only copy internal data of Image ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_image_copy_data(Main *UNUSED(bmain), Image *ima_dst, const Image *ima_src, const int flag)
{
- Image *nima = image_alloc(bmain, ima->id.name + 2, ima->source, ima->type);
-
- BLI_strncpy(nima->name, ima->name, sizeof(ima->name));
-
- nima->flag = ima->flag;
- nima->tpageflag = ima->tpageflag;
-
- nima->gen_x = ima->gen_x;
- nima->gen_y = ima->gen_y;
- nima->gen_type = ima->gen_type;
- copy_v4_v4(nima->gen_color, ima->gen_color);
+ BKE_color_managed_colorspace_settings_copy(&ima_dst->colorspace_settings, &ima_src->colorspace_settings);
- nima->animspeed = ima->animspeed;
+ copy_image_packedfiles(&ima_dst->packedfiles, &ima_src->packedfiles);
- nima->aspx = ima->aspx;
- nima->aspy = ima->aspy;
+ ima_dst->stereo3d_format = MEM_dupallocN(ima_src->stereo3d_format);
+ BLI_duplicatelist(&ima_dst->views, &ima_src->views);
- BKE_color_managed_colorspace_settings_copy(&nima->colorspace_settings, &ima->colorspace_settings);
-
- copy_image_packedfiles(&nima->packedfiles, &ima->packedfiles);
+ /* Cleanup stuff that cannot be copied. */
+ ima_dst->cache = NULL;
+ ima_dst->rr = NULL;
+ for (int i = 0; i < IMA_MAX_RENDER_SLOT; i++) {
+ ima_dst->renders[i] = NULL;
+ }
- /* nima->stere3d_format is already allocated by image_alloc... */
- *nima->stereo3d_format = *ima->stereo3d_format;
- BLI_duplicatelist(&nima->views, &ima->views);
+ BLI_listbase_clear(&ima_dst->anims);
- BKE_previewimg_id_copy(&nima->id, &ima->id);
+ ima_dst->totbind = 0;
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ ima_dst->bindcode[i] = 0;
+ ima_dst->gputexture[i] = NULL;
+ }
+ ima_dst->repbind = NULL;
- BKE_id_copy_ensure_local(bmain, &ima->id, &nima->id);
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
+ BKE_previewimg_id_copy(&ima_dst->id, &ima_src->id);
+ }
+ else {
+ ima_dst->preview = NULL;
+ }
+}
- return nima;
+/* empty image block, of similar type and filename */
+Image *BKE_image_copy(Main *bmain, const Image *ima)
+{
+ Image *ima_copy;
+ BKE_id_copy_ex(bmain, &ima->id, (ID **)&ima_copy, 0, false);
+ return ima_copy;
}
void BKE_image_make_local(Main *bmain, Image *ima, const bool lib_local)
@@ -2862,7 +2889,7 @@ bool BKE_image_is_stereo(Image *ima)
{
return BKE_image_is_multiview(ima) &&
(BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) &&
- BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)));
+ BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)));
}
static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
@@ -4132,33 +4159,32 @@ typedef struct ImagePoolEntry {
typedef struct ImagePool {
ListBase image_buffers;
+ BLI_mempool *memory_pool;
} ImagePool;
ImagePool *BKE_image_pool_new(void)
{
ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
+ pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolEntry), 0, 128, BLI_MEMPOOL_NOP);
return pool;
}
void BKE_image_pool_free(ImagePool *pool)
{
- ImagePoolEntry *entry, *next_entry;
-
- /* use single lock to dereference all the image buffers */
+ /* Use single lock to dereference all the image buffers. */
BLI_spin_lock(&image_spin);
-
- for (entry = pool->image_buffers.first; entry; entry = next_entry) {
- next_entry = entry->next;
-
- if (entry->ibuf)
+ for (ImagePoolEntry *entry = pool->image_buffers.first;
+ entry != NULL;
+ entry = entry->next)
+ {
+ if (entry->ibuf) {
IMB_freeImBuf(entry->ibuf);
-
- MEM_freeN(entry);
+ }
}
-
BLI_spin_unlock(&image_spin);
+ BLI_mempool_destroy(pool->memory_pool);
MEM_freeN(pool);
}
@@ -4210,7 +4236,7 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
ibuf = image_acquire_ibuf(ima, iuser, NULL);
- entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry");
+ entry = BLI_mempool_alloc(pool->memory_pool);
entry->image = ima;
entry->frame = frame;
entry->index = index;
diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index 2c8399adece..1f1f4c9d341 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -132,7 +132,7 @@ static void image_buf_fill_checker_slice(unsigned char *rect,
float hsv[3] = {0.0f, 0.9f, 0.9f};
float rgb[3];
- float dark_linear_color, bright_linear_color;
+ float dark_linear_color = 0.0f, bright_linear_color = 0.0f;
if (rect_float != NULL) {
dark_linear_color = srgb_to_linearrgb(0.25f);
bright_linear_color = srgb_to_linearrgb(0.58f);
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 8a7c1dd2833..fd42556067e 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -107,7 +107,7 @@ Key *BKE_key_add(ID *id) /* common function */
Key *key;
char *el;
- key = BKE_libblock_alloc(G.main, ID_KE, "Key");
+ key = BKE_libblock_alloc(G.main, ID_KE, "Key", 0);
key->type = KEY_NORMAL;
key->from = id;
@@ -146,36 +146,48 @@ Key *BKE_key_add(ID *id) /* common function */
key->elemsize = 16;
break;
+
+ default:
+ break;
}
return key;
}
-Key *BKE_key_copy(Main *bmain, Key *key)
+/**
+ * Only copy internal data of ShapeKey ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_key_copy_data(Main *UNUSED(bmain), Key *key_dst, const Key *key_src, const int UNUSED(flag))
{
- Key *keyn;
- KeyBlock *kbn, *kb;
-
- keyn = BKE_libblock_copy(bmain, &key->id);
-
- BLI_duplicatelist(&keyn->block, &key->block);
-
- kb = key->block.first;
- kbn = keyn->block.first;
- while (kbn) {
-
- if (kbn->data) kbn->data = MEM_dupallocN(kbn->data);
- if (kb == key->refkey) keyn->refkey = kbn;
-
- kbn = kbn->next;
- kb = kb->next;
- }
+ BLI_duplicatelist(&key_dst->block, &key_src->block);
- BKE_id_copy_ensure_local(bmain, &key->id, &keyn->id);
+ KeyBlock *kb_dst, *kb_src;
+ for (kb_src = key_src->block.first, kb_dst = key_dst->block.first;
+ kb_dst;
+ kb_src = kb_src->next, kb_dst = kb_dst->next)
+ {
+ if (kb_dst->data) {
+ kb_dst->data = MEM_dupallocN(kb_dst->data);
+ }
+ if (kb_src == key_src->refkey) {
+ key_dst->refkey = kb_dst;
+ }
+ }
+}
- return keyn;
+Key *BKE_key_copy(Main *bmain, const Key *key)
+{
+ Key *key_copy;
+ BKE_id_copy_ex(bmain, &key->id, (ID **)&key_copy, 0, false);
+ return key_copy;
}
+/* XXX TODO get rid of this! */
Key *BKE_key_copy_nolib(Key *key)
{
Key *keyn;
@@ -1397,6 +1409,8 @@ Key **BKE_key_from_id_p(ID *id)
Lattice *lt = (Lattice *)id;
return &lt->key;
}
+ default:
+ break;
}
return NULL;
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 69a2067f4e6..e8ef346927e 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -109,42 +109,60 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name)
{
Lamp *la;
- la = BKE_libblock_alloc(bmain, ID_LA, name);
+ la = BKE_libblock_alloc(bmain, ID_LA, name, 0);
BKE_lamp_init(la);
return la;
}
-Lamp *BKE_lamp_copy(Main *bmain, Lamp *la)
+/**
+ * Only copy internal data of Lamp ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_lamp_copy_data(Main *bmain, Lamp *la_dst, const Lamp *la_src, const int flag)
{
- Lamp *lan;
- int a;
-
- lan = BKE_libblock_copy(bmain, &la->id);
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (lan->mtex[a]) {
- lan->mtex[a] = MEM_mallocN(sizeof(MTex), "copylamptex");
- memcpy(lan->mtex[a], la->mtex[a], sizeof(MTex));
- id_us_plus((ID *)lan->mtex[a]->tex);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (la_dst->mtex[a]) {
+ la_dst->mtex[a] = MEM_mallocN(sizeof(*la_dst->mtex[a]), __func__);
+ *la_dst->mtex[a] = *la_src->mtex[a];
}
}
-
- lan->curfalloff = curvemapping_copy(la->curfalloff);
- if (la->nodetree)
- lan->nodetree = ntreeCopyTree(bmain, la->nodetree);
+ la_dst->curfalloff = curvemapping_copy(la_src->curfalloff);
- BKE_previewimg_id_copy(&lan->id, &la->id);
+ if (la_src->nodetree) {
+ BKE_id_copy_ex(bmain, (ID *)la_src->nodetree, (ID **)&la_dst->nodetree, flag, false);
+ }
- BKE_id_copy_ensure_local(bmain, &la->id, &lan->id);
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
+ BKE_previewimg_id_copy(&la_dst->id, &la_src->id);
+ }
+ else {
+ la_dst->preview = NULL;
+ }
+}
- return lan;
+Lamp *BKE_lamp_copy(Main *bmain, const Lamp *la)
+{
+ Lamp *la_copy;
+ BKE_id_copy_ex(bmain, &la->id, (ID **)&la_copy, 0, false);
+ return la_copy;
}
Lamp *localize_lamp(Lamp *la)
{
+ /* TODO replace with something like
+ * Lamp *la_copy;
+ * BKE_id_copy_ex(bmain, &la->id, (ID **)&la_copy, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT, false);
+ * return la_copy;
+ *
+ * ... Once f*** nodes are fully converted to that too :( */
+
Lamp *lan;
int a;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 54cfae620a1..ea4c3f380ff 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -270,39 +270,46 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name)
{
Lattice *lt;
- lt = BKE_libblock_alloc(bmain, ID_LT, name);
+ lt = BKE_libblock_alloc(bmain, ID_LT, name, 0);
BKE_lattice_init(lt);
return lt;
}
-Lattice *BKE_lattice_copy(Main *bmain, Lattice *lt)
+/**
+ * Only copy internal data of Lattice ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_lattice_copy_data(Main *bmain, Lattice *lt_dst, const Lattice *lt_src, const int flag)
{
- Lattice *ltn;
+ lt_dst->def = MEM_dupallocN(lt_src->def);
- ltn = BKE_libblock_copy(bmain, &lt->id);
- ltn->def = MEM_dupallocN(lt->def);
-
- if (lt->key) {
- ltn->key = BKE_key_copy(bmain, ltn->key);
- ltn->key->from = (ID *)ltn;
- }
-
- if (lt->dvert) {
- int tot = lt->pntsu * lt->pntsv * lt->pntsw;
- ltn->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
- BKE_defvert_array_copy(ltn->dvert, lt->dvert, tot);
+ if (lt_src->key) {
+ BKE_id_copy_ex(bmain, &lt_src->key->id, (ID **)&lt_dst->key, flag, false);
}
- ltn->editlatt = NULL;
+ if (lt_src->dvert) {
+ int tot = lt_src->pntsu * lt_src->pntsv * lt_src->pntsw;
+ lt_dst->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
+ BKE_defvert_array_copy(lt_dst->dvert, lt_src->dvert, tot);
+ }
- BKE_id_copy_ensure_local(bmain, &lt->id, &ltn->id);
+ lt_dst->editlatt = NULL;
+}
- return ltn;
+Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt)
+{
+ Lattice *lt_copy;
+ BKE_id_copy_ex(bmain, &lt->id, (ID **)&lt_copy, 0, false);
+ return lt_copy;
}
-/** Free (or release) any data used by this lattice (does not free the lattice itself). */
+ /** Free (or release) any data used by this lattice (does not free the lattice itself). */
void BKE_lattice_free(Lattice *lt)
{
BKE_animdata_free(&lt->id, false);
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index c249577686e..d5dfc63b317 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -307,7 +307,7 @@ void BKE_id_expand_local(Main *bmain, ID *id)
/**
* Ensure new (copied) ID is fully made local.
*/
-void BKE_id_copy_ensure_local(Main *bmain, ID *old_id, ID *new_id)
+void BKE_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id)
{
if (ID_IS_LINKED_DATABLOCK(old_id)) {
BKE_id_expand_local(bmain, new_id);
@@ -383,7 +383,6 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
switch ((ID_Type)GS(id->name)) {
case ID_SCE:
- /* Partially implemented (has no copy...). */
if (!test) BKE_scene_make_local(bmain, (Scene *)id, lib_local);
return true;
case ID_OB:
@@ -423,14 +422,12 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
if (!test) BKE_world_make_local(bmain, (World *)id, lib_local);
return true;
case ID_VF:
- /* Partially implemented (has no copy...). */
if (!test) BKE_vfont_make_local(bmain, (VFont *)id, lib_local);
return true;
case ID_TXT:
if (!test) BKE_text_make_local(bmain, (Text *)id, lib_local);
return true;
case ID_SO:
- /* Partially implemented (has no copy...). */
if (!test) BKE_sound_make_local(bmain, (bSound *)id, lib_local);
return true;
case ID_GR:
@@ -484,114 +481,189 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
return false;
}
+struct IDCopyLibManagementData {
+ const ID *id_src;
+ ID *id_dst;
+ int flag;
+};
+
+/* Increases usercount as required, and remap self ID pointers. */
+static int id_copy_libmanagement_cb(void *user_data, ID *UNUSED(id_self), ID **id_pointer, int cb_flag)
+{
+ struct IDCopyLibManagementData *data = user_data;
+ ID *id = *id_pointer;
+
+ /* Remap self-references to new copied ID. */
+ if (id == data->id_src) {
+ /* We cannot use id_self here, it is not *always* id_dst (thanks to $£!+@#&/? nodetrees). */
+ id = *id_pointer = data->id_dst;
+ }
+
+ /* Increase used IDs refcount if needed and required. */
+ if ((data->flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && (cb_flag & IDWALK_CB_USER)) {
+ id_us_plus(id);
+ }
+
+ return IDWALK_RET_NOP;
+}
+
/**
- * Invokes the appropriate copy method for the block and returns the result in
- * newid, unless test. Returns true if the block can be copied.
+ * Generic entry point for copying a datablock (new API).
+ *
+ * \note Copy is only affecting given data-block (no ID used by copied one will be affected, besides usercount).
+ * There is only one exception, if LIB_ID_COPY_ACTIONS is defined, actions used by animdata will be duplicated.
+ *
+ * \note Usercount of new copy is always set to 1.
+ *
+ * \param bmain Main database, may be NULL only if LIB_ID_COPY_NO_MAIN is specified.
+ * \param id Source datablock.
+ * \param r_newid Pointer to new (copied) ID pointer.
+ * \param flag Set of copy options, see DNA_ID.h enum for details (leave to zero for default, full copy).
+ * \param test If set, do not do any copy, just test whether copy is supported.
+ * \return False when copying that ID type is not supported, true otherwise.
*/
-bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
+/* XXX TODO remove test thing, *all* IDs should be copyable that way! */
+bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, const bool test)
{
- if (!test) {
- *newid = NULL;
+#define LIB_ID_TYPES_NOCOPY ID_LI, ID_SCR, ID_WM, /* Not supported */ \
+ ID_IP /* Deprecated */
+
+ BLI_assert(test || (r_newid != NULL));
+ if (r_newid != NULL) {
+ *r_newid = NULL;
+ }
+ if (id == NULL) {
+ return false;
}
- /* conventions:
- * - make shallow copy, only this ID block
- * - id.us of the new ID is set to 1 */
+ if (ELEM(GS(id->name), LIB_ID_TYPES_NOCOPY)) {
+ return false;
+ }
+ else if (test) {
+ return true;
+ }
+
+ BKE_libblock_copy_ex(bmain, id, r_newid, flag);
+
switch ((ID_Type)GS(id->name)) {
+ case ID_SCE:
+ BKE_scene_copy_data(bmain, (Scene *)*r_newid, (Scene *)id, flag);
+ break;
case ID_OB:
- if (!test) *newid = (ID *)BKE_object_copy(bmain, (Object *)id);
- return true;
+ BKE_object_copy_data(bmain, (Object *)*r_newid, (Object *)id, flag);
+ break;
case ID_ME:
- if (!test) *newid = (ID *)BKE_mesh_copy(bmain, (Mesh *)id);
- return true;
+ BKE_mesh_copy_data(bmain, (Mesh *)*r_newid, (Mesh *)id, flag);
+ break;
case ID_CU:
- if (!test) *newid = (ID *)BKE_curve_copy(bmain, (Curve *)id);
- return true;
+ BKE_curve_copy_data(bmain, (Curve *)*r_newid, (Curve *)id, flag);
+ break;
case ID_MB:
- if (!test) *newid = (ID *)BKE_mball_copy(bmain, (MetaBall *)id);
- return true;
+ BKE_mball_copy_data(bmain, (MetaBall *)*r_newid, (MetaBall *)id, flag);
+ break;
case ID_MA:
- if (!test) *newid = (ID *)BKE_material_copy(bmain, (Material *)id);
- return true;
+ BKE_material_copy_data(bmain, (Material *)*r_newid, (Material *)id, flag);
+ break;
case ID_TE:
- if (!test) *newid = (ID *)BKE_texture_copy(bmain, (Tex *)id);
- return true;
+ BKE_texture_copy_data(bmain, (Tex *)*r_newid, (Tex *)id, flag);
+ break;
case ID_IM:
- if (!test) *newid = (ID *)BKE_image_copy(bmain, (Image *)id);
- return true;
+ BKE_image_copy_data(bmain, (Image *)*r_newid, (Image *)id, flag);
+ break;
case ID_LT:
- if (!test) *newid = (ID *)BKE_lattice_copy(bmain, (Lattice *)id);
- return true;
+ BKE_lattice_copy_data(bmain, (Lattice *)*r_newid, (Lattice *)id, flag);
+ break;
case ID_LA:
- if (!test) *newid = (ID *)BKE_lamp_copy(bmain, (Lamp *)id);
- return true;
+ BKE_lamp_copy_data(bmain, (Lamp *)*r_newid, (Lamp *)id, flag);
+ break;
case ID_SPK:
- if (!test) *newid = (ID *)BKE_speaker_copy(bmain, (Speaker *)id);
- return true;
+ BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag);
+ break;
case ID_CA:
- if (!test) *newid = (ID *)BKE_camera_copy(bmain, (Camera *)id);
- return true;
+ BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag);
+ break;
case ID_KE:
- if (!test) *newid = (ID *)BKE_key_copy(bmain, (Key *)id);
- return true;
+ BKE_key_copy_data(bmain, (Key *)*r_newid, (Key *)id, flag);
+ break;
case ID_WO:
- if (!test) *newid = (ID *)BKE_world_copy(bmain, (World *)id);
- return true;
+ BKE_world_copy_data(bmain, (World *)*r_newid, (World *)id, flag);
+ break;
case ID_TXT:
- if (!test) *newid = (ID *)BKE_text_copy(bmain, (Text *)id);
- return true;
+ BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag);
+ break;
case ID_GR:
- if (!test) *newid = (ID *)BKE_group_copy(bmain, (Group *)id);
- return true;
+ BKE_group_copy_data(bmain, (Group *)*r_newid, (Group *)id, flag);
+ break;
case ID_AR:
- if (!test) *newid = (ID *)BKE_armature_copy(bmain, (bArmature *)id);
- return true;
+ BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag);
+ break;
case ID_AC:
- if (!test) *newid = (ID *)BKE_action_copy(bmain, (bAction *)id);
- return true;
+ BKE_action_copy_data(bmain, (bAction *)*r_newid, (bAction *)id, flag);
+ break;
case ID_NT:
- if (!test) *newid = (ID *)ntreeCopyTree(bmain, (bNodeTree *)id);
- return true;
+ BKE_node_tree_copy_data(bmain, (bNodeTree *)*r_newid, (bNodeTree *)id, flag);
+ break;
case ID_BR:
- if (!test) *newid = (ID *)BKE_brush_copy(bmain, (Brush *)id);
- return true;
+ BKE_brush_copy_data(bmain, (Brush *)*r_newid, (Brush *)id, flag);
+ break;
case ID_PA:
- if (!test) *newid = (ID *)BKE_particlesettings_copy(bmain, (ParticleSettings *)id);
- return true;
+ BKE_particlesettings_copy_data(bmain, (ParticleSettings *)*r_newid, (ParticleSettings *)id, flag);
+ break;
case ID_GD:
- if (!test) *newid = (ID *)BKE_gpencil_data_duplicate(bmain, (bGPdata *)id, false);
- return true;
+ BKE_gpencil_copy_data(bmain, (bGPdata *)*r_newid, (bGPdata *)id, flag);
+ break;
case ID_MC:
- if (!test) *newid = (ID *)BKE_movieclip_copy(bmain, (MovieClip *)id);
- return true;
+ BKE_movieclip_copy_data(bmain, (MovieClip *)*r_newid, (MovieClip *)id, flag);
+ break;
case ID_MSK:
- if (!test) *newid = (ID *)BKE_mask_copy(bmain, (Mask *)id);
- return true;
+ BKE_mask_copy_data(bmain, (Mask *)*r_newid, (Mask *)id, flag);
+ break;
case ID_LS:
- if (!test) *newid = (ID *)BKE_linestyle_copy(bmain, (FreestyleLineStyle *)id);
- return true;
+ BKE_linestyle_copy_data(bmain, (FreestyleLineStyle *)*r_newid, (FreestyleLineStyle *)id, flag);
+ break;
case ID_PAL:
- if (!test) *newid = (ID *)BKE_palette_copy(bmain, (Palette *)id);
- return true;
+ BKE_palette_copy_data(bmain, (Palette *)*r_newid, (Palette *)id, flag);
+ break;
case ID_PC:
- if (!test) *newid = (ID *)BKE_paint_curve_copy(bmain, (PaintCurve *)id);
- return true;
+ BKE_paint_curve_copy_data(bmain, (PaintCurve *)*r_newid, (PaintCurve *)id, flag);
+ break;
case ID_CF:
- if (!test) *newid = (ID *)BKE_cachefile_copy(bmain, (CacheFile *)id);
- return true;
- case ID_SCE:
+ BKE_cachefile_copy_data(bmain, (CacheFile *)*r_newid, (CacheFile *)id, flag);
+ break;
+ case ID_SO:
+ BKE_sound_copy_data(bmain, (bSound *)*r_newid, (bSound *)id, flag);
+ break;
+ case ID_VF:
+ BKE_vfont_copy_data(bmain, (VFont *)*r_newid, (VFont *)id, flag);
+ break;
case ID_LI:
case ID_SCR:
case ID_WM:
- return false; /* can't be copied from here */
- case ID_VF:
- case ID_SO:
- return false; /* not implemented */
case ID_IP:
- return false; /* deprecated */
+ BLI_assert(0); /* Should have been rejected at start of function! */
+ break;
}
-
- return false;
+
+ /* Update ID refcount, remap pointers to self in new ID. */
+ struct IDCopyLibManagementData data = {.id_src = id, .id_dst = *r_newid, .flag = flag};
+ BKE_library_foreach_ID_link(bmain, *r_newid, id_copy_libmanagement_cb, &data, IDWALK_NOP);
+
+ /* Do not make new copy local in case we are copying outside of main...
+ * XXX TODO: is this behavior OK, or should we need own flag to control that? */
+ if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ BKE_id_copy_ensure_local(bmain, id, *r_newid);
+ }
+
+ return true;
+}
+
+/**
+ * Invokes the appropriate copy method for the block and returns the result in
+ * newid, unless test. Returns true if the block can be copied.
+ */
+bool id_copy(Main *bmain, const ID *id, ID **newid, bool test)
+{
+ return BKE_id_copy_ex(bmain, id, newid, 0, test);
}
/** Does *not* set ID->newid pointer. */
@@ -623,6 +695,101 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
return false;
}
+static int libblock_management_us_plus(void *UNUSED(user_data), ID *UNUSED(id_self), ID **id_pointer, int cb_flag)
+{
+ if (cb_flag & IDWALK_CB_USER) {
+ id_us_plus(*id_pointer);
+ }
+ if (cb_flag & IDWALK_CB_USER_ONE) {
+ id_us_ensure_real(*id_pointer);
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+static int libblock_management_us_min(void *UNUSED(user_data), ID *UNUSED(id_self), ID **id_pointer, int cb_flag)
+{
+ if (cb_flag & IDWALK_CB_USER) {
+ id_us_min(*id_pointer);
+ }
+ /* We can do nothing in IDWALK_CB_USER_ONE case! */
+
+ return IDWALK_RET_NOP;
+}
+
+/** Add a 'NO_MAIN' datablock to given main (also sets usercounts of its IDs if needed). */
+void BKE_libblock_management_main_add(Main *bmain, void *idv)
+{
+ ID *id = idv;
+
+ BLI_assert(bmain != NULL);
+ if ((id->tag & LIB_TAG_NO_MAIN) == 0) {
+ return;
+ }
+
+ if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) {
+ /* We cannot add non-allocated ID to Main! */
+ return;
+ }
+
+ /* We cannot allow non-userrefcounting IDs in Main database! */
+ if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) {
+ BKE_library_foreach_ID_link(bmain, id, libblock_management_us_plus, NULL, IDWALK_NOP);
+ }
+
+ ListBase *lb = which_libbase(bmain, GS(id->name));
+ BKE_main_lock(bmain);
+ BLI_addtail(lb, id);
+ new_id(lb, id, NULL);
+ /* alphabetic insertion: is in new_id */
+ id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT);
+ BKE_main_unlock(bmain);
+}
+
+/** Remove a datablock from given main (set it to 'NO_MAIN' status). */
+void BKE_libblock_management_main_remove(Main *bmain, void *idv)
+{
+ ID *id = idv;
+
+ BLI_assert(bmain != NULL);
+ if ((id->tag & LIB_TAG_NO_MAIN) != 0) {
+ return;
+ }
+
+ /* For now, allow userrefcounting IDs to get out of Main - can be handy in some cases... */
+
+ ListBase *lb = which_libbase(bmain, GS(id->name));
+ BKE_main_lock(bmain);
+ BLI_remlink(lb, id);
+ id->tag |= LIB_TAG_NO_MAIN;
+ BKE_main_unlock(bmain);
+}
+
+void BKE_libblock_management_usercounts_set(Main *bmain, void *idv)
+{
+ ID *id = idv;
+
+ if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) == 0) {
+ return;
+ }
+
+ BKE_library_foreach_ID_link(bmain, id, libblock_management_us_plus, NULL, IDWALK_NOP);
+ id->tag &= ~LIB_TAG_NO_USER_REFCOUNT;
+}
+
+void BKE_libblock_management_usercounts_clear(Main *bmain, void *idv)
+{
+ ID *id = idv;
+
+ /* We do not allow IDs in Main database to not be userrefcounting. */
+ if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0 || (id->tag & LIB_TAG_NO_MAIN) != 0) {
+ return;
+ }
+
+ BKE_library_foreach_ID_link(bmain, id, libblock_management_us_min, NULL, IDWALK_NOP);
+ id->tag |= LIB_TAG_NO_USER_REFCOUNT;
+}
+
ListBase *which_libbase(Main *mainlib, short type)
{
switch ((ID_Type)type) {
@@ -858,118 +1025,72 @@ int set_listbasepointers(Main *main, ListBase **lb)
* **************************** */
/**
+ * Get allocation size fo a given datablock type and optionally allocation name.
+ */
+size_t BKE_libblock_get_alloc_info(short type, const char **name)
+{
+#define CASE_RETURN(id_code, type) \
+ case id_code: \
+ do { \
+ if (name != NULL) { \
+ *name = #type; \
+ } \
+ return sizeof(type); \
+ } while(0)
+
+ switch ((ID_Type)type) {
+ CASE_RETURN(ID_SCE, Scene);
+ CASE_RETURN(ID_LI, Library);
+ CASE_RETURN(ID_OB, Object);
+ CASE_RETURN(ID_ME, Mesh);
+ CASE_RETURN(ID_CU, Curve);
+ CASE_RETURN(ID_MB, MetaBall);
+ CASE_RETURN(ID_MA, Material);
+ CASE_RETURN(ID_TE, Tex);
+ CASE_RETURN(ID_IM, Image);
+ CASE_RETURN(ID_LT, Lattice);
+ CASE_RETURN(ID_LA, Lamp);
+ CASE_RETURN(ID_CA, Camera);
+ CASE_RETURN(ID_IP, Ipo);
+ CASE_RETURN(ID_KE, Key);
+ CASE_RETURN(ID_WO, World);
+ CASE_RETURN(ID_SCR, bScreen);
+ CASE_RETURN(ID_VF, VFont);
+ CASE_RETURN(ID_TXT, Text);
+ CASE_RETURN(ID_SPK, Speaker);
+ CASE_RETURN(ID_SO, bSound);
+ CASE_RETURN(ID_GR, Group);
+ CASE_RETURN(ID_AR, bArmature);
+ CASE_RETURN(ID_AC, bAction);
+ CASE_RETURN(ID_NT, bNodeTree);
+ CASE_RETURN(ID_BR, Brush);
+ CASE_RETURN(ID_PA, ParticleSettings);
+ CASE_RETURN(ID_WM, wmWindowManager);
+ CASE_RETURN(ID_GD, bGPdata);
+ CASE_RETURN(ID_MC, MovieClip);
+ CASE_RETURN(ID_MSK, Mask);
+ CASE_RETURN(ID_LS, FreestyleLineStyle);
+ CASE_RETURN(ID_PAL, Palette);
+ CASE_RETURN(ID_PC, PaintCurve);
+ CASE_RETURN(ID_CF, CacheFile);
+ }
+ return 0;
+#undef CASE_RETURN
+}
+
+/**
* Allocates and returns memory of the right size for the specified block type,
* initialized to zero.
*/
void *BKE_libblock_alloc_notest(short type)
{
- ID *id = NULL;
-
- switch ((ID_Type)type) {
- case ID_SCE:
- id = MEM_callocN(sizeof(Scene), "scene");
- break;
- case ID_LI:
- id = MEM_callocN(sizeof(Library), "library");
- break;
- case ID_OB:
- id = MEM_callocN(sizeof(Object), "object");
- break;
- case ID_ME:
- id = MEM_callocN(sizeof(Mesh), "mesh");
- break;
- case ID_CU:
- id = MEM_callocN(sizeof(Curve), "curve");
- break;
- case ID_MB:
- id = MEM_callocN(sizeof(MetaBall), "mball");
- break;
- case ID_MA:
- id = MEM_callocN(sizeof(Material), "mat");
- break;
- case ID_TE:
- id = MEM_callocN(sizeof(Tex), "tex");
- break;
- case ID_IM:
- id = MEM_callocN(sizeof(Image), "image");
- break;
- case ID_LT:
- id = MEM_callocN(sizeof(Lattice), "latt");
- break;
- case ID_LA:
- id = MEM_callocN(sizeof(Lamp), "lamp");
- break;
- case ID_CA:
- id = MEM_callocN(sizeof(Camera), "camera");
- break;
- case ID_IP:
- id = MEM_callocN(sizeof(Ipo), "ipo");
- break;
- case ID_KE:
- id = MEM_callocN(sizeof(Key), "key");
- break;
- case ID_WO:
- id = MEM_callocN(sizeof(World), "world");
- break;
- case ID_SCR:
- id = MEM_callocN(sizeof(bScreen), "screen");
- break;
- case ID_VF:
- id = MEM_callocN(sizeof(VFont), "vfont");
- break;
- case ID_TXT:
- id = MEM_callocN(sizeof(Text), "text");
- break;
- case ID_SPK:
- id = MEM_callocN(sizeof(Speaker), "speaker");
- break;
- case ID_SO:
- id = MEM_callocN(sizeof(bSound), "sound");
- break;
- case ID_GR:
- id = MEM_callocN(sizeof(Group), "group");
- break;
- case ID_AR:
- id = MEM_callocN(sizeof(bArmature), "armature");
- break;
- case ID_AC:
- id = MEM_callocN(sizeof(bAction), "action");
- break;
- case ID_NT:
- id = MEM_callocN(sizeof(bNodeTree), "nodetree");
- break;
- case ID_BR:
- id = MEM_callocN(sizeof(Brush), "brush");
- break;
- case ID_PA:
- id = MEM_callocN(sizeof(ParticleSettings), "ParticleSettings");
- break;
- case ID_WM:
- id = MEM_callocN(sizeof(wmWindowManager), "Window manager");
- break;
- case ID_GD:
- id = MEM_callocN(sizeof(bGPdata), "Grease Pencil");
- break;
- case ID_MC:
- id = MEM_callocN(sizeof(MovieClip), "Movie Clip");
- break;
- case ID_MSK:
- id = MEM_callocN(sizeof(Mask), "Mask");
- break;
- case ID_LS:
- id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style");
- break;
- case ID_PAL:
- id = MEM_callocN(sizeof(Palette), "Palette");
- break;
- case ID_PC:
- id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
- break;
- case ID_CF:
- id = MEM_callocN(sizeof(CacheFile), "Cache File");
- break;
+ const char *name;
+ size_t size = BKE_libblock_get_alloc_info(type, &name);
+ if (size != 0) {
+ return MEM_callocN(size, name);
}
- return id;
+ BLI_assert(!"Request to allocate unknown data type");
+ return NULL;
}
/**
@@ -978,23 +1099,44 @@ void *BKE_libblock_alloc_notest(short type)
* The user count is set to 1, all other content (apart from name and links) being
* initialized to zero.
*/
-void *BKE_libblock_alloc(Main *bmain, short type, const char *name)
+void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int flag)
{
- ID *id = NULL;
- ListBase *lb = which_libbase(bmain, type);
-
- id = BKE_libblock_alloc_notest(type);
+ BLI_assert((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
+
+ ID *id = BKE_libblock_alloc_notest(type);
+
if (id) {
- BKE_main_lock(bmain);
- BLI_addtail(lb, id);
- id->us = 1;
+ if ((flag & LIB_ID_CREATE_NO_MAIN) != 0) {
+ id->tag |= LIB_TAG_NO_MAIN;
+ }
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0) {
+ id->tag |= LIB_TAG_NO_USER_REFCOUNT;
+ }
+
id->icon_id = 0;
- *( (short *)id->name) = type;
- new_id(lb, id, name);
- /* alphabetic insertion: is in new_id */
- BKE_main_unlock(bmain);
+ *((short *)id->name) = type;
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id->us = 1;
+ }
+ if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ ListBase *lb = which_libbase(bmain, type);
+
+ BKE_main_lock(bmain);
+ BLI_addtail(lb, id);
+ new_id(lb, id, name);
+ /* alphabetic insertion: is in new_id */
+ BKE_main_unlock(bmain);
+
+ /* TODO to be removed from here! */
+ if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
+ DAG_id_type_tag(bmain, type);
+ }
+ }
+ else {
+ BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2);
+ }
}
- DAG_id_type_tag(bmain, type);
+
return id;
}
@@ -1117,70 +1259,80 @@ void BKE_libblock_init_empty(ID *id)
/* by spec, animdata is first item after ID */
/* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */
-static void id_copy_animdata(ID *id, const bool do_action)
+static void id_copy_animdata(Main *bmain, ID *id, const bool do_action)
{
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
- iat->adt = BKE_animdata_copy(iat->adt, do_action); /* could be set to false, need to investigate */
+ iat->adt = BKE_animdata_copy(bmain, iat->adt, do_action); /* could be set to false, need to investigate */
}
}
-/* material nodes use this since they are not treated as libdata */
-void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action)
+void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
{
- if (id_from->properties)
- id->properties = IDP_CopyProperty(id_from->properties);
+ ID *new_id = *r_newid;
- /* the duplicate should get a copy of the animdata */
- id_copy_animdata(id, do_action);
-}
-
-/* used everywhere in blenkernel */
-void *BKE_libblock_copy(Main *bmain, ID *id)
-{
- ID *idn;
- size_t idn_len;
+ /* Grrrrrrrrr... Not adding 'root' nodetrees to bmain.... grrrrrrrrrrrrrrrrrrrr! */
+ /* This is taken from original ntree copy code, might be weak actually? */
+ const bool use_nodetree_alloc_exception = ((GS(id->name) == ID_NT) && (bmain != NULL) &&
+ (BLI_findindex(&bmain->nodetree, id) < 0));
- idn = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2);
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0);
- assert(idn != NULL);
+ if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) {
+ /* r_newid already contains pointer to allocated memory. */
+ /* TODO do we want to memset(0) whole mem before filling it? */
+ BLI_strncpy(new_id->name, id->name, sizeof(new_id->name));
+ new_id->us = 0;
+ new_id->tag |= LIB_TAG_NOT_ALLOCATED | LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT;
+ /* TODO Do we want/need to copy more from ID struct itself? */
+ }
+ else {
+ new_id = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag | (use_nodetree_alloc_exception ? LIB_ID_CREATE_NO_MAIN : 0));
+ }
+ BLI_assert(new_id != NULL);
- idn_len = MEM_allocN_len(idn);
- if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */
+ const size_t id_len = BKE_libblock_get_alloc_info(GS(new_id->name), NULL);
+ const size_t id_offset = sizeof(ID);
+ if ((int)id_len - (int)id_offset > 0) { /* signed to allow neg result */ /* XXX ????? */
const char *cp = (const char *)id;
- char *cpn = (char *)idn;
+ char *cpn = (char *)new_id;
- memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
+ memcpy(cpn + id_offset, cp + id_offset, id_len - id_offset);
}
- BKE_libblock_copy_data(idn, id, false);
-
- return idn;
+ if (id->properties) {
+ new_id->properties = IDP_CopyProperty_ex(id->properties, flag);
+ }
+
+ /* the duplicate should get a copy of the animdata */
+ id_copy_animdata(bmain, new_id, (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0);
+
+ if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ DAG_id_type_tag(bmain, GS(new_id->name));
+ }
+
+ *r_newid = new_id;
}
-void *BKE_libblock_copy_nolib(ID *id, const bool do_action)
+/* used everywhere in blenkernel */
+void *BKE_libblock_copy(Main *bmain, const ID *id)
{
ID *idn;
- size_t idn_len;
- idn = BKE_libblock_alloc_notest(GS(id->name));
- assert(idn != NULL);
+ BKE_libblock_copy_ex(bmain, id, &idn, 0);
- BLI_strncpy(idn->name, id->name, sizeof(idn->name));
-
- idn_len = MEM_allocN_len(idn);
- if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */
- const char *cp = (const char *)id;
- char *cpn = (char *)idn;
-
- memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
- }
+ return idn;
+}
- idn->us = 1;
+void *BKE_libblock_copy_nolib(const ID *id, const bool do_action)
+{
+ ID *idn;
- BKE_libblock_copy_data(idn, id, do_action);
+ BKE_libblock_copy_ex(NULL, id, &idn, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | (do_action ? LIB_ID_COPY_ACTIONS : 0));
return idn;
}
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 931002e6bbc..d1f0c87183d 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -512,7 +512,8 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
/* Object is special, proxies make things hard... */
const int data_cb_flag = data.cb_flag;
- const int proxy_cb_flag = (object->proxy || object->proxy_group) ? IDWALK_CB_INDIRECT_USAGE : 0;
+ const int proxy_cb_flag = ((data.flag & IDWALK_NO_INDIRECT_PROXY_DATA_USAGE) == 0 && (object->proxy || object->proxy_group)) ?
+ IDWALK_CB_INDIRECT_USAGE : 0;
/* object data special case */
data.cb_flag |= proxy_cb_flag;
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 24626c6ead7..f8c193fe108 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -186,8 +186,8 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
#ifdef DEBUG_PRINT
- printf("In %s: Remapping %s (%p) to %s (%p) (skip_indirect: %d)\n",
- id->name, old_id->name, old_id, new_id ? new_id->name : "<NONE>", new_id, skip_indirect);
+ printf("In %s: Remapping %s (%p) to %s (%p) (is_indirect: %d, skip_indirect: %d)\n",
+ id->name, old_id->name, old_id, new_id ? new_id->name : "<NONE>", new_id, is_indirect, skip_indirect);
#endif
if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_CB_NEVER_NULL)) {
@@ -201,6 +201,14 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
{
if (is_indirect) {
id_remap_data->skipped_indirect++;
+ if (is_obj) {
+ Object *ob = (Object *)id;
+ if (ob->data == *id_p && ob->proxy != NULL) {
+ /* And another 'Proudly brought to you by Proxy Hell' hack!
+ * This will allow us to avoid clearing 'LIB_EXTERN' flag of obdata of proxies... */
+ id_remap_data->skipped_direct++;
+ }
+ }
}
else if (is_never_null || is_obj_editmode) {
id_remap_data->skipped_direct++;
@@ -241,7 +249,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
return IDWALK_RET_NOP;
}
-/* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */
+/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */
static void libblock_remap_data_preprocess_scene_base_unlink(
IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect)
{
@@ -318,7 +326,7 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
}
}
-static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain, Object *old_ob, Object *new_ob)
+static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *old_ob, Object *new_ob)
{
if (old_ob->flag & OB_FROMGROUP) {
/* Note that for Scene's BaseObject->flag, either we:
@@ -337,6 +345,13 @@ static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain,
new_ob->flag |= OB_FROMGROUP;
}
}
+ if (old_ob->type == OB_MBALL) {
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->type == OB_MBALL && BKE_mball_is_basis_for(ob, old_ob)) {
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ }
+ }
}
static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmain), Scene *sce, ID *old_id)
@@ -419,6 +434,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
IDRemap id_remap_data;
ListBase *lb_array[MAX_LIBARRAY];
int i;
+ const int foreach_id_flags = (remap_flags & ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE) != 0 ? IDWALK_NO_INDIRECT_PROXY_DATA_USAGE : IDWALK_NOP;
if (r_id_remap_data == NULL) {
r_id_remap_data = &id_remap_data;
@@ -439,7 +455,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
#endif
r_id_remap_data->id = id;
libblock_remap_data_preprocess(r_id_remap_data);
- BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+ BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags);
}
else {
i = set_listbasepointers(bmain, lb_array);
@@ -456,7 +472,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
r_id_remap_data->id = id_curr;
libblock_remap_data_preprocess(r_id_remap_data);
BKE_library_foreach_ID_link(
- NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+ NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags);
}
}
}
@@ -546,7 +562,7 @@ void BKE_libblock_remap_locked(
*/
switch (GS(old_id->name)) {
case ID_OB:
- libblock_remap_data_postprocess_object_fromgroup_update(bmain, (Object *)old_id, (Object *)new_id);
+ libblock_remap_data_postprocess_object_update(bmain, (Object *)old_id, (Object *)new_id);
break;
case ID_GR:
if (!new_id) { /* Only affects us in case group was unlinked. */
@@ -656,8 +672,7 @@ void BKE_libblock_relink_ex(
switch (GS(old_id->name)) {
case ID_OB:
{
- libblock_remap_data_postprocess_object_fromgroup_update(
- bmain, (Object *)old_id, (Object *)new_id);
+ libblock_remap_data_postprocess_object_update(bmain, (Object *)old_id, (Object *)new_id);
break;
}
case ID_GR:
@@ -672,7 +687,7 @@ void BKE_libblock_relink_ex(
else {
/* No choice but to check whole objects/groups. */
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
- libblock_remap_data_postprocess_object_fromgroup_update(bmain, ob, NULL);
+ libblock_remap_data_postprocess_object_update(bmain, ob, NULL);
}
for (Group *grp = bmain->group.first; grp; grp = grp->id.next) {
libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, NULL);
@@ -723,38 +738,19 @@ void BKE_libblock_relink_to_newid(ID *id)
BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0);
}
-void BKE_libblock_free_data(Main *UNUSED(bmain), ID *id, const bool do_id_user)
+void BKE_libblock_free_data(ID *id, const bool do_id_user)
{
if (id->properties) {
IDP_FreeProperty_ex(id->properties, do_id_user);
MEM_freeN(id->properties);
}
+
+ /* XXX TODO remove animdata handling from each type's freeing func, and do it here, like for copy! */
}
-/**
- * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
- *
- * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv.
- * (only applies to main database)
- * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to
- * \a id.
- */
-void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user)
+void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
{
- ID *id = idv;
- short type = GS(id->name);
- ListBase *lb = which_libbase(bmain, type);
-
- DAG_id_type_tag(bmain, type);
-
-#ifdef WITH_PYTHON
- BPY_id_release(id);
-#endif
-
- if (do_id_user) {
- BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
- }
-
+ const short type = GS(id->name);
switch (type) {
case ID_SCE:
BKE_scene_free((Scene *)id);
@@ -860,6 +856,117 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b
BKE_cachefile_free((CacheFile *)id);
break;
}
+}
+
+
+void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag)
+{
+ ID *id = idv;
+
+ if (use_flag_from_idtag) {
+ if ((id->tag & LIB_TAG_NO_MAIN) != 0) {
+ flag |= LIB_ID_FREE_NO_MAIN;
+ }
+ else {
+ flag &= ~LIB_ID_FREE_NO_MAIN;
+ }
+
+ if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) {
+ flag |= LIB_ID_FREE_NO_USER_REFCOUNT;
+ }
+ else {
+ flag &= ~LIB_ID_FREE_NO_USER_REFCOUNT;
+ }
+
+ if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) {
+ flag |= LIB_ID_FREE_NOT_ALLOCATED;
+ }
+ else {
+ flag &= ~LIB_ID_FREE_NOT_ALLOCATED;
+ }
+ }
+
+ BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || bmain != NULL);
+ BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NOT_ALLOCATED) == 0);
+ BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
+
+ const short type = GS(id->name);
+
+ if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) {
+ DAG_id_type_tag(bmain, type);
+ }
+
+#ifdef WITH_PYTHON
+ BPY_id_release(id);
+#endif
+
+ if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) {
+ BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
+ }
+
+ BKE_libblock_free_datablock(id, flag);
+
+ /* avoid notifying on removed data */
+ if (bmain) {
+ BKE_main_lock(bmain);
+ }
+
+ if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) {
+ if (free_notifier_reference_cb) {
+ free_notifier_reference_cb(id);
+ }
+
+ if (remap_editor_id_reference_cb) {
+ remap_editor_id_reference_cb(id, NULL);
+ }
+ }
+
+ if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
+ ListBase *lb = which_libbase(bmain, type);
+ BLI_remlink(lb, id);
+ }
+
+ BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
+
+ if (bmain) {
+ BKE_main_unlock(bmain);
+ }
+
+ if ((flag & LIB_ID_FREE_NOT_ALLOCATED) == 0) {
+ MEM_freeN(id);
+ }
+}
+
+void BKE_id_free(Main *bmain, void *idv)
+{
+ BKE_id_free_ex(bmain, idv, 0, true);
+}
+
+/**
+ * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
+ *
+ * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv.
+ * (only applies to main database)
+ * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to
+ * \a id.
+ */
+void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user)
+{
+ ID *id = idv;
+ short type = GS(id->name);
+ ListBase *lb = which_libbase(bmain, type);
+
+ DAG_id_type_tag(bmain, type);
+
+#ifdef WITH_PYTHON
+ BPY_id_release(id);
+#endif
+
+ if (do_id_user) {
+ BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
+ }
+
+ BKE_libblock_free_datablock(id, 0);
/* avoid notifying on removed data */
BKE_main_lock(bmain);
@@ -876,7 +983,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b
BLI_remlink(lb, id);
- BKE_libblock_free_data(bmain, id, do_id_user);
+ BKE_libblock_free_data(id, do_id_user);
BKE_main_unlock(bmain);
MEM_freeN(id);
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 1eb909bd9f9..1b1a12e702a 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -119,7 +119,7 @@ FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name)
{
FreestyleLineStyle *linestyle;
- linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(bmain, ID_LS, name);
+ linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(bmain, ID_LS, name, 0);
BKE_linestyle_init(linestyle);
@@ -155,73 +155,54 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle)
BKE_linestyle_geometry_modifier_remove(linestyle, m);
}
-FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle)
+/**
+ * Only copy internal data of Linestyle ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_linestyle_copy_data(
+ struct Main *bmain, FreestyleLineStyle *linestyle_dst, const FreestyleLineStyle *linestyle_src, const int flag)
{
- FreestyleLineStyle *new_linestyle;
- LineStyleModifier *m;
- int a;
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
- new_linestyle = BKE_linestyle_new(bmain, linestyle->id.name + 2);
- BKE_linestyle_free(new_linestyle);
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (linestyle->mtex[a]) {
- new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_linestyle_copy");
- memcpy(new_linestyle->mtex[a], linestyle->mtex[a], sizeof(MTex));
- id_us_plus((ID *)new_linestyle->mtex[a]->tex);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (linestyle_src->mtex[a]) {
+ linestyle_dst->mtex[a] = MEM_mallocN(sizeof(*linestyle_dst->mtex[a]), __func__);
+ *linestyle_dst->mtex[a] = *linestyle_src->mtex[a];
}
}
- if (linestyle->nodetree) {
- new_linestyle->nodetree = ntreeCopyTree(bmain, linestyle->nodetree);
+ if (linestyle_src->nodetree) {
+ BKE_id_copy_ex(bmain, (ID *)linestyle_src->nodetree, (ID **)&linestyle_dst->nodetree, flag, false);
}
- new_linestyle->r = linestyle->r;
- new_linestyle->g = linestyle->g;
- new_linestyle->b = linestyle->b;
- new_linestyle->alpha = linestyle->alpha;
- new_linestyle->thickness = linestyle->thickness;
- new_linestyle->thickness_position = linestyle->thickness_position;
- new_linestyle->thickness_ratio = linestyle->thickness_ratio;
- new_linestyle->flag = linestyle->flag;
- new_linestyle->caps = linestyle->caps;
- new_linestyle->chaining = linestyle->chaining;
- new_linestyle->rounds = linestyle->rounds;
- new_linestyle->split_length = linestyle->split_length;
- new_linestyle->min_angle = linestyle->min_angle;
- new_linestyle->max_angle = linestyle->max_angle;
- new_linestyle->min_length = linestyle->min_length;
- new_linestyle->max_length = linestyle->max_length;
- new_linestyle->chain_count = linestyle->chain_count;
- new_linestyle->split_dash1 = linestyle->split_dash1;
- new_linestyle->split_gap1 = linestyle->split_gap1;
- new_linestyle->split_dash2 = linestyle->split_dash2;
- new_linestyle->split_gap2 = linestyle->split_gap2;
- new_linestyle->split_dash3 = linestyle->split_dash3;
- new_linestyle->split_gap3 = linestyle->split_gap3;
- new_linestyle->dash1 = linestyle->dash1;
- new_linestyle->gap1 = linestyle->gap1;
- new_linestyle->dash2 = linestyle->dash2;
- new_linestyle->gap2 = linestyle->gap2;
- new_linestyle->dash3 = linestyle->dash3;
- new_linestyle->gap3 = linestyle->gap3;
- new_linestyle->panel = linestyle->panel;
- new_linestyle->sort_key = linestyle->sort_key;
- new_linestyle->integration_type = linestyle->integration_type;
- new_linestyle->texstep = linestyle->texstep;
- new_linestyle->pr_texture = linestyle->pr_texture;
- new_linestyle->use_nodes = linestyle->use_nodes;
- for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next)
- BKE_linestyle_color_modifier_copy(new_linestyle, m);
- for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next)
- BKE_linestyle_alpha_modifier_copy(new_linestyle, m);
- for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next)
- BKE_linestyle_thickness_modifier_copy(new_linestyle, m);
- for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next)
- BKE_linestyle_geometry_modifier_copy(new_linestyle, m);
-
- BKE_id_copy_ensure_local(bmain, &linestyle->id, &new_linestyle->id);
-
- return new_linestyle;
+ LineStyleModifier *m;
+ BLI_listbase_clear(&linestyle_dst->color_modifiers);
+ for (m = (LineStyleModifier *)linestyle_src->color_modifiers.first; m; m = m->next) {
+ BKE_linestyle_color_modifier_copy(linestyle_dst, m, flag_subdata);
+ }
+ BLI_listbase_clear(&linestyle_dst->alpha_modifiers);
+ for (m = (LineStyleModifier *)linestyle_src->alpha_modifiers.first; m; m = m->next) {
+ BKE_linestyle_alpha_modifier_copy(linestyle_dst, m, flag_subdata);
+ }
+ BLI_listbase_clear(&linestyle_dst->thickness_modifiers);
+ for (m = (LineStyleModifier *)linestyle_src->thickness_modifiers.first; m; m = m->next) {
+ BKE_linestyle_thickness_modifier_copy(linestyle_dst, m, flag_subdata);
+ }
+ BLI_listbase_clear(&linestyle_dst->geometry_modifiers);
+ for (m = (LineStyleModifier *)linestyle_src->geometry_modifiers.first; m; m = m->next) {
+ BKE_linestyle_geometry_modifier_copy(linestyle_dst, m, flag_subdata);
+ }
+}
+
+FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle)
+{
+ FreestyleLineStyle *linestyle_copy;
+ BKE_id_copy_ex(bmain, &linestyle->id, (ID **)&linestyle_copy, 0, false);
+ return linestyle_copy;
}
void BKE_linestyle_make_local(struct Main *bmain, FreestyleLineStyle *linestyle, const bool lib_local)
@@ -355,7 +336,8 @@ LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyl
return m;
}
-LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_color_modifier_copy(
+ FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag)
{
LineStyleModifier *new_m;
@@ -388,9 +370,10 @@ LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linesty
{
LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)m;
LineStyleColorModifier_DistanceFromObject *q = (LineStyleColorModifier_DistanceFromObject *)new_m;
- if (p->target)
- id_us_plus(&p->target->id);
q->target = p->target;
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)q->target);
+ }
q->color_ramp = MEM_dupallocN(p->color_ramp);
q->range_min = p->range_min;
q->range_max = p->range_max;
@@ -594,7 +577,8 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl
return m;
}
-LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_alpha_modifier_copy(
+ FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int UNUSED(flag))
{
LineStyleModifier *new_m;
@@ -863,7 +847,8 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *line
return m;
}
-LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_thickness_modifier_copy(
+ FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag)
{
LineStyleModifier *new_m;
@@ -901,9 +886,10 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *lin
{
LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)m;
LineStyleThicknessModifier_DistanceFromObject *q = (LineStyleThicknessModifier_DistanceFromObject *)new_m;
- if (p->target)
- id_us_plus(&p->target->id);
q->target = p->target;
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)q->target);
+ }
q->curve = curvemapping_copy(p->curve);
q->flags = p->flags;
q->range_min = p->range_min;
@@ -1195,7 +1181,8 @@ LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *lines
return m;
}
-LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_geometry_modifier_copy(
+ FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int UNUSED(flag))
{
LineStyleModifier *new_m;
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 6f23b82c6df..435bc949af0 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -192,7 +192,7 @@ void BKE_mask_layer_rename(Mask *mask, MaskLayer *masklay, char *oldname, char *
BKE_animdata_fix_paths_rename_all(&mask->id, "layers", oldname, masklay->name);
}
-MaskLayer *BKE_mask_layer_copy(MaskLayer *masklay)
+MaskLayer *BKE_mask_layer_copy(const MaskLayer *masklay)
{
MaskLayer *masklay_new;
MaskSpline *spline;
@@ -236,7 +236,7 @@ MaskLayer *BKE_mask_layer_copy(MaskLayer *masklay)
return masklay_new;
}
-void BKE_mask_layer_copy_list(ListBase *masklayers_new, ListBase *masklayers)
+void BKE_mask_layer_copy_list(ListBase *masklayers_new, const ListBase *masklayers)
{
MaskLayer *layer;
@@ -794,7 +794,7 @@ static Mask *mask_alloc(Main *bmain, const char *name)
{
Mask *mask;
- mask = BKE_libblock_alloc(bmain, ID_MSK, name);
+ mask = BKE_libblock_alloc(bmain, ID_MSK, name, 0);
id_fake_user_set(&mask->id);
@@ -821,6 +821,7 @@ Mask *BKE_mask_new(Main *bmain, const char *name)
}
/* TODO(sergey): Use generic BKE_libblock_copy_nolib() instead. */
+/* TODO(bastien): Use new super cool & generic BKE_id_copy_ex() instead! */
Mask *BKE_mask_copy_nolib(Mask *mask)
{
Mask *mask_new;
@@ -840,22 +841,29 @@ Mask *BKE_mask_copy_nolib(Mask *mask)
return mask_new;
}
-Mask *BKE_mask_copy(Main *bmain, Mask *mask)
+/**
+ * Only copy internal data of Mask ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_mask_copy_data(Main *UNUSED(bmain), Mask *mask_dst, const Mask *mask_src, const int UNUSED(flag))
{
- Mask *mask_new;
-
- mask_new = BKE_libblock_copy(bmain, &mask->id);
-
- BLI_listbase_clear(&mask_new->masklayers);
+ BLI_listbase_clear(&mask_dst->masklayers);
- BKE_mask_layer_copy_list(&mask_new->masklayers, &mask->masklayers);
+ BKE_mask_layer_copy_list(&mask_dst->masklayers, &mask_src->masklayers); /* TODO add unused flag to those as well. */
/* enable fake user by default */
- id_fake_user_set(&mask->id);
-
- BKE_id_copy_ensure_local(bmain, &mask->id, &mask_new->id);
+ id_fake_user_set(&mask_dst->id);
+}
- return mask_new;
+Mask *BKE_mask_copy(Main *bmain, const Mask *mask)
+{
+ Mask *mask_copy;
+ BKE_id_copy_ex(bmain, &mask->id, (ID **)&mask_copy, 0, false);
+ return mask_copy;
}
void BKE_mask_make_local(Main *bmain, Mask *mask, const bool lib_local)
@@ -906,7 +914,7 @@ void BKE_mask_spline_free_list(ListBase *splines)
}
}
-static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot_point)
+static MaskSplinePoint *mask_spline_points_copy(const MaskSplinePoint *points, int tot_point)
{
MaskSplinePoint *npoints;
int i;
@@ -923,7 +931,7 @@ static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot
return npoints;
}
-MaskSpline *BKE_mask_spline_copy(MaskSpline *spline)
+MaskSpline *BKE_mask_spline_copy(const MaskSpline *spline)
{
MaskSpline *nspline = MEM_callocN(sizeof(MaskSpline), "new spline");
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 54945242fe4..f5be72c6b4d 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -212,50 +212,68 @@ Material *BKE_material_add(Main *bmain, const char *name)
{
Material *ma;
- ma = BKE_libblock_alloc(bmain, ID_MA, name);
+ ma = BKE_libblock_alloc(bmain, ID_MA, name, 0);
BKE_material_init(ma);
return ma;
}
-/* XXX keep synced with next function */
-Material *BKE_material_copy(Main *bmain, Material *ma)
+/**
+ * Only copy internal data of Material ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_src, const int flag)
{
- Material *man;
- int a;
-
- man = BKE_libblock_copy(bmain, &ma->id);
-
- id_lib_extern((ID *)man->group);
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a]) {
- man->mtex[a] = MEM_mallocN(sizeof(MTex), "copymaterial");
- memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
- id_us_plus((ID *)man->mtex[a]->tex);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (ma_src->mtex[a]) {
+ ma_dst->mtex[a] = MEM_mallocN(sizeof(*ma_dst->mtex[a]), __func__);
+ *ma_dst->mtex[a] = *ma_src->mtex[a];
}
}
-
- if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
- if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
-
- if (ma->nodetree) {
- man->nodetree = ntreeCopyTree(bmain, ma->nodetree);
+
+ if (ma_src->ramp_col) {
+ ma_dst->ramp_col = MEM_dupallocN(ma_src->ramp_col);
+ }
+ if (ma_src->ramp_spec) {
+ ma_dst->ramp_spec = MEM_dupallocN(ma_src->ramp_spec);
}
- BKE_previewimg_id_copy(&man->id, &ma->id);
+ if (ma_src->nodetree) {
+ BKE_id_copy_ex(bmain, (ID *)ma_src->nodetree, (ID **)&ma_dst->nodetree, flag, false);
+ }
- BLI_listbase_clear(&man->gpumaterial);
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
+ BKE_previewimg_id_copy(&ma_dst->id, &ma_src->id);
+ }
+ else {
+ ma_dst->preview = NULL;
+ }
- BKE_id_copy_ensure_local(bmain, &ma->id, &man->id);
+ BLI_listbase_clear(&ma_dst->gpumaterial);
+}
- return man;
+Material *BKE_material_copy(Main *bmain, const Material *ma)
+{
+ Material *ma_copy;
+ BKE_id_copy_ex(bmain, &ma->id, (ID **)&ma_copy, 0, false);
+ return ma_copy;
}
/* XXX (see above) material copy without adding to main dbase */
Material *localize_material(Material *ma)
{
+ /* TODO replace with something like
+ * Material *ma_copy;
+ * BKE_id_copy_ex(bmain, &ma->id, (ID **)&ma_copy, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT, false);
+ * return ma_copy;
+ *
+ * ... Once f*** nodes are fully converted to that too :( */
+
Material *man;
int a;
@@ -343,6 +361,8 @@ Material ***give_matarar_id(ID *id)
return &(((Curve *)id)->mat);
case ID_MB:
return &(((MetaBall *)id)->mat);
+ default:
+ break;
}
return NULL;
}
@@ -359,6 +379,8 @@ short *give_totcolp_id(ID *id)
return &(((Curve *)id)->totcol);
case ID_MB:
return &(((MetaBall *)id)->totcol);
+ default:
+ break;
}
return NULL;
}
@@ -378,6 +400,8 @@ static void material_data_index_remove_id(ID *id, short index)
case ID_MB:
/* meta-elems don't have materials atm */
break;
+ default:
+ break;
}
}
@@ -396,6 +420,8 @@ static void material_data_index_clear_id(ID *id)
case ID_MB:
/* meta-elems don't have materials atm */
break;
+ default:
+ break;
}
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 97033a9555d..dfc49c996b1 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -96,33 +96,36 @@ MetaBall *BKE_mball_add(Main *bmain, const char *name)
{
MetaBall *mb;
- mb = BKE_libblock_alloc(bmain, ID_MB, name);
+ mb = BKE_libblock_alloc(bmain, ID_MB, name, 0);
BKE_mball_init(mb);
return mb;
}
-MetaBall *BKE_mball_copy(Main *bmain, MetaBall *mb)
+/**
+ * Only copy internal data of MetaBall ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_mball_copy_data(Main *UNUSED(bmain), MetaBall *mb_dst, const MetaBall *mb_src, const int UNUSED(flag))
{
- MetaBall *mbn;
- int a;
-
- mbn = BKE_libblock_copy(bmain, &mb->id);
+ BLI_duplicatelist(&mb_dst->elems, &mb_src->elems);
- BLI_duplicatelist(&mbn->elems, &mb->elems);
-
- mbn->mat = MEM_dupallocN(mb->mat);
- for (a = 0; a < mbn->totcol; a++) {
- id_us_plus((ID *)mbn->mat[a]);
- }
+ mb_dst->mat = MEM_dupallocN(mb_src->mat);
- mbn->editelems = NULL;
- mbn->lastelem = NULL;
-
- BKE_id_copy_ensure_local(bmain, &mb->id, &mbn->id);
+ mb_dst->editelems = NULL;
+ mb_dst->lastelem = NULL;
+}
- return mbn;
+MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb)
+{
+ MetaBall *mb_copy;
+ BKE_id_copy_ex(bmain, &mb->id, (ID **)&mb_copy, 0, false);
+ return mb_copy;
}
void BKE_mball_make_local(Main *bmain, MetaBall *mb, const bool lib_local)
@@ -470,7 +473,7 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3])
return false;
}
-void BKE_mball_transform(MetaBall *mb, float mat[4][4])
+void BKE_mball_transform(MetaBall *mb, float mat[4][4], const bool do_props)
{
MetaElem *me;
float quat[4];
@@ -482,14 +485,17 @@ void BKE_mball_transform(MetaBall *mb, float mat[4][4])
for (me = mb->elems.first; me; me = me->next) {
mul_m4_v3(mat, &me->x);
mul_qt_qtqt(me->quat, quat, me->quat);
- me->rad *= scale;
- /* hrmf, probably elems shouldn't be
- * treating scale differently - campbell */
- if (!MB_TYPE_SIZE_SQUARED(me->type)) {
- mul_v3_fl(&me->expx, scale);
- }
- else {
- mul_v3_fl(&me->expx, scale_sqrt);
+
+ if (do_props) {
+ me->rad *= scale;
+ /* hrmf, probably elems shouldn't be
+ * treating scale differently - campbell */
+ if (!MB_TYPE_SIZE_SQUARED(me->type)) {
+ mul_v3_fl(&me->expx, scale);
+ }
+ else {
+ mul_v3_fl(&me->expx, scale_sqrt);
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index c12890a354e..0d01fe77453 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -494,53 +494,56 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name)
{
Mesh *me;
- me = BKE_libblock_alloc(bmain, ID_ME, name);
+ me = BKE_libblock_alloc(bmain, ID_ME, name, 0);
BKE_mesh_init(me);
return me;
}
-Mesh *BKE_mesh_copy(Main *bmain, Mesh *me)
+/**
+ * Only copy internal data of Mesh ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int flag)
{
- Mesh *men;
- int a;
- const int do_tessface = ((me->totface != 0) && (me->totpoly == 0)); /* only do tessface if we have no polys */
-
- men = BKE_libblock_copy(bmain, &me->id);
-
- men->mat = MEM_dupallocN(me->mat);
- for (a = 0; a < men->totcol; a++) {
- id_us_plus((ID *)men->mat[a]);
- }
- id_us_plus((ID *)men->texcomesh);
+ const bool do_tessface = ((me_src->totface != 0) && (me_src->totpoly == 0)); /* only do tessface if we have no polys */
+
+ me_dst->mat = MEM_dupallocN(me_src->mat);
- CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert);
- CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge);
- CustomData_copy(&me->ldata, &men->ldata, CD_MASK_MESH, CD_DUPLICATE, men->totloop);
- CustomData_copy(&me->pdata, &men->pdata, CD_MASK_MESH, CD_DUPLICATE, men->totpoly);
+ CustomData_copy(&me_src->vdata, &me_dst->vdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totvert);
+ CustomData_copy(&me_src->edata, &me_dst->edata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totedge);
+ CustomData_copy(&me_src->ldata, &me_dst->ldata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totloop);
+ CustomData_copy(&me_src->pdata, &me_dst->pdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totpoly);
if (do_tessface) {
- CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface);
+ CustomData_copy(&me_src->fdata, &me_dst->fdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totface);
}
else {
- mesh_tessface_clear_intern(men, false);
+ mesh_tessface_clear_intern(me_dst, false);
}
- BKE_mesh_update_customdata_pointers(men, do_tessface);
+ BKE_mesh_update_customdata_pointers(me_dst, do_tessface);
- men->edit_btmesh = NULL;
+ me_dst->edit_btmesh = NULL;
- men->mselect = MEM_dupallocN(men->mselect);
- men->bb = MEM_dupallocN(men->bb);
+ me_dst->mselect = MEM_dupallocN(me_dst->mselect);
+ me_dst->bb = MEM_dupallocN(me_dst->bb);
- if (me->key) {
- men->key = BKE_key_copy(bmain, me->key);
- men->key->from = (ID *)men;
+ /* TODO Do we want to add flag to prevent this? */
+ if (me_src->key) {
+ BKE_id_copy_ex(bmain, &me_src->key->id, (ID **)&me_dst->key, flag, false);
}
+}
- BKE_id_copy_ensure_local(bmain, &me->id, &men->id);
-
- return men;
+Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me)
+{
+ Mesh *me_copy;
+ BKE_id_copy_ex(bmain, &me->id, (ID **)&me_copy, 0, false);
+ return me_copy;
}
BMesh *BKE_mesh_to_bmesh(
@@ -1339,7 +1342,7 @@ int BKE_mesh_nurbs_displist_to_mdata(
/* this may fail replacing ob->data, be sure to check ob->type */
-void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv)
+void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name)
{
Main *bmain = G.main;
Object *ob1;
@@ -1366,7 +1369,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
}
/* make mesh */
- me = BKE_mesh_add(bmain, "Mesh");
+ me = BKE_mesh_add(bmain, obdata_name);
me->totvert = totvert;
me->totedge = totedge;
me->totloop = totloop;
@@ -1386,7 +1389,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
BKE_mesh_calc_normals(me);
}
else {
- me = BKE_mesh_add(bmain, "Mesh");
+ me = BKE_mesh_add(bmain, obdata_name);
DM_to_mesh(dm, me, ob, CD_MASK_MESH, false);
}
@@ -1398,9 +1401,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
cu->mat = NULL;
cu->totcol = 0;
- if (ob->data) {
- BKE_libblock_free(bmain, ob->data);
- }
+ /* Do not decrement ob->data usercount here, it's done at end of func with BKE_libblock_free_us() call. */
ob->data = me;
ob->type = OB_MESH;
@@ -1410,11 +1411,14 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
if (ob1->data == cu) {
ob1->type = OB_MESH;
+ id_us_min((ID *)ob1->data);
ob1->data = ob->data;
- id_us_plus((ID *)ob->data);
+ id_us_plus((ID *)ob1->data);
}
ob1 = ob1->id.next;
}
+
+ BKE_libblock_free_us(bmain, cu);
}
void BKE_mesh_from_nurbs(Object *ob)
@@ -1427,7 +1431,7 @@ void BKE_mesh_from_nurbs(Object *ob)
disp = ob->curve_cache->disp;
}
- BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv);
+ BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv, cu->id.name);
}
typedef struct EdgeLink {
@@ -2055,6 +2059,12 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type)
(me->mselect[me->totselect - 1].type == type));
}
+/**
+ * Compute 'split' (aka loop, or per face corner's) normals.
+ *
+ * \param r_lnors_spacearr Allows to get computed loop normal space array. That data, among other things,
+ * contains 'smooth fan' info, useful e.g. to split geometry along sharp edges...
+ */
void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr)
{
float (*r_loopnors)[3];
@@ -2062,6 +2072,11 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
short (*clnors)[2] = NULL;
bool free_polynors = false;
+ /* Note that we enforce computing clnors when the clnor space array is requested by caller here.
+ * However, we obviously only use the autosmooth angle threshold only in case autosmooth is enabled. */
+ const bool use_split_normals = (r_lnors_spacearr != NULL) || ((mesh->flag & ME_AUTOSMOOTH) != 0);
+ const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI;
+
if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop);
@@ -2090,7 +2105,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
BKE_mesh_normals_loop_split(
mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge,
mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly,
- (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, r_lnors_spacearr, clnors, NULL);
+ use_split_normals, split_angle, r_lnors_spacearr, clnors, NULL);
if (free_polynors) {
MEM_freeN(polynors);
@@ -2122,118 +2137,70 @@ typedef struct SplitFaceNewEdge {
/* Detect needed new vertices, and update accordingly loops' vertex indices.
* WARNING! Leaves mesh in invalid state. */
static int split_faces_prepare_new_verts(
- const Mesh *mesh, MLoopNorSpaceArray *lnors_spacearr, SplitFaceNewVert **new_verts, MemArena *memarena,
- bool *r_need_vnors_recalc)
+ const Mesh *mesh, MLoopNorSpaceArray *lnors_spacearr, SplitFaceNewVert **new_verts, MemArena *memarena)
{
- /* Note: if lnors_spacearr is NULL, ther is no autosmooth handling, and we only split out flat polys. */
+ /* This is now mandatory, trying to do the job in simple way without that data is doomed to fail, even when only
+ * dealing with smooth/flat faces one can find cases that no simple algorithm can handle properly. */
+ BLI_assert(lnors_spacearr != NULL);
+
const int num_loops = mesh->totloop;
int num_verts = mesh->totvert;
MVert *mvert = mesh->mvert;
MLoop *mloop = mesh->mloop;
BLI_bitmap *verts_used = BLI_BITMAP_NEW(num_verts, __func__);
+ BLI_bitmap *done_loops = BLI_BITMAP_NEW(num_loops, __func__);
- if (lnors_spacearr) {
- BLI_bitmap *done_loops = BLI_BITMAP_NEW(num_loops, __func__);
-
- MLoop *ml = mloop;
- MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr;
- for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) {
- if (!BLI_BITMAP_TEST(done_loops, loop_idx)) {
- const int vert_idx = ml->v;
- const bool vert_used = BLI_BITMAP_TEST_BOOL(verts_used, vert_idx);
- /* If vert is already used by another smooth fan, we need a new vert for this one. */
- const int new_vert_idx = vert_used ? num_verts++ : vert_idx;
-
- BLI_assert(*lnor_space);
-
- if ((*lnor_space)->loops) {
- for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) {
- const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link);
- BLI_BITMAP_ENABLE(done_loops, ml_fan_idx);
- if (vert_used) {
- mloop[ml_fan_idx].v = new_vert_idx;
- }
- }
- }
- else {
- /* Single loop in this fan... */
- BLI_BITMAP_ENABLE(done_loops, loop_idx);
+ MLoop *ml = mloop;
+ MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr;
+
+ for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) {
+ if (!BLI_BITMAP_TEST(done_loops, loop_idx)) {
+ const int vert_idx = ml->v;
+ const bool vert_used = BLI_BITMAP_TEST_BOOL(verts_used, vert_idx);
+ /* If vert is already used by another smooth fan, we need a new vert for this one. */
+ const int new_vert_idx = vert_used ? num_verts++ : vert_idx;
+
+ BLI_assert(*lnor_space);
+
+ if ((*lnor_space)->loops) {
+ for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) {
+ const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link);
+ BLI_BITMAP_ENABLE(done_loops, ml_fan_idx);
if (vert_used) {
- ml->v = new_vert_idx;
+ mloop[ml_fan_idx].v = new_vert_idx;
}
}
-
- if (!vert_used) {
- BLI_BITMAP_ENABLE(verts_used, vert_idx);
- /* We need to update that vertex's normal here, we won't go over it again. */
- /* This is important! *DO NOT* set vnor to final computed lnor, vnor should always be defined to
- * 'automatic normal' value computed from its polys, not some custom normal.
- * Fortunately, that's the loop normal space's 'lnor' reference vector. ;) */
- normal_float_to_short_v3(mvert[vert_idx].no, (*lnor_space)->vec_lnor);
- }
- else {
- /* Add new vert to list. */
- SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert));
- new_vert->orig_index = vert_idx;
- new_vert->new_index = new_vert_idx;
- new_vert->vnor = (*lnor_space)->vec_lnor; /* See note above. */
- new_vert->next = *new_verts;
- *new_verts = new_vert;
- }
}
- }
-
- MEM_freeN(done_loops);
- }
- else {
- /* No loop normal spaces available, we only split out flat polys. */
- const int num_polys = mesh->totpoly;
- const MPoly *mpoly = mesh->mpoly;
-
- /* We do that in two loops, to keep original edges/verts to smooth polys preferencially. */
- const MPoly *mp = mpoly;
- for (int i = 0; i < num_polys; i++, mp++) {
- if (mp->flag & ME_SMOOTH) {
- const MLoop *ml = &mloop[mp->loopstart];
- for (int j = 0; j < mp->totloop; j++, ml++) {
- /* Just mark the vertex as used/reserved, that way neighbor flat polys, if any,
- * will have to create their own. */
- BLI_BITMAP_ENABLE(verts_used, ml->v);
+ else {
+ /* Single loop in this fan... */
+ BLI_BITMAP_ENABLE(done_loops, loop_idx);
+ if (vert_used) {
+ ml->v = new_vert_idx;
}
}
- }
- mp = mpoly;
- for (int i = 0; i < num_polys; i++, mp++) {
- if (!(mp->flag & ME_SMOOTH)) {
- MLoop *ml = &mloop[mp->loopstart];
- for (int j = 0; j < mp->totloop; j++, ml++) {
- const int vert_idx = ml->v;
-
- if (BLI_BITMAP_TEST(verts_used, vert_idx)) {
- /* Add new vert to list. */
- const int new_vert_idx = num_verts++;
- ml->v = new_vert_idx;
-
- SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert));
- new_vert->orig_index = vert_idx;
- new_vert->new_index = new_vert_idx;
- new_vert->vnor = NULL; /* See note below about normals. */
- new_vert->next = *new_verts;
- *new_verts = new_vert;
- }
- else {
- BLI_BITMAP_ENABLE(verts_used, vert_idx);
- }
- }
- /* Note: there is no way to get new normals for smooth vertices here (and we don't have direct access
- * to poly normals either for flat ones), so we'll have to recompute all vnors at the end... */
- *r_need_vnors_recalc = true;
+ if (!vert_used) {
+ BLI_BITMAP_ENABLE(verts_used, vert_idx);
+ /* We need to update that vertex's normal here, we won't go over it again. */
+ /* This is important! *DO NOT* set vnor to final computed lnor, vnor should always be defined to
+ * 'automatic normal' value computed from its polys, not some custom normal.
+ * Fortunately, that's the loop normal space's 'lnor' reference vector. ;) */
+ normal_float_to_short_v3(mvert[vert_idx].no, (*lnor_space)->vec_lnor);
+ }
+ else {
+ /* Add new vert to list. */
+ SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert));
+ new_vert->orig_index = vert_idx;
+ new_vert->new_index = new_vert_idx;
+ new_vert->vnor = (*lnor_space)->vec_lnor; /* See note above. */
+ new_vert->next = *new_verts;
+ *new_verts = new_vert;
}
}
}
+ MEM_freeN(done_loops);
MEM_freeN(verts_used);
return num_verts - mesh->totvert;
@@ -2352,27 +2319,17 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
}
BKE_mesh_tessface_clear(mesh);
- MLoopNorSpaceArray *lnors_spacearr = NULL;
- MemArena *memarena;
- bool need_vnors_recalc = false;
-
- if (mesh->flag & ME_AUTOSMOOTH) {
- lnors_spacearr = MEM_callocN(sizeof(*lnors_spacearr), __func__);
- /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */
- BKE_mesh_calc_normals_split_ex(mesh, lnors_spacearr);
- /* Stealing memarena from loop normals space array. */
- memarena = lnors_spacearr->mem;
- }
- else {
- /* We still have to split out flat faces... */
- memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- }
+ MLoopNorSpaceArray lnors_spacearr = {NULL};
+ /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */
+ BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr);
+ /* Stealing memarena from loop normals space array. */
+ MemArena *memarena = lnors_spacearr.mem;
SplitFaceNewVert *new_verts = NULL;
SplitFaceNewEdge *new_edges = NULL;
/* Detect loop normal spaces (a.k.a. smooth fans) that will need a new vert. */
- const int num_new_verts = split_faces_prepare_new_verts(mesh, lnors_spacearr, &new_verts, memarena, &need_vnors_recalc);
+ const int num_new_verts = split_faces_prepare_new_verts(mesh, &lnors_spacearr, &new_verts, memarena);
if (num_new_verts > 0) {
/* Reminder: beyond this point, there is no way out, mesh is in invalid state (due to early-reassignment of
@@ -2384,9 +2341,9 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
/* Reallocate all vert and edge related data. */
mesh->totvert += num_new_verts;
- mesh->totedge += num_new_edges;
CustomData_realloc(&mesh->vdata, mesh->totvert);
if (do_edges) {
+ mesh->totedge += num_new_edges;
CustomData_realloc(&mesh->edata, mesh->totedge);
}
/* Update pointers to a newly allocated memory. */
@@ -2406,18 +2363,9 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
}
- if (lnors_spacearr) {
- /* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */
- BKE_lnor_spacearr_free(lnors_spacearr);
- MEM_freeN(lnors_spacearr);
- }
- else {
- BLI_memarena_free(memarena);
- }
+ /* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */
+ BKE_lnor_spacearr_free(&lnors_spacearr);
- if (need_vnors_recalc) {
- BKE_mesh_calc_normals(mesh);
- }
#ifdef VALIDATE_MESH
BKE_mesh_validate(mesh, true, true);
#endif
@@ -2446,7 +2394,9 @@ Mesh *BKE_mesh_new_from_object(
int uv_from_orco;
/* copies object and modifiers (but not the data) */
- Object *tmpobj = BKE_object_copy_ex(bmain, ob, true);
+ Object *tmpobj;
+ /* TODO: make it temp copy outside bmain! */
+ BKE_id_copy_ex(bmain, &ob->id, (ID **)&tmpobj, LIB_ID_COPY_CACHES, false);
tmpcu = (Curve *)tmpobj->data;
id_us_min(&tmpcu->id);
@@ -2486,7 +2436,7 @@ Mesh *BKE_mesh_new_from_object(
/* convert object type to mesh */
uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
- BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco);
+ BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2);
tmpmesh = tmpobj->data;
@@ -2522,7 +2472,7 @@ Mesh *BKE_mesh_new_from_object(
if (ob != basis_ob)
return NULL; /* only do basis metaball */
- tmpmesh = BKE_mesh_add(bmain, "Mesh");
+ tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
/* BKE_mesh_add gives us a user count we don't need */
id_us_min(&tmpmesh->id);
@@ -2577,7 +2527,7 @@ Mesh *BKE_mesh_new_from_object(
else
dm = mesh_create_derived_view(sce, ob, mask);
- tmpmesh = BKE_mesh_add(bmain, "Mesh");
+ tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
DM_to_mesh(dm, tmpmesh, ob, mask, true);
/* Copy autosmooth settings from original mesh. */
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 37f4477febf..643ca3ee536 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1629,8 +1629,8 @@ void BKE_mesh_normals_loop_custom_from_vertices_set(
/**
* Computes average per-vertex normals from given custom loop normals.
*
- * @param clnors The computed custom loop normals.
- * @param r_vert_clnors The (already allocated) array where to store averaged per-vertex normals.
+ * \param clnors: The computed custom loop normals.
+ * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals.
*/
void BKE_mesh_normals_loop_to_vertex(
const int numVerts, const MLoop *mloops, const int numLoops,
@@ -2002,11 +2002,14 @@ float BKE_mesh_calc_poly_area(
* - http://forums.cgsociety.org/archive/index.php?t-756235.html
* - http://www.globalspec.com/reference/52702/203279/4-8-the-centroid-of-a-tetrahedron
*
- * \note volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid
- * (so division can be done once at the end)
- * \note results will have bias if polygon is non-planar.
+ * \note
+ * - Volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid
+ * (so division can be done once at the end).
+ * - Results will have bias if polygon is non-planar.
+ * - The resulting volume will only be correct if the mesh is manifold and has consistent face winding
+ * (non-contiguous face normals or holes in the mesh surface).
*/
-static float mesh_calc_poly_volume_and_weighted_centroid(
+static float mesh_calc_poly_volume_centroid(
const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray,
float r_cent[3])
{
@@ -2043,6 +2046,43 @@ static float mesh_calc_poly_volume_and_weighted_centroid(
return total_volume;
}
+/**
+ * \note
+ * - Results won't be correct if polygon is non-planar.
+ * - This has the advantage over #mesh_calc_poly_volume_centroid
+ * that it doesn't depend on solid geometry, instead it weights the surface by volume.
+ */
+static float mesh_calc_poly_area_centroid(
+ const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray,
+ float r_cent[3])
+{
+ int i;
+ float tri_area;
+ float total_area = 0.0f;
+ float v1[3], v2[3], v3[3], normal[3], tri_cent[3];
+
+ BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, normal);
+ copy_v3_v3(v1, mvarray[loopstart[0].v].co);
+ copy_v3_v3(v2, mvarray[loopstart[1].v].co);
+ zero_v3(r_cent);
+
+ for (i = 2; i < mpoly->totloop; i++) {
+ copy_v3_v3(v3, mvarray[loopstart[i].v].co);
+
+ tri_area = area_tri_signed_v3(v1, v2, v3, normal);
+ total_area += tri_area;
+
+ mid_v3_v3v3v3(tri_cent, v1, v2, v3);
+ madd_v3_v3fl(r_cent, tri_cent, tri_area);
+
+ copy_v3_v3(v2, v3);
+ }
+
+ mul_v3_fl(r_cent, 1.0f / total_area);
+
+ return total_area;
+}
+
#if 0 /* slow version of the function below */
void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart,
MVert *mvarray, float angles[])
@@ -2157,7 +2197,40 @@ bool BKE_mesh_center_bounds(const Mesh *me, float r_cent[3])
return false;
}
-bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3])
+bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
+{
+ int i = me->totpoly;
+ MPoly *mpoly;
+ float poly_area;
+ float total_area = 0.0f;
+ float poly_cent[3];
+
+ zero_v3(r_cent);
+
+ /* calculate a weighted average of polygon centroids */
+ for (mpoly = me->mpoly; i--; mpoly++) {
+ poly_area = mesh_calc_poly_area_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
+
+ madd_v3_v3fl(r_cent, poly_cent, poly_area);
+ total_area += poly_area;
+ }
+ /* otherwise we get NAN for 0 polys */
+ if (me->totpoly) {
+ mul_v3_fl(r_cent, 1.0f / total_area);
+ }
+
+ /* zero area faces cause this, fallback to median */
+ if (UNLIKELY(!is_finite_v3(r_cent))) {
+ return BKE_mesh_center_median(me, r_cent);
+ }
+
+ return (me->totpoly != 0);
+}
+
+/**
+ * \note Mesh must be manifold with consistent face-winding, see #mesh_calc_poly_volume_centroid for details.
+ */
+bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3])
{
int i = me->totpoly;
MPoly *mpoly;
@@ -2169,7 +2242,7 @@ bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3])
/* calculate a weighted average of polyhedron centroids */
for (mpoly = me->mpoly; i--; mpoly++) {
- poly_volume = mesh_calc_poly_volume_and_weighted_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
+ poly_volume = mesh_calc_poly_volume_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
/* poly_cent is already volume-weighted, so no need to multiply by the volume */
add_v3_v3(r_cent, poly_cent);
@@ -2189,6 +2262,7 @@ bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3])
return (me->totpoly != 0);
}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 8562988b5e1..525c0c9728e 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -165,7 +165,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(
vmap->vert[a] = newvlist;
}
- if (use_winding) {
+ if (use_winding) {
MEM_freeN(winding);
}
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index c5fa9b15896..d2fe8f27f4a 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -1184,7 +1184,6 @@ void BKE_mesh_remap_calc_loops_from_dm(
bool polys_allocated_src;
MPoly *polys_src = DM_get_poly_array(dm_src, &polys_allocated_src);
const int num_polys_src = dm_src->getNumPolys(dm_src);
- bool looptri_allocated_src = false;
const MLoopTri *looptri_src = NULL;
int num_looptri_src = 0;
@@ -1374,17 +1373,11 @@ void BKE_mesh_remap_calc_loops_from_dm(
if (dirty_tess_flag) {
dm_src->dirty &= ~dirty_tess_flag;
}
- DM_ensure_looptri(dm_src);
if (dirty_tess_flag) {
dm_src->dirty |= dirty_tess_flag;
}
- looptri_src = DM_get_looptri_array(
- dm_src,
- verts_src,
- polys_src, num_polys_src,
- loops_src, num_loops_src,
- &looptri_allocated_src);
+ looptri_src = dm_src->getLoopTriArray(dm_src);
num_looptri_src = dm_src->getNumLoopTri(dm_src);
looptri_active = BLI_BITMAP_NEW((size_t)num_looptri_src, __func__);
@@ -1403,7 +1396,7 @@ void BKE_mesh_remap_calc_loops_from_dm(
&treedata[tindex],
verts_src, verts_allocated_src,
loops_src, loops_allocated_src,
- looptri_src, num_looptri_src, looptri_allocated_src,
+ looptri_src, num_looptri_src, false,
looptri_active, num_looptri_active, bvh_epsilon, 2, 6);
if (verts_allocated_src) {
verts_allocated_src = false; /* Only 'give' our verts once, to first tree! */
@@ -1411,9 +1404,6 @@ void BKE_mesh_remap_calc_loops_from_dm(
if (loops_allocated_src) {
loops_allocated_src = false; /* Only 'give' our loops once, to first tree! */
}
- if (looptri_allocated_src) {
- looptri_allocated_src = false; /* Only 'give' our looptri once, to first tree! */
- }
}
MEM_freeN(looptri_active);
@@ -1928,9 +1918,6 @@ void BKE_mesh_remap_calc_loops_from_dm(
if (polys_allocated_src) {
MEM_freeN(polys_src);
}
- if (looptri_allocated_src) {
- MEM_freeN((void *)looptri_src);
- }
if (vert_to_loop_map_src) {
MEM_freeN(vert_to_loop_map_src);
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 2276d56b9c6..118bafa94d2 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -59,6 +59,8 @@
#include "BKE_appdir.h"
#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_multires.h"
#include "BKE_DerivedMesh.h"
@@ -269,14 +271,37 @@ void modifier_copyData_generic(const ModifierData *md_src, ModifierData *md_dst)
memcpy(md_dst_data, md_src_data, (size_t)mti->structSize - data_size);
}
-void modifier_copyData(ModifierData *md, ModifierData *target)
+static void modifier_copy_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
+{
+ ID *id = *idpoin;
+ if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
+ id_us_plus(id);
+ }
+}
+
+void modifier_copyData_ex(ModifierData *md, ModifierData *target, const int flag)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
target->mode = md->mode;
- if (mti->copyData)
+ if (mti->copyData) {
mti->copyData(md, target);
+ }
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ if (mti->foreachIDLink) {
+ mti->foreachIDLink(target, NULL, modifier_copy_data_id_us_cb, NULL);
+ }
+ else if (mti->foreachObjectLink) {
+ mti->foreachObjectLink(target, NULL, (ObjectWalkFunc)modifier_copy_data_id_us_cb, NULL);
+ }
+ }
+}
+
+void modifier_copyData(ModifierData *md, ModifierData *target)
+{
+ modifier_copyData_ex(md, target, 0);
}
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 6794a8e8f93..16d597e25fa 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -588,7 +588,7 @@ static MovieClip *movieclip_alloc(Main *bmain, const char *name)
{
MovieClip *clip;
- clip = BKE_libblock_alloc(bmain, ID_MC, name);
+ clip = BKE_libblock_alloc(bmain, ID_MC, name, 0);
clip->aspx = clip->aspy = 1.0f;
@@ -1488,25 +1488,33 @@ void BKE_movieclip_free(MovieClip *clip)
BKE_animdata_free((ID *) clip, false);
}
-MovieClip *BKE_movieclip_copy(Main *bmain, MovieClip *clip)
+/**
+ * Only copy internal data of MovieClip ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_movieclip_copy_data(Main *UNUSED(bmain), MovieClip *clip_dst, const MovieClip *clip_src, const int flag)
{
- MovieClip *clip_new;
-
- clip_new = BKE_libblock_copy(bmain, &clip->id);
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
- clip_new->anim = NULL;
- clip_new->cache = NULL;
+ clip_dst->anim = NULL;
+ clip_dst->cache = NULL;
- BKE_tracking_copy(&clip_new->tracking, &clip->tracking);
- clip_new->tracking_context = NULL;
+ BKE_tracking_copy(&clip_dst->tracking, &clip_src->tracking, flag_subdata);
+ clip_dst->tracking_context = NULL;
- id_us_plus((ID *)clip_new->gpd);
-
- BKE_color_managed_colorspace_settings_copy(&clip_new->colorspace_settings, &clip->colorspace_settings);
-
- BKE_id_copy_ensure_local(bmain, &clip->id, &clip_new->id);
+ BKE_color_managed_colorspace_settings_copy(&clip_dst->colorspace_settings, &clip_src->colorspace_settings);
+}
- return clip_new;
+MovieClip *BKE_movieclip_copy(Main *bmain, const MovieClip *clip)
+{
+ MovieClip *clip_copy;
+ BKE_id_copy_ex(bmain, &clip->id, (ID **)&clip_copy, 0, false);
+ return clip_copy;
}
void BKE_movieclip_make_local(Main *bmain, MovieClip *clip, const bool lib_local)
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 63da1b5f9e7..54afe76ec07 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -902,80 +902,100 @@ bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type)
return nodeAddNode(C, ntree, idname);
}
-static void node_socket_copy(bNodeSocket *dst, bNodeSocket *src)
+static void node_socket_copy(bNodeSocket *sock_dst, bNodeSocket *sock_src, const int flag)
{
- src->new_sock = dst;
-
- if (src->prop)
- dst->prop = IDP_CopyProperty(src->prop);
-
- if (src->default_value)
- dst->default_value = MEM_dupallocN(src->default_value);
-
- dst->stack_index = 0;
+ sock_src->new_sock = sock_dst;
+
+ if (sock_src->prop) {
+ sock_dst->prop = IDP_CopyProperty_ex(sock_src->prop, flag);
+ }
+
+ if (sock_src->default_value) {
+ sock_dst->default_value = MEM_dupallocN(sock_src->default_value);
+ }
+
+ sock_dst->stack_index = 0;
/* XXX some compositor node (e.g. image, render layers) still store
* some persistent buffer data here, need to clear this to avoid dangling pointers.
*/
- dst->cache = NULL;
+ sock_dst->cache = NULL;
}
/* keep socket listorder identical, for copying links */
/* ntree is the target tree */
-bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
+bNode *BKE_node_copy_ex(bNodeTree *ntree, bNode *node_src, const int flag)
{
- bNode *nnode = MEM_callocN(sizeof(bNode), "dupli node");
- bNodeSocket *sock, *oldsock;
- bNodeLink *link, *oldlink;
+ bNode *node_dst = MEM_callocN(sizeof(bNode), "dupli node");
+ bNodeSocket *sock_dst, *sock_src;
+ bNodeLink *link_dst, *link_src;
- *nnode = *node;
+ *node_dst = *node_src;
/* can be called for nodes outside a node tree (e.g. clipboard) */
if (ntree) {
- nodeUniqueName(ntree, nnode);
+ nodeUniqueName(ntree, node_dst);
- BLI_addtail(&ntree->nodes, nnode);
+ BLI_addtail(&ntree->nodes, node_dst);
}
- BLI_duplicatelist(&nnode->inputs, &node->inputs);
- oldsock = node->inputs.first;
- for (sock = nnode->inputs.first; sock; sock = sock->next, oldsock = oldsock->next)
- node_socket_copy(sock, oldsock);
-
- BLI_duplicatelist(&nnode->outputs, &node->outputs);
- oldsock = node->outputs.first;
- for (sock = nnode->outputs.first; sock; sock = sock->next, oldsock = oldsock->next)
- node_socket_copy(sock, oldsock);
-
- if (node->prop)
- nnode->prop = IDP_CopyProperty(node->prop);
-
- BLI_duplicatelist(&nnode->internal_links, &node->internal_links);
- oldlink = node->internal_links.first;
- for (link = nnode->internal_links.first; link; link = link->next, oldlink = oldlink->next) {
- link->fromnode = nnode;
- link->tonode = nnode;
- link->fromsock = link->fromsock->new_sock;
- link->tosock = link->tosock->new_sock;
+ BLI_duplicatelist(&node_dst->inputs, &node_src->inputs);
+ for (sock_dst = node_dst->inputs.first, sock_src = node_src->inputs.first;
+ sock_dst != NULL;
+ sock_dst = sock_dst->next, sock_src = sock_src->next)
+ {
+ node_socket_copy(sock_dst, sock_src, flag);
}
-
- /* don't increase node->id users, freenode doesn't decrement either */
-
- if (node->typeinfo->copyfunc)
- node->typeinfo->copyfunc(ntree, nnode, node);
-
- node->new_node = nnode;
- nnode->new_node = NULL;
-
- if (nnode->typeinfo->copyfunc_api) {
+
+ BLI_duplicatelist(&node_dst->outputs, &node_src->outputs);
+ for (sock_dst = node_dst->outputs.first, sock_src = node_src->outputs.first;
+ sock_dst != NULL;
+ sock_dst = sock_dst->next, sock_src = sock_src->next)
+ {
+ node_socket_copy(sock_dst, sock_src, flag);
+ }
+
+ if (node_src->prop) {
+ node_dst->prop = IDP_CopyProperty_ex(node_src->prop, flag);
+ }
+
+ BLI_duplicatelist(&node_dst->internal_links, &node_src->internal_links);
+ for (link_dst = node_dst->internal_links.first, link_src = node_src->internal_links.first;
+ link_dst != NULL;
+ link_dst = link_dst->next, link_src = link_src->next)
+ {
+ link_dst->fromnode = node_dst;
+ link_dst->tonode = node_dst;
+ link_dst->fromsock = link_dst->fromsock->new_sock;
+ link_dst->tosock = link_dst->tosock->new_sock;
+ }
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus(node_dst->id);
+ }
+
+ if (node_src->typeinfo->copyfunc) {
+ node_src->typeinfo->copyfunc(ntree, node_dst, node_src);
+ }
+
+ node_src->new_node = node_dst;
+ node_dst->new_node = NULL;
+
+ if (node_dst->typeinfo->copyfunc_api) {
PointerRNA ptr;
- RNA_pointer_create((ID *)ntree, &RNA_Node, nnode, &ptr);
-
- nnode->typeinfo->copyfunc_api(&ptr, node);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node_dst, &ptr);
+
+ node_dst->typeinfo->copyfunc_api(&ptr, node_src);
}
-
- if (ntree)
+
+ if (ntree) {
ntree->update |= NTREE_UPDATE_NODES;
-
- return nnode;
+ }
+
+ return node_dst;
+}
+
+bNode *nodeCopyNode(bNodeTree *ntree, bNode *node)
+{
+ return BKE_node_copy_ex(ntree, node, LIB_ID_CREATE_NO_USER_REFCOUNT);
}
/* also used via rna api, so we check for proper input output direction */
@@ -1172,7 +1192,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
* node groups and other tree types are created as library data.
*/
if (bmain) {
- ntree = BKE_libblock_alloc(bmain, ID_NT, name);
+ ntree = BKE_libblock_alloc(bmain, ID_NT, name, 0);
}
else {
ntree = MEM_callocN(sizeof(bNodeTree), "new node tree");
@@ -1191,119 +1211,98 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
return ntree;
}
-/* Warning: this function gets called during some rather unexpected times
- * - this gets called when executing compositing updates (for threaded previews)
- * - when the nodetree datablock needs to be copied (i.e. when users get copied)
- * - for scene duplication use ntreeSwapID() after so we don't have stale pointers.
+/**
+ * Only copy internal data of NodeTree ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
*
- * do_make_extern: keep enabled for general use, only reason _not_ to enable is when
- * copying for internal use (threads for eg), where you wont want it to modify the
- * scene data.
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
-static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool skip_database, bool do_id_user, bool do_make_extern, bool copy_previews)
+void BKE_node_tree_copy_data(Main *UNUSED(bmain), bNodeTree *ntree_dst, const bNodeTree *ntree_src, const int flag)
{
- bNodeTree *newtree;
- bNode *node /*, *nnode */ /* UNUSED */, *last;
- bNodeSocket *sock, *oldsock;
- bNodeLink *link;
-
- if (ntree == NULL) return NULL;
-
- /* is ntree part of library? */
- if (bmain && !skip_database && BLI_findindex(&bmain->nodetree, ntree) >= 0) {
- newtree = BKE_libblock_copy(bmain, &ntree->id);
- }
- else {
- newtree = BKE_libblock_copy_nolib(&ntree->id, true);
- }
+ bNodeSocket *sock_dst, *sock_src;
+ bNodeLink *link_dst;
- id_us_plus((ID *)newtree->gpd);
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
/* in case a running nodetree is copied */
- newtree->execdata = NULL;
-
- newtree->duplilock = NULL;
-
- BLI_listbase_clear(&newtree->nodes);
- BLI_listbase_clear(&newtree->links);
-
- last = ntree->nodes.last;
- for (node = ntree->nodes.first; node; node = node->next) {
+ ntree_dst->execdata = NULL;
- /* ntreeUserDecrefID inline */
- if (do_id_user) {
- id_us_plus(node->id);
- }
+ ntree_dst->duplilock = NULL;
- if (do_make_extern) {
- id_lib_extern(node->id);
- }
+ BLI_listbase_clear(&ntree_dst->nodes);
+ BLI_listbase_clear(&ntree_dst->links);
- node->new_node = NULL;
- /* nnode = */ nodeCopyNode(newtree, node); /* sets node->new */
-
- /* make sure we don't copy new nodes again! */
- if (node == last)
- break;
+ for (bNode *node_src = ntree_src->nodes.first; node_src; node_src = node_src->next) {
+ BKE_node_copy_ex(ntree_dst, node_src, flag_subdata);
}
-
+
/* copy links */
- BLI_duplicatelist(&newtree->links, &ntree->links);
- for (link = newtree->links.first; link; link = link->next) {
- link->fromnode = (link->fromnode ? link->fromnode->new_node : NULL);
- link->fromsock = (link->fromsock ? link->fromsock->new_sock : NULL);
- link->tonode = (link->tonode ? link->tonode->new_node : NULL);
- link->tosock = (link->tosock ? link->tosock->new_sock : NULL);
+ BLI_duplicatelist(&ntree_dst->links, &ntree_src->links);
+ for (link_dst = ntree_dst->links.first; link_dst; link_dst = link_dst->next) {
+ link_dst->fromnode = (link_dst->fromnode ? link_dst->fromnode->new_node : NULL);
+ link_dst->fromsock = (link_dst->fromsock ? link_dst->fromsock->new_sock : NULL);
+ link_dst->tonode = (link_dst->tonode ? link_dst->tonode->new_node : NULL);
+ link_dst->tosock = (link_dst->tosock ? link_dst->tosock->new_sock : NULL);
/* update the link socket's pointer */
- if (link->tosock)
- link->tosock->link = link;
+ if (link_dst->tosock) {
+ link_dst->tosock->link = link_dst;
+ }
}
-
+
/* copy interface sockets */
- BLI_duplicatelist(&newtree->inputs, &ntree->inputs);
- oldsock = ntree->inputs.first;
- for (sock = newtree->inputs.first; sock; sock = sock->next, oldsock = oldsock->next)
- node_socket_copy(sock, oldsock);
-
- BLI_duplicatelist(&newtree->outputs, &ntree->outputs);
- oldsock = ntree->outputs.first;
- for (sock = newtree->outputs.first; sock; sock = sock->next, oldsock = oldsock->next)
- node_socket_copy(sock, oldsock);
-
+ BLI_duplicatelist(&ntree_dst->inputs, &ntree_src->inputs);
+ for (sock_dst = ntree_dst->inputs.first, sock_src = ntree_src->inputs.first;
+ sock_dst != NULL;
+ sock_dst = sock_dst->next, sock_src = sock_src->next)
+ {
+ node_socket_copy(sock_dst, sock_src, flag_subdata);
+ }
+
+ BLI_duplicatelist(&ntree_dst->outputs, &ntree_src->outputs);
+ for (sock_dst = ntree_dst->outputs.first, sock_src = ntree_src->outputs.first;
+ sock_dst != NULL;
+ sock_dst = sock_dst->next, sock_src = sock_src->next)
+ {
+ node_socket_copy(sock_dst, sock_src, flag_subdata);
+ }
+
/* copy preview hash */
- if (ntree->previews && copy_previews) {
+ if (ntree_src->previews && (flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
bNodeInstanceHashIterator iter;
-
- newtree->previews = BKE_node_instance_hash_new("node previews");
-
- NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+
+ ntree_dst->previews = BKE_node_instance_hash_new("node previews");
+
+ NODE_INSTANCE_HASH_ITER(iter, ntree_src->previews) {
bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
- BKE_node_instance_hash_insert(newtree->previews, key, BKE_node_preview_copy(preview));
+ BKE_node_instance_hash_insert(ntree_dst->previews, key, BKE_node_preview_copy(preview));
}
}
- else
- newtree->previews = NULL;
-
+ else {
+ ntree_dst->previews = NULL;
+ }
+
/* update node->parent pointers */
- for (node = newtree->nodes.first; node; node = node->next) {
- if (node->parent)
- node->parent = node->parent->new_node;
+ for (bNode *node_dst = ntree_dst->nodes.first, *node_src = ntree_src->nodes.first; node_dst; node_dst = node_dst->next, node_src = node_src->next) {
+ if (node_dst->parent) {
+ node_dst->parent = node_dst->parent->new_node;
+ }
}
-
- /* node tree will generate its own interface type */
- newtree->interface_type = NULL;
-
- BKE_id_copy_ensure_local(bmain, &ntree->id, &newtree->id);
- return newtree;
+ /* node tree will generate its own interface type */
+ ntree_dst->interface_type = NULL;
}
-bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user)
+bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user)
{
- return ntreeCopyTree_internal(ntree, bmain, false, do_id_user, true, true);
+ bNodeTree *ntree_copy;
+ BKE_id_copy_ex(bmain, (ID *)ntree, (ID **)&ntree_copy, do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT, false);
+ return ntree_copy;
}
-bNodeTree *ntreeCopyTree(Main *bmain, bNodeTree *ntree)
+bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree)
{
return ntreeCopyTree_ex(ntree, bmain, true);
}
@@ -1698,11 +1697,12 @@ static void node_free_node_ex(bNodeTree *ntree, bNode *node, bool remove_animdat
ntreeTexEndExecTree(ntree->execdata);
ntree->execdata = NULL;
}
-
- if (node->typeinfo->freefunc)
- node->typeinfo->freefunc(node);
}
-
+
+ if (node->typeinfo->freefunc) {
+ node->typeinfo->freefunc(node);
+ }
+
for (sock = node->inputs.first; sock; sock = nextsock) {
nextsock = sock->next;
node_socket_free(ntree, sock, node);
@@ -1828,7 +1828,7 @@ void ntreeFreeTree(bNodeTree *ntree)
if (tntree == ntree)
break;
if (tntree == NULL) {
- BKE_libblock_free_data(G.main, &ntree->id, true);
+ BKE_libblock_free_data(&ntree->id, true);
}
}
@@ -1991,10 +1991,11 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
adt->tmpact = NULL;
}
- /* Make full copy.
+ /* Make full copy outside of Main database.
* Note: previews are not copied here.
*/
- ltree = ntreeCopyTree_internal(ntree, G.main, true, false, false, false);
+ BKE_id_copy_ex(G.main, (ID *)ntree, (ID **)&ltree,
+ LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_COPY_NO_PREVIEW, false);
ltree->flag |= NTREE_IS_LOCALIZED;
for (node = ltree->nodes.first; node; node = node->next) {
@@ -2234,7 +2235,7 @@ static void ntree_interface_type_create(bNodeTree *ntree)
/* register a subtype of PropertyGroup */
srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_PropertyGroup);
RNA_def_struct_ui_text(srna, name, description);
- RNA_def_struct_duplicate_pointers(srna);
+ RNA_def_struct_duplicate_pointers(&BLENDER_RNA, srna);
/* associate the RNA type with the node tree */
ntree->interface_type = srna;
@@ -2273,10 +2274,10 @@ StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create)
ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description);
/* rename the RNA type */
- RNA_def_struct_free_pointers(srna);
- RNA_def_struct_identifier(srna, identifier);
+ RNA_def_struct_free_pointers(&BLENDER_RNA, srna);
+ RNA_def_struct_identifier(&BLENDER_RNA, srna, identifier);
RNA_def_struct_ui_text(srna, name, description);
- RNA_def_struct_duplicate_pointers(srna);
+ RNA_def_struct_duplicate_pointers(&BLENDER_RNA, srna);
}
}
else if (create) {
@@ -3172,12 +3173,20 @@ void nodeSynchronizeID(bNode *node, bool copy_to_id)
void nodeLabel(bNodeTree *ntree, bNode *node, char *label, int maxlen)
{
- if (node->label[0] != '\0')
+ if (node->label[0] != '\0') {
BLI_strncpy(label, node->label, maxlen);
- else if (node->typeinfo->labelfunc)
+ }
+ else if (node->typeinfo->labelfunc) {
node->typeinfo->labelfunc(ntree, node, label, maxlen);
- else
- BLI_strncpy(label, IFACE_(node->typeinfo->ui_name), maxlen);
+ }
+ else {
+ /* Kind of hacky and weak... Ideally would be better to use RNA here. :| */
+ const char *tmp = CTX_IFACE_(BLT_I18NCONTEXT_ID_NODETREE, node->typeinfo->ui_name);
+ if (tmp == node->typeinfo->ui_name) {
+ tmp = IFACE_(node->typeinfo->ui_name);
+ }
+ BLI_strncpy(label, tmp, maxlen);
+ }
}
static void node_type_base_defaults(bNodeType *ntype)
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 536170bf108..a89b1a2d60e 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -312,7 +312,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr
modifier_unique_name(&ob_dst->modifiers, nmd);
}
- BKE_object_copy_particlesystems(ob_dst, ob_src);
+ BKE_object_copy_particlesystems(ob_dst, ob_src, 0);
/* TODO: smoke?, cloth? */
}
@@ -330,14 +330,14 @@ void BKE_object_free_derived_caches(Object *ob)
Mesh *me = ob->data;
if (me && me->bb) {
- atomic_fetch_and_or_uint32((uint*)&me->bb->flag, BOUNDBOX_DIRTY);
+ atomic_fetch_and_or_uint32((uint *)&me->bb->flag, BOUNDBOX_DIRTY);
}
}
else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
Curve *cu = ob->data;
if (cu && cu->bb) {
- atomic_fetch_and_or_uint32((uint*)&cu->bb->flag, BOUNDBOX_DIRTY);
+ atomic_fetch_and_or_uint32((uint *)&cu->bb->flag, BOUNDBOX_DIRTY);
}
}
@@ -670,7 +670,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
if (!name)
name = get_obdata_defname(type);
- ob = BKE_libblock_alloc(bmain, ID_OB, name);
+ ob = BKE_libblock_alloc(bmain, ID_OB, name, 0);
/* default object vars */
ob->type = type;
@@ -837,7 +837,7 @@ struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene)
#endif /* WITH_GAMEENGINE */
-SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches)
+SoftBody *copy_softbody(const SoftBody *sb, const int flag)
{
SoftBody *sbn;
@@ -845,7 +845,7 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches)
sbn = MEM_dupallocN(sb);
- if (copy_caches == false) {
+ if ((flag & LIB_ID_COPY_CACHES) == 0) {
sbn->totspring = sbn->totpoint = 0;
sbn->bpoint = NULL;
sbn->bspring = NULL;
@@ -874,7 +874,7 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches)
sbn->scratch = NULL;
- sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, copy_caches);
+ sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, flag);
if (sb->effector_weights)
sbn->effector_weights = MEM_dupallocN(sb->effector_weights);
@@ -882,7 +882,7 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches)
return sbn;
}
-BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
+BulletSoftBody *copy_bulletsoftbody(const BulletSoftBody *bsb, const int UNUSED(flag))
{
BulletSoftBody *bsbn;
@@ -893,7 +893,7 @@ BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
return bsbn;
}
-ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
+ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int flag)
{
ParticleSystem *psysn;
ParticleData *pa;
@@ -930,7 +930,7 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
if (psys->clmd) {
psysn->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth);
- modifier_copyData((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd);
+ modifier_copyData_ex((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd, flag);
psys->hair_in_dm = psys->hair_out_dm = NULL;
}
@@ -948,7 +948,8 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
BLI_listbase_clear(&psysn->childcachebufs);
psysn->renderdata = NULL;
- psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, false);
+ /* XXX Never copy caches here? */
+ psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag & ~LIB_ID_COPY_CACHES);
/* XXX - from reading existing code this seems correct but intended usage of
* pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
@@ -956,12 +957,14 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
psysn->clmd->point_cache = psysn->pointcache;
}
- id_us_plus((ID *)psysn->part);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)psysn->part);
+ }
return psysn;
}
-void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src)
+void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src, const int flag)
{
ParticleSystem *psys, *npsys;
ModifierData *md;
@@ -973,7 +976,7 @@ void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src)
BLI_listbase_clear(&ob_dst->particlesystem);
for (psys = ob_src->particlesystem.first; psys; psys = psys->next) {
- npsys = BKE_object_copy_particlesystem(psys);
+ npsys = BKE_object_copy_particlesystem(psys, flag);
BLI_addtail(&ob_dst->particlesystem, npsys);
@@ -1010,23 +1013,25 @@ void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src)
{
if (ob_src->soft) {
ob_dst->softflag = ob_src->softflag;
- ob_dst->soft = copy_softbody(ob_src->soft, false);
+ ob_dst->soft = copy_softbody(ob_src->soft, 0);
}
}
-static void copy_object_pose(Object *obn, Object *ob)
+static void copy_object_pose(Object *obn, const Object *ob, const int flag)
{
bPoseChannel *chan;
/* note: need to clear obn->pose pointer first, so that BKE_pose_copy_data works (otherwise there's a crash) */
obn->pose = NULL;
- BKE_pose_copy_data(&obn->pose, ob->pose, 1); /* 1 = copy constraints */
+ BKE_pose_copy_data_ex(&obn->pose, ob->pose, flag, true); /* true = copy constraints */
for (chan = obn->pose->chanbase.first; chan; chan = chan->next) {
bConstraint *con;
chan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE);
+ /* XXX Remapping object pointing onto itself should be handled by generic BKE_library_remap stuff, but...
+ * the flush_constraint_targets callback am not sure about, so will delay that for now. */
for (con = chan->constraints.first; con; con = con->next) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
@@ -1047,13 +1052,10 @@ static void copy_object_pose(Object *obn, Object *ob)
}
}
-static void copy_object_lod(Object *obn, Object *ob)
+static void copy_object_lod(Object *obn, const Object *ob, const int UNUSED(flag))
{
BLI_duplicatelist(&obn->lodlevels, &ob->lodlevels);
- if (obn->lodlevels.first)
- ((LodLevel *)obn->lodlevels.first)->source = obn;
-
obn->currentlod = (LodLevel *)obn->lodlevels.first;
}
@@ -1098,98 +1100,99 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
copy_v3_v3(ob_tar->size, ob_src->size);
}
-Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
+/**
+ * Only copy internal data of Object ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_src, const int flag)
{
- Object *obn;
ModifierData *md;
- int a;
- obn = BKE_libblock_copy(bmain, &ob->id);
-
- if (ob->totcol) {
- obn->mat = MEM_dupallocN(ob->mat);
- obn->matbits = MEM_dupallocN(ob->matbits);
- obn->totcol = ob->totcol;
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+
+ if (ob_src->totcol) {
+ ob_dst->mat = MEM_dupallocN(ob_src->mat);
+ ob_dst->matbits = MEM_dupallocN(ob_src->matbits);
+ ob_dst->totcol = ob_src->totcol;
}
- if (ob->iuser) obn->iuser = MEM_dupallocN(ob->iuser);
+ if (ob_src->iuser) ob_dst->iuser = MEM_dupallocN(ob_src->iuser);
- if (ob->bb) obn->bb = MEM_dupallocN(ob->bb);
- obn->flag &= ~OB_FROMGROUP;
+ if (ob_src->bb) ob_dst->bb = MEM_dupallocN(ob_src->bb);
+ ob_dst->flag &= ~OB_FROMGROUP;
- BLI_listbase_clear(&obn->modifiers);
+ BLI_listbase_clear(&ob_dst->modifiers);
- for (md = ob->modifiers.first; md; md = md->next) {
+ for (md = ob_src->modifiers.first; md; md = md->next) {
ModifierData *nmd = modifier_new(md->type);
BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
- modifier_copyData(md, nmd);
- BLI_addtail(&obn->modifiers, nmd);
+ modifier_copyData_ex(md, nmd, flag_subdata);
+ BLI_addtail(&ob_dst->modifiers, nmd);
}
- BLI_listbase_clear(&obn->prop);
- BKE_bproperty_copy_list(&obn->prop, &ob->prop);
+ BLI_listbase_clear(&ob_dst->prop);
+ BKE_bproperty_copy_list(&ob_dst->prop, &ob_src->prop);
- BKE_sca_logic_copy(obn, ob);
+ BKE_sca_logic_copy(ob_dst, ob_src, flag_subdata);
- if (ob->pose) {
- copy_object_pose(obn, ob);
+ if (ob_src->pose) {
+ copy_object_pose(ob_dst, ob_src, flag_subdata);
/* backwards compat... non-armatures can get poses in older files? */
- if (ob->type == OB_ARMATURE)
- BKE_pose_rebuild(obn, obn->data);
+ if (ob_src->type == OB_ARMATURE)
+ BKE_pose_rebuild(ob_dst, ob_dst->data);
}
- defgroup_copy_list(&obn->defbase, &ob->defbase);
- BKE_constraints_copy(&obn->constraints, &ob->constraints, true);
-
- obn->mode = OB_MODE_OBJECT;
- obn->sculpt = NULL;
+ defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase);
+ BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
- /* increase user numbers */
- id_us_plus((ID *)obn->data);
- id_us_plus((ID *)obn->poselib);
- id_us_plus((ID *)obn->gpd);
- id_us_plus((ID *)obn->dup_group);
+ ob_dst->mode = OB_MODE_OBJECT;
+ ob_dst->sculpt = NULL;
- for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
-
- if (ob->pd) {
- obn->pd = MEM_dupallocN(ob->pd);
- if (obn->pd->tex)
- id_us_plus(&(obn->pd->tex->id));
- if (obn->pd->rng)
- obn->pd->rng = MEM_dupallocN(ob->pd->rng);
+ if (ob_src->pd) {
+ ob_dst->pd = MEM_dupallocN(ob_src->pd);
+ if (ob_dst->pd->rng) {
+ ob_dst->pd->rng = MEM_dupallocN(ob_src->pd->rng);
+ }
}
- obn->soft = copy_softbody(ob->soft, copy_caches);
- obn->bsoft = copy_bulletsoftbody(ob->bsoft);
- obn->rigidbody_object = BKE_rigidbody_copy_object(ob);
- obn->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob);
+ ob_dst->soft = copy_softbody(ob_src->soft, flag_subdata);
+ ob_dst->bsoft = copy_bulletsoftbody(ob_src->bsoft, flag_subdata);
+ ob_dst->rigidbody_object = BKE_rigidbody_copy_object(ob_src, flag_subdata);
+ ob_dst->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob_src, flag_subdata);
- BKE_object_copy_particlesystems(obn, ob);
+ BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata);
- obn->derivedDeform = NULL;
- obn->derivedFinal = NULL;
+ ob_dst->derivedDeform = NULL;
+ ob_dst->derivedFinal = NULL;
- BLI_listbase_clear(&obn->gpulamp);
- BLI_listbase_clear(&obn->pc_ids);
+ BLI_listbase_clear(&ob_dst->gpulamp);
+ BLI_listbase_clear(&ob_dst->pc_ids);
- obn->mpath = NULL;
+ ob_dst->mpath = NULL;
- copy_object_lod(obn, ob);
+ copy_object_lod(ob_dst, ob_src, flag_subdata);
- /* Copy runtime surve data. */
- obn->curve_cache = NULL;
-
- BKE_id_copy_ensure_local(bmain, &ob->id, &obn->id);
+ /* Do not copy runtime curve data. */
+ ob_dst->curve_cache = NULL;
/* Do not copy object's preview (mostly due to the fact renderers create temp copy of objects). */
- obn->preview = NULL;
-
- return obn;
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
+ BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id);
+ }
+ else {
+ ob_dst->preview = NULL;
+ }
}
/* copy objects, will re-initialize cached simulation data */
-Object *BKE_object_copy(Main *bmain, Object *ob)
+Object *BKE_object_copy(Main *bmain, const Object *ob)
{
- return BKE_object_copy_ex(bmain, ob, false);
+ Object *ob_copy;
+ BKE_id_copy_ex(bmain, &ob->id, (ID **)&ob_copy, 0, false);
+ return ob_copy;
}
void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, const bool clear_proxy)
@@ -1387,7 +1390,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
/* type conversions */
if (target->type == OB_ARMATURE) {
- copy_object_pose(ob, target); /* data copy, object pointers in constraints */
+ copy_object_pose(ob, target, 0); /* data copy, object pointers in constraints */
BKE_pose_rest(ob->pose); /* clear all transforms in channels */
BKE_pose_rebuild(ob, ob->data); /* set all internal links */
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index ccf2aec5c7a..d387e30050c 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -481,6 +481,8 @@ bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_t
*dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
return true;
}
+ default:
+ break;
}
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index e9ebd397df0..b49e481b068 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -343,7 +343,7 @@ static void make_duplis_group(const DupliContext *ctx)
}
}
-const DupliGenerator gen_dupli_group = {
+static const DupliGenerator gen_dupli_group = {
OB_DUPLIGROUP, /* type */
make_duplis_group /* make_duplis */
};
@@ -421,7 +421,7 @@ static void make_duplis_frames(const DupliContext *ctx)
*ob = copyob;
}
-const DupliGenerator gen_dupli_frames = {
+static const DupliGenerator gen_dupli_frames = {
OB_DUPLIFRAMES, /* type */
make_duplis_frames /* make_duplis */
};
@@ -547,10 +547,15 @@ static void make_duplis_verts(const DupliContext *ctx)
BMEditMesh *em = BKE_editmesh_from_object(parent);
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH);
- if (em)
+ if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) {
+ vdd.dm = mesh_create_derived_render(scene, parent, dm_mask);
+ }
+ else if (em) {
vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask);
- else
+ }
+ else {
vdd.dm = mesh_get_derived_final(scene, parent, dm_mask);
+ }
vdd.edit_btmesh = me->edit_btmesh;
if (use_texcoords)
@@ -566,7 +571,7 @@ static void make_duplis_verts(const DupliContext *ctx)
vdd.dm->release(vdd.dm);
}
-const DupliGenerator gen_dupli_verts = {
+static const DupliGenerator gen_dupli_verts = {
OB_DUPLIVERTS, /* type */
make_duplis_verts /* make_duplis */
};
@@ -679,7 +684,7 @@ static void make_duplis_font(const DupliContext *ctx)
MEM_freeN(chartransdata);
}
-const DupliGenerator gen_dupli_verts_font = {
+static const DupliGenerator gen_dupli_verts_font = {
OB_DUPLIVERTS, /* type */
make_duplis_font /* make_duplis */
};
@@ -810,10 +815,15 @@ static void make_duplis_faces(const DupliContext *ctx)
BMEditMesh *em = BKE_editmesh_from_object(parent);
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH);
- if (em)
+ if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) {
+ fdd.dm = mesh_create_derived_render(scene, parent, dm_mask);
+ }
+ else if (em) {
fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask);
- else
+ }
+ else {
fdd.dm = mesh_get_derived_final(scene, parent, dm_mask);
+ }
if (use_texcoords) {
CustomData *ml_data = fdd.dm->getLoopDataLayout(fdd.dm);
@@ -837,7 +847,7 @@ static void make_duplis_faces(const DupliContext *ctx)
fdd.dm->release(fdd.dm);
}
-const DupliGenerator gen_dupli_faces = {
+static const DupliGenerator gen_dupli_faces = {
OB_DUPLIFACES, /* type */
make_duplis_faces /* make_duplis */
};
@@ -1158,7 +1168,7 @@ static void make_duplis_particles(const DupliContext *ctx)
}
}
-const DupliGenerator gen_dupli_particles = {
+static const DupliGenerator gen_dupli_particles = {
OB_DUPLIPARTS, /* type */
make_duplis_particles /* make_duplis */
};
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index a531466294e..e03af585cf2 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -145,18 +145,6 @@ void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob)
else ob->transflag &= ~OB_NEG_SCALE;
}
-void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob,
- struct ModifierData *md)
-{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
- (void) eval_ctx; /* Ignored. */
- (void) scene; /* Ignored. */
- (void) ob; /* Ignored. */
- (void) md; /* Ignored. */
-}
-
void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
Scene *scene,
Object *ob)
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 621ac9c2480..537c8926a5b 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -334,10 +334,10 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
i1 = i1 % oc->_M;
j1 = j1 % oc->_N;
-
#define BILERP(m) (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
frac_z))
+
{
if (oc->_do_disp_y) {
ocr->disp[1] = BILERP(oc->_disp_y);
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 64f90ef5c52..89f25136caf 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -522,6 +522,8 @@ static void unpack_generate_paths(
case ID_IM:
BLI_snprintf(r_relpath, relpathlen, "//textures/%s", tempname);
break;
+ default:
+ break;
}
{
@@ -712,6 +714,8 @@ bool BKE_pack_check(ID *id)
Library *li = (Library *)id;
return li->packedfile != NULL;
}
+ default:
+ break;
}
return false;
}
@@ -750,5 +754,7 @@ void BKE_unpack_id(Main *bmain, ID *id, ReportList *reports, int how)
BKE_reportf(reports, RPT_ERROR, "Cannot unpack individual Library file, '%s'", li->name);
break;
}
+ default:
+ break;
}
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index e56db89097d..24544e571d7 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -309,24 +309,31 @@ PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name)
{
PaintCurve *pc;
- pc = BKE_libblock_alloc(bmain, ID_PC, name);
+ pc = BKE_libblock_alloc(bmain, ID_PC, name, 0);
return pc;
}
-PaintCurve *BKE_paint_curve_copy(Main *bmain, PaintCurve *pc)
+/**
+ * Only copy internal data of PaintCurve ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_paint_curve_copy_data(Main *UNUSED(bmain), PaintCurve *pc_dst, const PaintCurve *pc_src, const int UNUSED(flag))
{
- PaintCurve *pc_new;
-
- pc_new = BKE_libblock_copy(bmain, &pc->id);
-
- if (pc->tot_points != 0) {
- pc_new->points = MEM_dupallocN(pc->points);
+ if (pc_src->tot_points != 0) {
+ pc_dst->points = MEM_dupallocN(pc_src->points);
}
+}
- BKE_id_copy_ensure_local(bmain, &pc->id, &pc_new->id);
-
- return pc_new;
+PaintCurve *BKE_paint_curve_copy(Main *bmain, const PaintCurve *pc)
+{
+ PaintCurve *pc_copy;
+ BKE_id_copy_ex(bmain, &pc->id, (ID **)&pc_copy, 0, false);
+ return pc_copy;
}
void BKE_paint_curve_make_local(Main *bmain, PaintCurve *pc, const bool lib_local)
@@ -388,7 +395,7 @@ Palette *BKE_palette_add(Main *bmain, const char *name)
{
Palette *palette;
- palette = BKE_libblock_alloc(bmain, ID_PAL, name);
+ palette = BKE_libblock_alloc(bmain, ID_PAL, name, 0);
/* enable fake user by default */
id_fake_user_set(&palette->id);
@@ -396,17 +403,24 @@ Palette *BKE_palette_add(Main *bmain, const char *name)
return palette;
}
-Palette *BKE_palette_copy(Main *bmain, Palette *palette)
+/**
+ * Only copy internal data of Palette ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_palette_copy_data(Main *UNUSED(bmain), Palette *palette_dst, const Palette *palette_src, const int UNUSED(flag))
{
- Palette *palette_new;
-
- palette_new = BKE_libblock_copy(bmain, &palette->id);
-
- BLI_duplicatelist(&palette_new->colors, &palette->colors);
-
- BKE_id_copy_ensure_local(bmain, &palette->id, &palette_new->id);
+ BLI_duplicatelist(&palette_dst->colors, &palette_src->colors);
+}
- return palette_new;
+Palette *BKE_palette_copy(Main *bmain, const Palette *palette)
+{
+ Palette *palette_copy;
+ BKE_id_copy_ex(bmain, &palette->id, (ID **)&palette_copy, 0, false);
+ return palette_copy;
}
void BKE_palette_make_local(Main *bmain, Palette *palette, const bool lib_local)
@@ -537,12 +551,15 @@ void BKE_paint_free(Paint *paint)
* still do a id_us_plus(), rather then if we were copying between 2 existing
* scenes where a matching value should decrease the existing user count as
* with paint_brush_set() */
-void BKE_paint_copy(Paint *src, Paint *tar)
+void BKE_paint_copy(Paint *src, Paint *tar, const int flag)
{
tar->brush = src->brush;
- id_us_plus((ID *)tar->brush);
- id_us_plus((ID *)tar->palette);
tar->cavity_curve = curvemapping_copy(src->cavity_curve);
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)tar->brush);
+ id_us_plus((ID *)tar->palette);
+ }
}
void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3])
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index bb5cea9dcc7..8c94cdfe784 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -253,11 +253,16 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData
if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
Object *lattice = NULL;
ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
+ int mode = G.is_rendering ? eModifierMode_Render : eModifierMode_Realtime;
for (; md; md = md->next) {
if (md->type == eModifierType_Lattice) {
- LatticeModifierData *lmd = (LatticeModifierData *)md;
- lattice = lmd->object;
+ if (md->mode & mode) {
+ LatticeModifierData *lmd = (LatticeModifierData *)md;
+ lattice = lmd->object;
+ sim->psys->lattice_strength = lmd->strength;
+ }
+
break;
}
}
@@ -590,7 +595,7 @@ void psys_free(Object *ob, ParticleSystem *psys)
BLI_bvhtree_free(psys->bvhtree);
BLI_kdtree_free(psys->tree);
-
+
if (psys->fluid_springs)
MEM_freeN(psys->fluid_springs);
@@ -2706,7 +2711,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
/* lattices have to be calculated separately to avoid mixups between effector calculations */
if (psys->lattice_deform_data) {
for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
- calc_latt_deform(psys->lattice_deform_data, ca->co, 1.0f);
+ calc_latt_deform(psys->lattice_deform_data, ca->co, psys->lattice_strength);
}
}
@@ -3295,7 +3300,7 @@ ParticleSettings *psys_new_settings(const char *name, Main *main)
if (main == NULL)
main = G.main;
- part = BKE_libblock_alloc(main, ID_PA, name);
+ part = BKE_libblock_alloc(main, ID_PA, name, 0);
default_particle_settings(part);
@@ -3326,38 +3331,45 @@ void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
part->roughcurve = cumap;
}
-ParticleSettings *BKE_particlesettings_copy(Main *bmain, ParticleSettings *part)
+/**
+ * Only copy internal data of ParticleSettings ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_particlesettings_copy_data(
+ Main *UNUSED(bmain), ParticleSettings *part_dst, const ParticleSettings *part_src, const int UNUSED(flag))
{
- ParticleSettings *partn;
- int a;
+ part_dst->pd = MEM_dupallocN(part_src->pd);
+ part_dst->pd2 = MEM_dupallocN(part_src->pd2);
+ part_dst->effector_weights = MEM_dupallocN(part_src->effector_weights);
+ part_dst->fluid = MEM_dupallocN(part_src->fluid);
- partn = BKE_libblock_copy(bmain, &part->id);
-
- partn->pd = MEM_dupallocN(part->pd);
- partn->pd2 = MEM_dupallocN(part->pd2);
- partn->effector_weights = MEM_dupallocN(part->effector_weights);
- partn->fluid = MEM_dupallocN(part->fluid);
+ if (part_src->clumpcurve) {
+ part_dst->clumpcurve = curvemapping_copy(part_src->clumpcurve);
+ }
+ if (part_src->roughcurve) {
+ part_dst->roughcurve = curvemapping_copy(part_src->roughcurve);
+ }
- if (part->clumpcurve)
- partn->clumpcurve = curvemapping_copy(part->clumpcurve);
- if (part->roughcurve)
- partn->roughcurve = curvemapping_copy(part->roughcurve);
-
- partn->boids = boid_copy_settings(part->boids);
+ part_dst->boids = boid_copy_settings(part_src->boids);
- for (a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- partn->mtex[a] = MEM_mallocN(sizeof(MTex), "psys_copy_tex");
- memcpy(partn->mtex[a], part->mtex[a], sizeof(MTex));
- id_us_plus((ID *)partn->mtex[a]->tex);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (part_src->mtex[a]) {
+ part_dst->mtex[a] = MEM_dupallocN(part_src->mtex[a]);
}
}
- BLI_duplicatelist(&partn->dupliweights, &part->dupliweights);
-
- BKE_id_copy_ensure_local(bmain, &part->id, &partn->id);
+ BLI_duplicatelist(&part_dst->dupliweights, &part_src->dupliweights);
+}
- return partn;
+ParticleSettings *BKE_particlesettings_copy(Main *bmain, const ParticleSettings *part)
+{
+ ParticleSettings *part_copy;
+ BKE_id_copy_ex(bmain, &part->id, (ID **)&part_copy, 0, false);
+ return part_copy;
}
void BKE_particlesettings_make_local(Main *bmain, ParticleSettings *part, const bool lib_local)
@@ -3369,7 +3381,8 @@ void BKE_particlesettings_make_local(Main *bmain, ParticleSettings *part, const
/* Textures */
/************************************************/
-static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, const float fuv[4], char *name, float *texco)
+static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int index, const float fuv[4],
+ char *name, float *texco, bool from_vert)
{
MFace *mf;
MTFace *tf;
@@ -3385,11 +3398,15 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co
if (pa) {
i = ELEM(pa->num_dmcache, DMCACHE_NOTFOUND, DMCACHE_ISCHILD) ? pa->num : pa->num_dmcache;
- if (i >= dm->getNumTessFaces(dm))
+ if ((!from_vert && i >= dm->getNumTessFaces(dm)) ||
+ (from_vert && i >= dm->getNumVerts(dm)))
+ {
i = -1;
+ }
+ }
+ else {
+ i = index;
}
- else
- i = face_index;
if (i == -1) {
texco[0] = 0.0f;
@@ -3397,7 +3414,22 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co
texco[2] = 0.0f;
}
else {
- mf = dm->getTessFaceData(dm, i, CD_MFACE);
+ if (from_vert) {
+ mf = dm->getTessFaceDataArray(dm, CD_MFACE);
+
+ /* This finds the first face to contain the emitting vertex,
+ * this is not ideal, but is mostly fine as UV seams generally
+ * map to equal-colored parts of a texture */
+ for (int j = 0; j < dm->getNumTessFaces(dm); j++, mf++) {
+ if (ELEM(i, mf->v1, mf->v2, mf->v3, mf->v4)) {
+ i = j;
+ break;
+ }
+ }
+ }
+ else {
+ mf = dm->getTessFaceData(dm, i, CD_MFACE);
+ }
psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco);
@@ -3464,8 +3496,11 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
mul_m4_v3(mtex->object->imat, texvec);
break;
case TEXCO_UV:
- if (fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec))
+ if (fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname,
+ texvec, (part->from == PART_FROM_VERT)))
+ {
break;
+ }
/* no break, failed to get uv's, so let's try orco's */
ATTR_FALLTHROUGH;
case TEXCO_ORCO:
@@ -3537,8 +3572,11 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
mul_m4_v3(mtex->object->imat, texvec);
break;
case TEXCO_UV:
- if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, texvec))
+ if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname,
+ texvec, (part->from == PART_FROM_VERT)))
+ {
break;
+ }
/* no break, failed to get uv's, so let's try orco's */
ATTR_FALLTHROUGH;
case TEXCO_ORCO:
@@ -3748,7 +3786,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
}
if (psys->lattice_deform_data && edit == 0)
- calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
+ calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength);
}
}
}
@@ -3987,7 +4025,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
do_child_modifiers(NULL, sim, NULL, key1->co, key1->vel, key1->rot, par_orco, cpa, cpa->fuv, mat, state, t);
if (psys->lattice_deform_data)
- calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
+ calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength);
}
else {
if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
@@ -4046,7 +4084,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
}
if (sim->psys->lattice_deform_data)
- calc_latt_deform(sim->psys->lattice_deform_data, state->co, 1.0f);
+ calc_latt_deform(sim->psys->lattice_deform_data, state->co, psys->lattice_strength);
}
return 1;
@@ -4293,7 +4331,7 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
hkey = pa->hair;
for (h = 0; h < pa->totkey; h++, hkey++) {
mul_m4_v3(hairmat, hkey->co);
- calc_latt_deform(psys->lattice_deform_data, hkey->co, 1.0f);
+ calc_latt_deform(psys->lattice_deform_data, hkey->co, psys->lattice_strength);
mul_m4_v3(imat, hkey->co);
}
}
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index 842de869291..bfcda89a635 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -355,9 +355,13 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
{
const float step_length = 1.0f / (float)(totkeys - 1);
-
float cur_length = 0.0f;
-
+
+ if (max_length <= 0.0f) {
+ keys->segments = -1;
+ totkeys = 0;
+ }
+
/* we have to correct velocity because of kink & clump */
for (k = 0, key = keys; k < totkeys; ++k, ++key) {
if (k >= 2) {
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 44cf5b119c1..ac9c60e8999 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -427,12 +427,37 @@ static int distribute_binary_search(float *sum, int n, float value)
static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p)
{
ParticleThreadContext *ctx= thread->ctx;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
+ MFace *mface;
+
+ mface = ctx->dm->getTessFaceDataArray(ctx->dm, CD_MFACE);
+
+ int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
/* TODO_PARTICLE - use original index */
- pa->num= ctx->index[p];
- pa->fuv[0] = 1.0f;
- pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
+ pa->num = ctx->index[p];
+
+ zero_v4(pa->fuv);
+
+ if (pa->num != DMCACHE_NOTFOUND && pa->num < ctx->dm->getNumVerts(ctx->dm)) {
+
+ /* This finds the first face to contain the emitting vertex,
+ * this is not ideal, but is mostly fine as UV seams generally
+ * map to equal-colored parts of a texture */
+ for (int i = 0; i < ctx->dm->getNumTessFaces(ctx->dm); i++, mface++) {
+ if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) {
+ unsigned int *vert = &mface->v1;
+
+ for (int j = 0; j < 4; j++, vert++) {
+ if (*vert == pa->num) {
+ pa->fuv[j] = 1.0f;
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+ }
#if ONLY_WORKING_WITH_PA_VERTS
if (ctx->tree) {
@@ -873,10 +898,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
else
dm= CDDM_from_mesh((Mesh*)ob->data);
- /* BMESH ONLY, for verts we don't care about tessfaces */
- if (from != PART_FROM_VERT) {
- DM_ensure_tessface(dm);
- }
+ DM_ensure_tessface(dm);
/* we need orco for consistent distributions */
if (!CustomData_has_layer(&dm->vertData, CD_ORCO))
@@ -1092,7 +1114,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* For hair, sort by origindex (allows optimization's in rendering), */
/* however with virtual parents the children need to be in random order. */
- if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) {
+ if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents != 0.0f)) {
int *orig_index = NULL;
if (from == PART_FROM_VERT) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 943dc781246..9ee456227e2 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -1000,7 +1000,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
part=psys->part;
/* get precise emitter matrix if particle is born */
- if (part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
+ if (part->type != PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
evaluate_emitter_anim(sim->scene, sim->ob, pa->time);
psys->flag |= PSYS_OB_ANIM_RESTORE;
@@ -1183,7 +1183,7 @@ static void set_keyed_keys(ParticleSimulationData *sim)
key->time = pa->time;
}
- if (psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f)
+ if (psys->flag & PSYS_KEYED_TIMING && pt->duration != 0.0f)
k++;
ksim.psys->flag |= keyed_flag;
@@ -3042,10 +3042,12 @@ static void hair_create_input_dm(ParticleSimulationData *sim, int totpoint, int
/* calculate maximum segment length */
max_length = 0.0f;
LOOP_PARTICLES {
- for (k=1, key=pa->hair+1; k<pa->totkey; k++,key++) {
- float length = len_v3v3(key->co, (key-1)->co);
- if (max_length < length)
- max_length = length;
+ if (!(pa->flag & PARS_UNEXIST)) {
+ for (k=1, key=pa->hair+1; k<pa->totkey; k++,key++) {
+ float length = len_v3v3(key->co, (key-1)->co);
+ if (max_length < length)
+ max_length = length;
+ }
}
}
@@ -3057,76 +3059,78 @@ static void hair_create_input_dm(ParticleSimulationData *sim, int totpoint, int
/* make vgroup for pin roots etc.. */
hair_index = 1;
LOOP_PARTICLES {
- float root_mat[4][4];
- float bending_stiffness;
- bool use_hair;
-
- pa->hair_index = hair_index;
- use_hair = psys_hair_use_simulation(pa, max_length);
-
- psys_mat_hair_to_object(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
- mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
- normalize_m4(root_mat);
-
- bending_stiffness = CLAMPIS(1.0f - part->bending_random * psys_frand(psys, p + 666), 0.0f, 1.0f);
-
- for (k=0, key=pa->hair; k<pa->totkey; k++,key++) {
- ClothHairData *hair;
- float *co, *co_next;
-
- co = key->co;
- co_next = (key+1)->co;
-
- /* create fake root before actual root to resist bending */
- if (k==0) {
- hair = &psys->clmd->hairdata[pa->hair_index - 1];
+ if (!(pa->flag & PARS_UNEXIST)) {
+ float root_mat[4][4];
+ float bending_stiffness;
+ bool use_hair;
+
+ pa->hair_index = hair_index;
+ use_hair = psys_hair_use_simulation(pa, max_length);
+
+ psys_mat_hair_to_object(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
+ mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
+ normalize_m4(root_mat);
+
+ bending_stiffness = CLAMPIS(1.0f - part->bending_random * psys_frand(psys, p + 666), 0.0f, 1.0f);
+
+ for (k=0, key=pa->hair; k<pa->totkey; k++,key++) {
+ ClothHairData *hair;
+ float *co, *co_next;
+
+ co = key->co;
+ co_next = (key+1)->co;
+
+ /* create fake root before actual root to resist bending */
+ if (k==0) {
+ hair = &psys->clmd->hairdata[pa->hair_index - 1];
+ copy_v3_v3(hair->loc, root_mat[3]);
+ copy_m3_m4(hair->rot, root_mat);
+
+ hair->radius = hair_radius;
+ hair->bending_stiffness = bending_stiffness;
+
+ add_v3_v3v3(mvert->co, co, co);
+ sub_v3_v3(mvert->co, co_next);
+ mul_m4_v3(hairmat, mvert->co);
+
+ medge->v1 = pa->hair_index - 1;
+ medge->v2 = pa->hair_index;
+
+ dvert = hair_set_pinning(dvert, 1.0f);
+
+ mvert++;
+ medge++;
+ }
+
+ /* store root transform in cloth data */
+ hair = &psys->clmd->hairdata[pa->hair_index + k];
copy_v3_v3(hair->loc, root_mat[3]);
copy_m3_m4(hair->rot, root_mat);
-
+
hair->radius = hair_radius;
hair->bending_stiffness = bending_stiffness;
-
- add_v3_v3v3(mvert->co, co, co);
- sub_v3_v3(mvert->co, co_next);
+
+ copy_v3_v3(mvert->co, co);
mul_m4_v3(hairmat, mvert->co);
-
- medge->v1 = pa->hair_index - 1;
- medge->v2 = pa->hair_index;
-
- dvert = hair_set_pinning(dvert, 1.0f);
-
+
+ if (k) {
+ medge->v1 = pa->hair_index + k - 1;
+ medge->v2 = pa->hair_index + k;
+ }
+
+ /* roots and disabled hairs should be 1.0, the rest can be anything from 0.0 to 1.0 */
+ if (use_hair)
+ dvert = hair_set_pinning(dvert, key->weight);
+ else
+ dvert = hair_set_pinning(dvert, 1.0f);
+
mvert++;
- medge++;
+ if (k)
+ medge++;
}
-
- /* store root transform in cloth data */
- hair = &psys->clmd->hairdata[pa->hair_index + k];
- copy_v3_v3(hair->loc, root_mat[3]);
- copy_m3_m4(hair->rot, root_mat);
-
- hair->radius = hair_radius;
- hair->bending_stiffness = bending_stiffness;
-
- copy_v3_v3(mvert->co, co);
- mul_m4_v3(hairmat, mvert->co);
-
- if (k) {
- medge->v1 = pa->hair_index + k - 1;
- medge->v2 = pa->hair_index + k;
- }
-
- /* roots and disabled hairs should be 1.0, the rest can be anything from 0.0 to 1.0 */
- if (use_hair)
- dvert = hair_set_pinning(dvert, key->weight);
- else
- dvert = hair_set_pinning(dvert, 1.0f);
-
- mvert++;
- if (k)
- medge++;
+
+ hair_index += pa->totkey + 1;
}
-
- hair_index += pa->totkey + 1;
}
}
@@ -3152,9 +3156,11 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
totpoint = 0;
totedge = 0;
LOOP_PARTICLES {
- /* "out" dm contains all hairs */
- totedge += pa->totkey;
- totpoint += pa->totkey + 1; /* +1 for virtual root point */
+ if (!(pa->flag & PARS_UNEXIST)) {
+ /* "out" dm contains all hairs */
+ totedge += pa->totkey;
+ totpoint += pa->totkey + 1; /* +1 for virtual root point */
+ }
}
realloc_roots = false; /* whether hair root info array has to be reallocated */
@@ -4350,13 +4356,12 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
/* **** Depsgraph evaluation **** */
-void BKE_particle_system_eval(EvaluationContext *UNUSED(eval_ctx),
- Scene *scene,
- Object *ob,
- ParticleSystem *psys)
+void BKE_particle_system_eval_init(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob)
{
if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s:%s\n", __func__, ob->id.name, psys->name);
+ printf("%s on %s\n", __func__, ob->id.name);
}
BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 549b0293bd1..f6d53075bf0 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1118,7 +1118,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
GPU_pbvh_bmesh_buffers_build(bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING);
break;
}
-
+
node->flag &= ~PBVH_RebuildDrawBuffers;
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index a7e00a8103a..7a1b378b3c4 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3449,7 +3449,7 @@ void BKE_ptcache_free_list(ListBase *ptcaches)
}
}
-static PointCache *ptcache_copy(PointCache *cache, bool copy_data)
+static PointCache *ptcache_copy(PointCache *cache, const bool copy_data)
{
PointCache *ncache;
@@ -3492,14 +3492,15 @@ static PointCache *ptcache_copy(PointCache *cache, bool copy_data)
}
/* returns first point cache */
-PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcaches_old, bool copy_data)
+PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcaches_old, const int flag)
{
PointCache *cache = ptcaches_old->first;
BLI_listbase_clear(ptcaches_new);
- for (; cache; cache=cache->next)
- BLI_addtail(ptcaches_new, ptcache_copy(cache, copy_data));
+ for (; cache; cache=cache->next) {
+ BLI_addtail(ptcaches_new, ptcache_copy(cache, (flag & LIB_ID_COPY_CACHES) != 0));
+ }
return ptcaches_new->first;
}
@@ -3618,7 +3619,13 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
}
- if (((cache->flag & PTCACHE_BAKED) == 0) && (render || bake)) {
+ // XXX workaround for regression inroduced in ee3fadd, needs looking into
+ if (pid->type == PTCACHE_TYPE_RIGIDBODY) {
+ if ((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) && (render || bake)) {
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+ }
+ }
+ else if (((cache->flag & PTCACHE_BAKED) == 0) && (render || bake)) {
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
}
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index dc4063b42ed..b163f623d21 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -65,7 +65,7 @@ void BKE_bproperty_free_list(ListBase *lb)
}
}
-bProperty *BKE_bproperty_copy(bProperty *prop)
+bProperty *BKE_bproperty_copy(const bProperty *prop)
{
bProperty *propn;
@@ -80,7 +80,7 @@ bProperty *BKE_bproperty_copy(bProperty *prop)
return propn;
}
-void BKE_bproperty_copy_list(ListBase *lbn, ListBase *lbo)
+void BKE_bproperty_copy_list(ListBase *lbn, const ListBase *lbo)
{
bProperty *prop, *propn;
BKE_bproperty_free_list(lbn); /* in case we are copying to an object with props */
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index b3a36bfb089..03eb83376e7 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -184,7 +184,7 @@ void BKE_rigidbody_free_constraint(Object *ob)
* be added to relevant groups later...
*/
-RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
+RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int UNUSED(flag))
{
RigidBodyOb *rboN = NULL;
@@ -204,7 +204,7 @@ RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
return rboN;
}
-RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob)
+RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int UNUSED(flag))
{
RigidBodyCon *rbcN = NULL;
@@ -291,8 +291,6 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
if (dm == NULL)
return NULL;
- DM_ensure_looptri(dm);
-
mvert = dm->getVertArray(dm);
totvert = dm->getNumVerts(dm);
looptri = dm->getLoopTriArray(dm);
@@ -524,8 +522,6 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
if (dm == NULL)
return;
- DM_ensure_looptri(dm);
-
mvert = dm->getVertArray(dm);
totvert = dm->getNumVerts(dm);
lt = dm->getLoopTriArray(dm);
@@ -609,8 +605,6 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
if (dm == NULL)
return;
- DM_ensure_looptri(dm);
-
mvert = dm->getVertArray(dm);
totvert = dm->getNumVerts(dm);
looptri = dm->getLoopTriArray(dm);
@@ -945,24 +939,26 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
return rbw;
}
-RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw)
+RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw, const int flag)
{
- RigidBodyWorld *rbwn = MEM_dupallocN(rbw);
+ RigidBodyWorld *rbw_copy = MEM_dupallocN(rbw);
- if (rbw->effector_weights)
- rbwn->effector_weights = MEM_dupallocN(rbw->effector_weights);
- if (rbwn->group)
- id_us_plus(&rbwn->group->id);
- if (rbwn->constraints)
- id_us_plus(&rbwn->constraints->id);
+ if (rbw->effector_weights) {
+ rbw_copy->effector_weights = MEM_dupallocN(rbw->effector_weights);
+ }
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)rbw_copy->group);
+ id_us_plus((ID *)rbw_copy->constraints);
+ }
- rbwn->pointcache = BKE_ptcache_copy_list(&rbwn->ptcaches, &rbw->ptcaches, false);
+ /* XXX Never copy caches here? */
+ rbw_copy->pointcache = BKE_ptcache_copy_list(&rbw_copy->ptcaches, &rbw->ptcaches, flag & ~LIB_ID_COPY_CACHES);
- rbwn->objects = NULL;
- rbwn->physics_world = NULL;
- rbwn->numbodies = 0;
+ rbw_copy->objects = NULL;
+ rbw_copy->physics_world = NULL;
+ rbw_copy->numbodies = 0;
- return rbwn;
+ return rbw_copy;
}
void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw)
@@ -1486,24 +1482,60 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
{
RigidBodyOb *rbo = ob->rigidbody_object;
+ bool correct_delta = !(rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE);
/* return rigid body and object to their initial states */
copy_v3_v3(rbo->pos, ob->loc);
copy_v3_v3(ob->loc, loc);
+ if (correct_delta) {
+ add_v3_v3(rbo->pos, ob->dloc);
+ }
+
if (ob->rotmode > 0) {
- eulO_to_quat(rbo->orn, ob->rot, ob->rotmode);
+ float qt[4];
+ eulO_to_quat(qt, ob->rot, ob->rotmode);
+
+ if (correct_delta) {
+ float dquat[4];
+ eulO_to_quat(dquat, ob->drot, ob->rotmode);
+
+ mul_qt_qtqt(rbo->orn, dquat, qt);
+ }
+ else {
+ copy_qt_qt(rbo->orn, qt);
+ }
+
copy_v3_v3(ob->rot, rot);
}
else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_quat(rbo->orn, ob->rotAxis, ob->rotAngle);
+ float qt[4];
+ axis_angle_to_quat(qt, ob->rotAxis, ob->rotAngle);
+
+ if (correct_delta) {
+ float dquat[4];
+ axis_angle_to_quat(dquat, ob->drotAxis, ob->drotAngle);
+
+ mul_qt_qtqt(rbo->orn, dquat, qt);
+ }
+ else {
+ copy_qt_qt(rbo->orn, qt);
+ }
+
copy_v3_v3(ob->rotAxis, rotAxis);
ob->rotAngle = rotAngle;
}
else {
- copy_qt_qt(rbo->orn, ob->quat);
+ if (correct_delta) {
+ mul_qt_qtqt(rbo->orn, ob->dquat, ob->quat);
+ }
+ else {
+ copy_qt_qt(rbo->orn, ob->quat);
+ }
+
copy_qt_qt(ob->quat, quat);
}
+
if (rbo->physics_object) {
/* allow passive objects to return to original transform */
if (rbo->type == RBO_TYPE_PASSIVE)
@@ -1515,8 +1547,9 @@ void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], flo
void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
{
- if (rbw)
+ if (rbw) {
rbw->pointcache->flag |= PTCACHE_OUTDATED;
+ }
}
/* ------------------ */
@@ -1582,7 +1615,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
// RB_TODO deal with interpolated, old and baked results
bool can_simulate = (ctime == rbw->ltime + 1) && !(cache->flag & PTCACHE_BAKED);
- if (BKE_ptcache_read(&pid, ctime, can_simulate)) {
+ if (BKE_ptcache_read(&pid, ctime, can_simulate) == PTCACHE_READ_EXACT) {
BKE_ptcache_validate(cache, (int)ctime);
rbw->ltime = ctime;
return;
@@ -1622,13 +1655,13 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
# pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
-struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; }
-struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; }
+struct RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag) { return NULL; }
+struct RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int flag) { return NULL; }
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {}
void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) { if (r_vol) *r_vol = 0.0f; }
void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3]) { zero_v3(r_center); }
struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; }
-struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; }
+struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw, const int flag) { return NULL; }
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {}
void BKE_rigidbody_world_id_loop(struct RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata) {}
struct RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) { return NULL; }
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 7920d8b5696..fb81ed4d47f 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -72,7 +72,7 @@ void free_sensors(ListBase *lb)
}
}
-bSensor *copy_sensor(bSensor *sens)
+bSensor *copy_sensor(bSensor *sens, const int UNUSED(flag))
{
bSensor *sensn;
@@ -87,14 +87,14 @@ bSensor *copy_sensor(bSensor *sens)
return sensn;
}
-void copy_sensors(ListBase *lbn, ListBase *lbo)
+void copy_sensors(ListBase *lbn, const ListBase *lbo, const int flag)
{
bSensor *sens, *sensn;
lbn->first= lbn->last= NULL;
sens= lbo->first;
while (sens) {
- sensn= copy_sensor(sens);
+ sensn= copy_sensor(sens, flag);
BLI_addtail(lbn, sensn);
sens= sens->next;
}
@@ -234,7 +234,7 @@ void free_controllers(ListBase *lb)
}
}
-bController *copy_controller(bController *cont)
+bController *copy_controller(bController *cont, const int UNUSED(flag))
{
bController *contn;
@@ -251,14 +251,14 @@ bController *copy_controller(bController *cont)
return contn;
}
-void copy_controllers(ListBase *lbn, ListBase *lbo)
+void copy_controllers(ListBase *lbn, const ListBase *lbo, const int flag)
{
bController *cont, *contn;
lbn->first= lbn->last= NULL;
cont= lbo->first;
while (cont) {
- contn= copy_controller(cont);
+ contn= copy_controller(cont, flag);
BLI_addtail(lbn, contn);
cont= cont->next;
}
@@ -359,7 +359,7 @@ void free_actuators(ListBase *lb)
}
}
-bActuator *copy_actuator(bActuator *act)
+bActuator *copy_actuator(bActuator *act, const int flag)
{
bActuator *actn;
@@ -374,29 +374,31 @@ bActuator *copy_actuator(bActuator *act)
case ACT_SHAPEACTION:
{
bActionActuator *aa = (bActionActuator *)act->data;
- if (aa->act)
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
id_us_plus((ID *)aa->act);
+ }
break;
}
case ACT_SOUND:
{
bSoundActuator *sa = (bSoundActuator *)act->data;
- if (sa->sound)
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
id_us_plus((ID *)sa->sound);
+ }
break;
}
}
return actn;
}
-void copy_actuators(ListBase *lbn, ListBase *lbo)
+void copy_actuators(ListBase *lbn, const ListBase *lbo, const int flag)
{
bActuator *act, *actn;
lbn->first= lbn->last= NULL;
act= lbo->first;
while (act) {
- actn= copy_actuator(act);
+ actn= copy_actuator(act, flag);
BLI_addtail(lbn, actn);
act= act->next;
}
@@ -783,11 +785,11 @@ void BKE_sca_logic_links_remap(Main *bmain, Object *ob_old, Object *ob_new)
* Handle the copying of logic data into a new object, including internal logic links update.
* External links (links between logic bricks of different objects) must be handled separately.
*/
-void BKE_sca_logic_copy(Object *ob_new, Object *ob)
+void BKE_sca_logic_copy(Object *ob_new, const Object *ob, const int flag)
{
- copy_sensors(&ob_new->sensors, &ob->sensors);
- copy_controllers(&ob_new->controllers, &ob->controllers);
- copy_actuators(&ob_new->actuators, &ob->actuators);
+ copy_sensors(&ob_new->sensors, &ob->sensors, flag);
+ copy_controllers(&ob_new->controllers, &ob->controllers, flag);
+ copy_actuators(&ob_new->actuators, &ob->actuators, flag);
for (bSensor *sens = ob_new->sensors.first; sens; sens = sens->next) {
if (sens->flag & SENS_NEW) {
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 5933aaccd66..b8ad54dc533 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -154,213 +154,316 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
-Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
-{
- Scene *scen;
- SceneRenderLayer *srl, *new_srl;
- FreestyleLineSet *lineset;
- ToolSettings *ts;
- Base *base, *obase;
-
- if (type == SCE_COPY_EMPTY) {
- ListBase rl, rv;
- scen = BKE_scene_add(bmain, sce->id.name + 2);
-
- rl = scen->r.layers;
- rv = scen->r.views;
- curvemapping_free_data(&scen->r.mblur_shutter_curve);
- scen->r = sce->r;
- scen->r.layers = rl;
- scen->r.actlay = 0;
- scen->r.views = rv;
- scen->unit = sce->unit;
- scen->physics_settings = sce->physics_settings;
- scen->gm = sce->gm;
- scen->audio = sce->audio;
-
- if (sce->id.properties)
- scen->id.properties = IDP_CopyProperty(sce->id.properties);
-
- MEM_freeN(scen->toolsettings);
- BKE_sound_destroy_scene(scen);
- }
- else {
- scen = BKE_libblock_copy(bmain, &sce->id);
- BLI_duplicatelist(&(scen->base), &(sce->base));
-
- id_us_plus((ID *)scen->world);
- id_us_plus((ID *)scen->set);
- /* id_us_plus((ID *)scen->gm.dome.warptext); */ /* XXX Not refcounted? see readfile.c */
-
- scen->ed = NULL;
- scen->theDag = NULL;
- scen->depsgraph = NULL;
- scen->obedit = NULL;
- scen->stats = NULL;
- scen->fps_info = NULL;
-
- if (sce->rigidbody_world)
- scen->rigidbody_world = BKE_rigidbody_world_copy(sce->rigidbody_world);
-
- BLI_duplicatelist(&(scen->markers), &(sce->markers));
- BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces));
- BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers));
- BLI_duplicatelist(&(scen->r.views), &(sce->r.views));
- BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets));
-
- if (sce->nodetree) {
- /* ID's are managed on both copy and switch */
- scen->nodetree = ntreeCopyTree(bmain, sce->nodetree);
- BKE_libblock_relink_ex(bmain, scen->nodetree, &sce->id, &scen->id, false);
+/**
+ * Only copy internal data of Scene ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, const int flag)
+{
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+
+ sce_dst->ed = NULL;
+ sce_dst->theDag = NULL;
+ sce_dst->depsgraph = NULL;
+ sce_dst->obedit = NULL;
+ sce_dst->stats = NULL;
+ sce_dst->fps_info = NULL;
+
+ BLI_duplicatelist(&(sce_dst->base), &(sce_src->base));
+ for (Base *base_dst = sce_dst->base.first, *base_src = sce_src->base.first;
+ base_dst;
+ base_dst = base_dst->next, base_src = base_src->next)
+ {
+ if (base_src == sce_src->basact) {
+ sce_dst->basact = base_dst;
}
+ }
- obase = sce->base.first;
- base = scen->base.first;
- while (base) {
- id_us_plus(&base->object->id);
- if (obase == sce->basact) scen->basact = base;
-
- obase = obase->next;
- base = base->next;
- }
+ BLI_duplicatelist(&(sce_dst->markers), &(sce_src->markers));
+ BLI_duplicatelist(&(sce_dst->transform_spaces), &(sce_src->transform_spaces));
+ BLI_duplicatelist(&(sce_dst->r.layers), &(sce_src->r.layers));
+ BLI_duplicatelist(&(sce_dst->r.views), &(sce_src->r.views));
+ BKE_keyingsets_copy(&(sce_dst->keyingsets), &(sce_src->keyingsets));
- /* copy action and remove animation used by sequencer */
- BKE_animdata_copy_id_action(&scen->id, false);
+ if (sce_src->nodetree) {
+ BKE_id_copy_ex(bmain, (ID *)sce_src->nodetree, (ID **)&sce_dst->nodetree, flag, false);
+ BKE_libblock_relink_ex(bmain, sce_dst->nodetree, (void *)(&sce_src->id), &sce_dst->id, false);
+ }
- if (type != SCE_COPY_FULL)
- remove_sequencer_fcurves(scen);
+ if (sce_src->rigidbody_world) {
+ sce_dst->rigidbody_world = BKE_rigidbody_world_copy(sce_src->rigidbody_world, flag_subdata);
+ }
- /* copy Freestyle settings */
- new_srl = scen->r.layers.first;
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- if (new_srl->prop != NULL) {
- new_srl->prop = IDP_CopyProperty(new_srl->prop);
- }
- BKE_freestyle_config_copy(&new_srl->freestyleConfig, &srl->freestyleConfig);
- if (type == SCE_COPY_FULL) {
- for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
- if (lineset->linestyle) {
- id_us_plus((ID *)lineset->linestyle);
- lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
- }
- }
- }
- new_srl = new_srl->next;
+ /* copy Freestyle settings */
+ for (SceneRenderLayer *srl_dst = sce_dst->r.layers.first, *srl_src = sce_src->r.layers.first;
+ srl_src;
+ srl_dst = srl_dst->next, srl_src = srl_src->next)
+ {
+ if (srl_dst->prop != NULL) {
+ srl_dst->prop = IDP_CopyProperty_ex(srl_dst->prop, flag_subdata);
}
+ BKE_freestyle_config_copy(&srl_dst->freestyleConfig, &srl_src->freestyleConfig, flag_subdata);
}
/* copy color management settings */
- BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings);
- BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings);
- BKE_color_managed_colorspace_settings_copy(&scen->sequencer_colorspace_settings, &sce->sequencer_colorspace_settings);
+ BKE_color_managed_display_settings_copy(&sce_dst->display_settings, &sce_src->display_settings);
+ BKE_color_managed_view_settings_copy(&sce_dst->view_settings, &sce_src->view_settings);
+ BKE_color_managed_colorspace_settings_copy(&sce_dst->sequencer_colorspace_settings, &sce_src->sequencer_colorspace_settings);
- BKE_color_managed_display_settings_copy(&scen->r.im_format.display_settings, &sce->r.im_format.display_settings);
- BKE_color_managed_view_settings_copy(&scen->r.im_format.view_settings, &sce->r.im_format.view_settings);
+ BKE_color_managed_display_settings_copy(&sce_dst->r.im_format.display_settings, &sce_src->r.im_format.display_settings);
+ BKE_color_managed_view_settings_copy(&sce_dst->r.im_format.view_settings, &sce_src->r.im_format.view_settings);
- BKE_color_managed_display_settings_copy(&scen->r.bake.im_format.display_settings, &sce->r.bake.im_format.display_settings);
- BKE_color_managed_view_settings_copy(&scen->r.bake.im_format.view_settings, &sce->r.bake.im_format.view_settings);
+ BKE_color_managed_display_settings_copy(&sce_dst->r.bake.im_format.display_settings, &sce_src->r.bake.im_format.display_settings);
+ BKE_color_managed_view_settings_copy(&sce_dst->r.bake.im_format.view_settings, &sce_src->r.bake.im_format.view_settings);
- curvemapping_copy_data(&scen->r.mblur_shutter_curve, &sce->r.mblur_shutter_curve);
+ curvemapping_copy_data(&sce_dst->r.mblur_shutter_curve, &sce_src->r.mblur_shutter_curve);
/* tool settings */
- scen->toolsettings = MEM_dupallocN(sce->toolsettings);
-
- ts = scen->toolsettings;
- if (ts) {
+ if (sce_dst->toolsettings != NULL) {
+ ToolSettings *ts = sce_dst->toolsettings = MEM_dupallocN(sce_dst->toolsettings);
if (ts->vpaint) {
ts->vpaint = MEM_dupallocN(ts->vpaint);
ts->vpaint->paintcursor = NULL;
ts->vpaint->vpaint_prev = NULL;
ts->vpaint->wpaint_prev = NULL;
- BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint);
+ BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag_subdata);
}
if (ts->wpaint) {
ts->wpaint = MEM_dupallocN(ts->wpaint);
ts->wpaint->paintcursor = NULL;
ts->wpaint->vpaint_prev = NULL;
ts->wpaint->wpaint_prev = NULL;
- BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint);
+ BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag_subdata);
}
if (ts->sculpt) {
ts->sculpt = MEM_dupallocN(ts->sculpt);
- BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint);
+ BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag_subdata);
+ }
+ if (ts->uvsculpt) {
+ ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
+ BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag_subdata);
}
- BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint);
+ BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag_subdata);
ts->imapaint.paintcursor = NULL;
- id_us_plus((ID *)ts->imapaint.stencil);
ts->particle.paintcursor = NULL;
-
+ ts->particle.scene = NULL;
+ ts->particle.object = NULL;
+
/* duplicate Grease Pencil Drawing Brushes */
BLI_listbase_clear(&ts->gp_brushes);
- for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) {
+ for (bGPDbrush *brush = sce_src->toolsettings->gp_brushes.first; brush; brush = brush->next) {
bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
BLI_addtail(&ts->gp_brushes, newbrush);
}
-
+
/* duplicate Grease Pencil interpolation curve */
ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
}
-
+
/* make a private copy of the avicodecdata */
- if (sce->r.avicodecdata) {
- scen->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata);
- scen->r.avicodecdata->lpFormat = MEM_dupallocN(scen->r.avicodecdata->lpFormat);
- scen->r.avicodecdata->lpParms = MEM_dupallocN(scen->r.avicodecdata->lpParms);
+ if (sce_src->r.avicodecdata) {
+ sce_dst->r.avicodecdata = MEM_dupallocN(sce_src->r.avicodecdata);
+ sce_dst->r.avicodecdata->lpFormat = MEM_dupallocN(sce_dst->r.avicodecdata->lpFormat);
+ sce_dst->r.avicodecdata->lpParms = MEM_dupallocN(sce_dst->r.avicodecdata->lpParms);
}
-
+
/* make a private copy of the qtcodecdata */
- if (sce->r.qtcodecdata) {
- scen->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata);
- scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms);
+ if (sce_src->r.qtcodecdata) {
+ sce_dst->r.qtcodecdata = MEM_dupallocN(sce_src->r.qtcodecdata);
+ sce_dst->r.qtcodecdata->cdParms = MEM_dupallocN(sce_dst->r.qtcodecdata->cdParms);
}
-
- if (sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */
- scen->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties);
+
+ if (sce_src->r.ffcodecdata.properties) { /* intentionally check sce_dst not sce_src. */ /* XXX ??? comment outdated... */
+ sce_dst->r.ffcodecdata.properties = IDP_CopyProperty_ex(sce_src->r.ffcodecdata.properties, flag_subdata);
}
- /* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations
- * are done outside of blenkernel with ED_objects_single_users! */
+ /* before scene copy */
+ BKE_sound_create_scene(sce_dst);
- /* camera */
- if (type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) {
- ID_NEW_REMAP(scen->camera);
+ /* Copy sequencer, this is local data! */
+ if (sce_src->ed) {
+ sce_dst->ed = MEM_callocN(sizeof(*sce_dst->ed), __func__);
+ sce_dst->ed->seqbasep = &sce_dst->ed->seqbase;
+ BKE_sequence_base_dupli_recursive(
+ sce_src, sce_dst, &sce_dst->ed->seqbase, &sce_src->ed->seqbase, SEQ_DUPE_ALL, flag_subdata);
}
-
- /* before scene copy */
- BKE_sound_create_scene(scen);
- /* world */
- if (type == SCE_COPY_FULL) {
- if (scen->world) {
- id_us_plus((ID *)scen->world);
- scen->world = BKE_world_copy(bmain, scen->world);
- BKE_animdata_copy_id_action((ID *)scen->world, false);
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
+ BKE_previewimg_id_copy(&sce_dst->id, &sce_src->id);
+ }
+ else {
+ sce_dst->preview = NULL;
+ }
+}
+
+Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
+{
+ Scene *sce_copy;
+
+ /* TODO this should/could most likely be replaced by call to more generic code at some point...
+ * But for now, let's keep it well isolated here. */
+ if (type == SCE_COPY_EMPTY) {
+ ToolSettings *ts;
+ ListBase rl, rv;
+
+ sce_copy = BKE_scene_add(bmain, sce->id.name + 2);
+
+ rl = sce_copy->r.layers;
+ rv = sce_copy->r.views;
+ curvemapping_free_data(&sce_copy->r.mblur_shutter_curve);
+ sce_copy->r = sce->r;
+ sce_copy->r.layers = rl;
+ sce_copy->r.actlay = 0;
+ sce_copy->r.views = rv;
+ sce_copy->unit = sce->unit;
+ sce_copy->physics_settings = sce->physics_settings;
+ sce_copy->gm = sce->gm;
+ sce_copy->audio = sce->audio;
+
+ if (sce->id.properties)
+ sce_copy->id.properties = IDP_CopyProperty(sce->id.properties);
+
+ MEM_freeN(sce_copy->toolsettings);
+ BKE_sound_destroy_scene(sce_copy);
+
+ /* copy color management settings */
+ BKE_color_managed_display_settings_copy(&sce_copy->display_settings, &sce->display_settings);
+ BKE_color_managed_view_settings_copy(&sce_copy->view_settings, &sce->view_settings);
+ BKE_color_managed_colorspace_settings_copy(&sce_copy->sequencer_colorspace_settings, &sce->sequencer_colorspace_settings);
+
+ BKE_color_managed_display_settings_copy(&sce_copy->r.im_format.display_settings, &sce->r.im_format.display_settings);
+ BKE_color_managed_view_settings_copy(&sce_copy->r.im_format.view_settings, &sce->r.im_format.view_settings);
+
+ BKE_color_managed_display_settings_copy(&sce_copy->r.bake.im_format.display_settings, &sce->r.bake.im_format.display_settings);
+ BKE_color_managed_view_settings_copy(&sce_copy->r.bake.im_format.view_settings, &sce->r.bake.im_format.view_settings);
+
+ curvemapping_copy_data(&sce_copy->r.mblur_shutter_curve, &sce->r.mblur_shutter_curve);
+
+ /* tool settings */
+ sce_copy->toolsettings = MEM_dupallocN(sce->toolsettings);
+
+ ts = sce_copy->toolsettings;
+ if (ts) {
+ if (ts->vpaint) {
+ ts->vpaint = MEM_dupallocN(ts->vpaint);
+ ts->vpaint->paintcursor = NULL;
+ ts->vpaint->vpaint_prev = NULL;
+ ts->vpaint->wpaint_prev = NULL;
+ BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, 0);
+ }
+ if (ts->wpaint) {
+ ts->wpaint = MEM_dupallocN(ts->wpaint);
+ ts->wpaint->paintcursor = NULL;
+ ts->wpaint->vpaint_prev = NULL;
+ ts->wpaint->wpaint_prev = NULL;
+ BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, 0);
+ }
+ if (ts->sculpt) {
+ ts->sculpt = MEM_dupallocN(ts->sculpt);
+ BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, 0);
+ }
+ if (ts->uvsculpt) {
+ ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
+ BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, 0);
+ }
+
+ BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, 0);
+ ts->imapaint.paintcursor = NULL;
+ id_us_plus((ID *)ts->imapaint.stencil);
+ id_us_plus((ID *)ts->imapaint.clone);
+ id_us_plus((ID *)ts->imapaint.canvas);
+ ts->particle.paintcursor = NULL;
+ ts->particle.scene = NULL;
+ ts->particle.object = NULL;
+
+ /* 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 = BKE_gpencil_brush_duplicate(brush);
+ BLI_addtail(&ts->gp_brushes, newbrush);
+ }
+
+ /* duplicate Grease Pencil interpolation curve */
+ ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
+ }
+
+ /* make a private copy of the avicodecdata */
+ if (sce->r.avicodecdata) {
+ sce_copy->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata);
+ sce_copy->r.avicodecdata->lpFormat = MEM_dupallocN(sce_copy->r.avicodecdata->lpFormat);
+ sce_copy->r.avicodecdata->lpParms = MEM_dupallocN(sce_copy->r.avicodecdata->lpParms);
+ }
+
+ /* make a private copy of the qtcodecdata */
+ if (sce->r.qtcodecdata) {
+ sce_copy->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata);
+ sce_copy->r.qtcodecdata->cdParms = MEM_dupallocN(sce_copy->r.qtcodecdata->cdParms);
}
- if (sce->ed) {
- scen->ed = MEM_callocN(sizeof(Editing), "addseq");
- scen->ed->seqbasep = &scen->ed->seqbase;
- BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL);
+ if (sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */
+ sce_copy->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties);
}
+
+ /* before scene copy */
+ BKE_sound_create_scene(sce_copy);
+
+ /* grease pencil */
+ sce_copy->gpd = NULL;
+
+ sce_copy->preview = NULL;
+
+ return sce_copy;
}
-
- /* grease pencil */
- if (scen->gpd) {
+ else {
+ BKE_id_copy_ex(bmain, (ID *)sce, (ID **)&sce_copy, LIB_ID_COPY_ACTIONS, false);
+
+ /* Extra actions, most notably SCE_FULL_COPY also duplicates several 'children' datablocks... */
+
if (type == SCE_COPY_FULL) {
- scen->gpd = BKE_gpencil_data_duplicate(bmain, scen->gpd, false);
- }
- else if (type == SCE_COPY_EMPTY) {
- scen->gpd = NULL;
+ /* Copy Freestyle LineStyle datablocks. */
+ for (SceneRenderLayer *srl_dst = sce_copy->r.layers.first; srl_dst; srl_dst = srl_dst->next) {
+ for (FreestyleLineSet *lineset = srl_dst->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->linestyle) {
+ /* XXX Not copying anim/actions here? */
+ BKE_id_copy_ex(bmain, (ID *)lineset->linestyle, (ID **)&lineset->linestyle, 0, false);
+ }
+ }
+ }
+
+ /* Full copy of world (included animations) */
+ if (sce_copy->world) {
+ BKE_id_copy_ex(bmain, (ID *)sce_copy->world, (ID **)&sce_copy->world, LIB_ID_COPY_ACTIONS, false);
+ }
+
+ /* Full copy of GreasePencil. */
+ /* XXX Not copying anim/actions here? */
+ if (sce_copy->gpd) {
+ BKE_id_copy_ex(bmain, (ID *)sce_copy->gpd, (ID **)&sce_copy->gpd, 0, false);
+ }
}
else {
- id_us_plus((ID *)scen->gpd);
+ /* Remove sequencer if not full copy */
+ /* XXX Why in Hell? :/ */
+ remove_sequencer_fcurves(sce_copy);
+ BKE_sequencer_editing_free(sce_copy);
}
- }
- BKE_previewimg_id_copy(&scen->id, &sce->id);
+ /* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations
+ * are done outside of blenkernel with ED_objects_single_users! */
+
+ /* camera */
+ if (ELEM(type, SCE_COPY_LINK_DATA, SCE_COPY_FULL)) {
+ ID_NEW_REMAP(sce_copy->camera);
+ }
- return scen;
+ return sce_copy;
+ }
}
void BKE_scene_groups_relink(Scene *sce)
@@ -573,7 +676,7 @@ void BKE_scene_init(Scene *sce)
sce->r.seq_prev_type = OB_SOLID;
sce->r.seq_rend_type = OB_SOLID;
- sce->r.seq_flag = R_SEQ_GL_PREV;
+ sce->r.seq_flag = 0;
sce->r.threads = 1;
@@ -833,7 +936,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
{
Scene *sce;
- sce = BKE_libblock_alloc(bmain, ID_SCE, name);
+ sce = BKE_libblock_alloc(bmain, ID_SCE, name, 0);
id_us_min(&sce->id);
id_us_ensure_real(&sce->id);
@@ -2137,7 +2240,7 @@ bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv)
int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
{
- if (r->mode & R_SIMPLIFY) {
+ if (r->mode & R_SIMPLIFY) {
if (for_render)
return min_ii(r->simplify_subsurf_render, lvl);
else
@@ -2308,6 +2411,14 @@ int BKE_scene_num_threads(const Scene *scene)
return BKE_render_num_threads(&scene->r);
}
+int BKE_render_preview_pixel_size(const RenderData *r)
+{
+ if (r->preview_pixel_size == 0) {
+ return (U.pixelsize > 1.5f)? 2 : 1;
+ }
+ return r->preview_pixel_size;
+}
+
/* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently)
* and unit->scale_length.
*/
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 857bd5447c8..df47b89fadc 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -181,6 +181,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
BLI_listbase_clear(&newar->ui_lists);
newar->swinid = 0;
newar->regiontimer = NULL;
+ newar->headerstr = NULL;
/* use optional regiondata callback */
if (ar->regiondata) {
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 298671beedb..e435d87024e 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -684,7 +684,7 @@ static float invGammaCorrect(float c)
else if (i >= RE_GAMMA_TABLE_SIZE) res = powf(c, valid_inv_gamma);
else res = inv_gamma_range_table[i] +
((c - color_domain_table[i]) * inv_gamfactor_table[i]);
-
+
return res;
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 2de7cd49901..05ce9c4bbb6 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -377,6 +377,8 @@ static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt)
}
break;
}
+ default:
+ break;
}
}
@@ -480,9 +482,12 @@ void BKE_sequencer_editing_free(Scene *scene)
static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf)
{
+#if 0
+ /* Bute buffer is supposed to be in sequencer working space already. */
if (ibuf->rect != NULL) {
IMB_colormanagement_assign_rect_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
}
+#endif
if (ibuf->rect_float != NULL) {
IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
}
@@ -1775,7 +1780,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
if (proxy->anim == NULL) {
return NULL;
}
-
+
seq_open_anim_file(context->scene, seq, true);
sanim = seq->anims.first;
@@ -1783,7 +1788,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
}
-
+
if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) {
return NULL;
}
@@ -2082,7 +2087,7 @@ void BKE_sequencer_proxy_set(struct Sequence *seq, bool value)
}
}
else {
- seq->flag ^= SEQ_USE_PROXY;
+ seq->flag &= ~SEQ_USE_PROXY;
}
}
@@ -3233,7 +3238,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
const bool is_background = G.background;
const bool do_seq_gl = is_rendering ?
0 /* (context->scene->r.seq_flag & R_SEQ_GL_REND) */ :
- (context->scene->r.seq_flag & R_SEQ_GL_PREV) != 0;
+ (context->scene->r.seq_prev_type) != OB_RENDER;
// bool have_seq = false; /* UNUSED */
bool have_comp = false;
bool use_gpencil = true;
@@ -4190,9 +4195,10 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha
if (free_imbuf) {
if (ibuf_change) {
- if (seq->type == SEQ_TYPE_MOVIE)
+ if (seq->type == SEQ_TYPE_MOVIE) {
BKE_sequence_free_anim(seq);
- if (seq->type == SEQ_TYPE_SPEED) {
+ }
+ else if (seq->type == SEQ_TYPE_SPEED) {
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
}
}
@@ -5182,6 +5188,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */
if (sound->playback_handle == NULL) {
+ BKE_libblock_free(bmain, sound);
#if 0
if (op)
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
@@ -5369,9 +5376,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
return seq;
}
-static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag)
+static Sequence *seq_dupli(const Scene *scene_src, Scene *scene_dst, Sequence *seq, int dupe_flag, const int flag)
{
- Scene *sce_audio = scene_to ? scene_to : scene;
Sequence *seqn = MEM_dupallocN(seq);
seq->tmp = seqn;
@@ -5395,7 +5401,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
}
if (seq->prop) {
- seqn->prop = IDP_CopyProperty(seq->prop);
+ seqn->prop = IDP_CopyProperty_ex(seq->prop, flag);
}
if (seqn->modifiers.first) {
@@ -5414,7 +5420,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
else if (seq->type == SEQ_TYPE_SCENE) {
seqn->strip->stripdata = NULL;
if (seq->scene_sound)
- seqn->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce_audio, seqn);
+ seqn->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene_dst, seqn);
}
else if (seq->type == SEQ_TYPE_MOVIECLIP) {
/* avoid assert */
@@ -5431,9 +5437,11 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
seqn->strip->stripdata =
MEM_dupallocN(seq->strip->stripdata);
if (seq->scene_sound)
- seqn->scene_sound = BKE_sound_add_scene_sound_defaults(sce_audio, seqn);
+ seqn->scene_sound = BKE_sound_add_scene_sound_defaults(scene_dst, seqn);
- id_us_plus((ID *)seqn->sound);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)seqn->sound);
+ }
}
else if (seq->type == SEQ_TYPE_IMAGE) {
seqn->strip->stripdata =
@@ -5453,11 +5461,15 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
BLI_assert(0);
}
- if (dupe_flag & SEQ_DUPE_UNIQUE_NAME)
- BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqn);
+ if (scene_src == scene_dst) {
+ if (dupe_flag & SEQ_DUPE_UNIQUE_NAME) {
+ BKE_sequence_base_unique_name_recursive(&scene_dst->ed->seqbase, seqn);
+ }
- if (dupe_flag & SEQ_DUPE_ANIM)
- BKE_sequencer_dupe_animdata(scene, seq->name + 2, seqn->name + 2);
+ if (dupe_flag & SEQ_DUPE_ANIM) {
+ BKE_sequencer_dupe_animdata(scene_dst, seq->name + 2, seqn->name + 2);
+ }
+ }
return seqn;
}
@@ -5484,16 +5496,16 @@ static void seq_new_fix_links_recursive(Sequence *seq)
}
}
-Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag)
+Sequence *BKE_sequence_dupli_recursive(const Scene *scene_src, Scene *scene_dst, Sequence *seq, int dupe_flag)
{
Sequence *seqn;
seq->tmp = NULL;
- seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
+ seqn = seq_dupli(scene_src, scene_dst, seq, dupe_flag, 0);
if (seq->type == SEQ_TYPE_META) {
Sequence *s;
for (s = seq->seqbase.first; s; s = s->next) {
- Sequence *n = BKE_sequence_dupli_recursive(scene, scene_to, s, dupe_flag);
+ Sequence *n = BKE_sequence_dupli_recursive(scene_src, scene_dst, s, dupe_flag);
if (n) {
BLI_addtail(&seqn->seqbase, n);
}
@@ -5506,19 +5518,19 @@ Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence *
}
void BKE_sequence_base_dupli_recursive(
- Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase,
- int dupe_flag)
+ const Scene *scene_src, Scene *scene_dst, ListBase *nseqbase, const ListBase *seqbase,
+ int dupe_flag, const int flag)
{
Sequence *seq;
Sequence *seqn = NULL;
- Sequence *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *last_seq = BKE_sequencer_active_get((Scene *)scene_src);
/* always include meta's strips */
int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL;
for (seq = seqbase->first; seq; seq = seq->next) {
seq->tmp = NULL;
if ((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) {
- seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
+ seqn = seq_dupli(scene_src, scene_dst, seq, dupe_flag, flag);
if (seqn) { /*should never fail */
if (dupe_flag & SEQ_DUPE_CONTEXT) {
seq->flag &= ~SEQ_ALLSEL;
@@ -5528,13 +5540,13 @@ void BKE_sequence_base_dupli_recursive(
BLI_addtail(nseqbase, seqn);
if (seq->type == SEQ_TYPE_META) {
BKE_sequence_base_dupli_recursive(
- scene, scene_to, &seqn->seqbase, &seq->seqbase,
- dupe_flag_recursive);
+ scene_src, scene_dst, &seqn->seqbase, &seq->seqbase,
+ dupe_flag_recursive, flag);
}
if (dupe_flag & SEQ_DUPE_CONTEXT) {
if (seq == last_seq) {
- BKE_sequencer_active_set(scene, seqn);
+ BKE_sequencer_active_set(scene_dst, seqn);
}
}
}
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 7094d5a3547..f9d1793d7cb 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -152,6 +152,9 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
BVHTreeNearest nearest = NULL_BVHTreeNearest;
+ if (calc->target != NULL && calc->target->getNumVerts(calc->target) == 0) {
+ return;
+ }
TIMEIT_BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6), bvhtree_verts);
if (treeData.tree == NULL) {
@@ -376,6 +379,9 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
if ((calc->smd->shrinkOpts & (MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)) == 0)
return;
+ if (calc->target != NULL && calc->target->getNumPolys(calc->target) == 0) {
+ return;
+ }
/* Prepare data to retrieve the direction in which we should project each vertex */
if (calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) {
@@ -432,7 +438,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
if (targ_tree) {
BVHTree *aux_tree = NULL;
void *aux_callback = NULL;
- if (auxMesh != NULL) {
+ if (auxMesh != NULL && auxMesh->getNumPolys(auxMesh) != 0) {
/* use editmesh to avoid array allocation */
if (calc->smd->auxTarget && auxMesh->type == DM_TYPE_EDITBMESH) {
emaux = BKE_editmesh_from_object(calc->smd->auxTarget);
@@ -560,6 +566,10 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
BVHTreeNearest nearest = NULL_BVHTreeNearest;
+ if (calc->target->getNumPolys(calc->target) == 0) {
+ return;
+ }
+
/* Create a bvh-tree of the given target */
bvhtree_from_mesh_looptri(&treeData, calc->target, 0.0, 2, 6);
if (treeData.tree == NULL) {
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index d0ef5cfc092..adecea7080c 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -2692,7 +2692,6 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
if (smd->flow->dm) smd->flow->dm->release(smd->flow->dm);
smd->flow->dm = CDDM_copy(dm);
- DM_ensure_looptri(smd->flow->dm);
if (scene->r.cfra > smd->time)
{
@@ -2715,7 +2714,6 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
smd->coll->dm->release(smd->coll->dm);
smd->coll->dm = CDDM_copy(dm);
- DM_ensure_looptri(smd->coll->dm);
}
smd->time = scene->r.cfra;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 4f73e153074..600bc3f453d 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -2235,9 +2235,9 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow)
{
-/* rule we never alter free variables :bp->vec bp->pos in here !
- * this will ruin adaptive stepsize AKA heun! (BM)
- */
+ /* rule we never alter free variables :bp->vec bp->pos in here !
+ * this will ruin adaptive stepsize AKA heun! (BM)
+ */
SoftBody *sb= ob->soft; /* is supposed to be there */
/*BodyPoint *bproot;*/ /* UNUSED */
ListBase *do_effector = NULL;
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 8469351c54a..45d1f969d64 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -83,7 +83,7 @@ bSound *BKE_sound_new_file(struct Main *bmain, const char *filepath)
BLI_path_abs(str, path);
- sound = BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath));
+ sound = BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath), 0);
BLI_strncpy(sound->name, filepath, FILE_MAX);
/* sound->type = SOUND_TYPE_FILE; */ /* XXX unused currently */
@@ -155,6 +155,34 @@ void BKE_sound_free(bSound *sound)
}
}
+/**
+ * Only copy internal data of Sound ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_sound_copy_data(Main *bmain, bSound *sound_dst, const bSound *UNUSED(sound_src), const int UNUSED(flag))
+{
+ sound_dst->handle = NULL;
+ sound_dst->cache = NULL;
+ sound_dst->waveform = NULL;
+ sound_dst->playback_handle = NULL;
+ sound_dst->spinlock = NULL; /* Think this is OK? Otherwise, easy to create new spinlock here... */
+
+ /* Just to be sure, should not have any value actually after reading time. */
+ sound_dst->ipo = NULL;
+ sound_dst->newpackedfile = NULL;
+
+ if (sound_dst->packedfile) {
+ sound_dst->packedfile = dupPackedFile(sound_dst->packedfile);
+ }
+
+ /* Initialize whole runtime (audaspace) stuff. */
+ BKE_sound_load(bmain, sound_dst);
+}
+
void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &sound->id, true, lib_local);
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index ee6886e3fb2..9d604a9382a 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -61,25 +61,31 @@ void *BKE_speaker_add(Main *bmain, const char *name)
{
Speaker *spk;
- spk = BKE_libblock_alloc(bmain, ID_SPK, name);
+ spk = BKE_libblock_alloc(bmain, ID_SPK, name, 0);
BKE_speaker_init(spk);
return spk;
}
-Speaker *BKE_speaker_copy(Main *bmain, Speaker *spk)
+/**
+ * Only copy internal data of Speaker ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_speaker_copy_data(Main *UNUSED(bmain), Speaker *UNUSED(spk_dst), const Speaker *UNUSED(spk_src), const int UNUSED(flag))
{
- Speaker *spkn;
-
- spkn = BKE_libblock_copy(bmain, &spk->id);
-
- if (spkn->sound)
- id_us_plus(&spkn->sound->id);
-
- BKE_id_copy_ensure_local(bmain, &spk->id, &spkn->id);
+ /* Nothing to do! */
+}
- return spkn;
+Speaker *BKE_speaker_copy(Main *bmain, const Speaker *spk)
+{
+ Speaker *spk_copy;
+ BKE_id_copy_ex(bmain, &spk->id, (ID **)&spk_copy, 0, false);
+ return spk_copy;
}
void BKE_speaker_make_local(Main *bmain, Speaker *spk, const bool lib_local)
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index e466c5fc3c1..c06ac91d6c8 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -4494,10 +4494,10 @@ static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
/* Nothing to do: CCG handles creating its own tessfaces */
}
+/* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */
static void ccgDM_recalcLoopTri(DerivedMesh *dm)
{
- BLI_rw_mutex_lock(&loops_cache_rwlock, THREAD_LOCK_WRITE);
- MLoopTri *mlooptri;
+ MLoopTri *mlooptri = dm->looptris.array;
const int tottri = dm->numPolyData * 2;
int i, poly_index;
@@ -4522,19 +4522,6 @@ static void ccgDM_recalcLoopTri(DerivedMesh *dm)
lt->tri[2] = (poly_index * 4) + 2;
lt->poly = poly_index;
}
- BLI_rw_mutex_unlock(&loops_cache_rwlock);
-}
-
-static const MLoopTri *ccgDM_getLoopTriArray(DerivedMesh *dm)
-{
- if (dm->looptris.array) {
- BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
- }
- else {
- dm->recalcLoopTri(dm);
- }
-
- return dm->looptris.array;
}
static void ccgDM_calcNormals(DerivedMesh *dm)
@@ -4553,8 +4540,6 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.getNumPolys = ccgDM_getNumPolys;
ccgdm->dm.getNumTessFaces = ccgDM_getNumTessFaces;
- ccgdm->dm.getLoopTriArray = ccgDM_getLoopTriArray;
-
ccgdm->dm.getVert = ccgDM_getFinalVert;
ccgdm->dm.getEdge = ccgDM_getFinalEdge;
ccgdm->dm.getTessFace = ccgDM_getFinalFace;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 298790a9e9b..7c4aa81ee46 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -224,7 +224,7 @@ Text *BKE_text_add(Main *bmain, const char *name)
{
Text *ta;
- ta = BKE_libblock_alloc(bmain, ID_TXT, name);
+ ta = BKE_libblock_alloc(bmain, ID_TXT, name, 0);
BKE_text_init(ta);
@@ -410,7 +410,7 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
return false;
}
- ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(filepath_abs));
+ ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(filepath_abs), 0);
ta->id.us = 0;
BLI_listbase_clear(&ta->lines);
@@ -449,53 +449,49 @@ Text *BKE_text_load(Main *bmain, const char *file, const char *relpath)
return BKE_text_load_ex(bmain, file, relpath, false);
}
-Text *BKE_text_copy(Main *bmain, Text *ta)
+/**
+ * Only copy internal data of Text ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_text_copy_data(Main *UNUSED(bmain), Text *ta_dst, const Text *ta_src, const int UNUSED(flag))
{
- Text *tan;
- TextLine *line, *tmp;
-
- tan = BKE_libblock_copy(bmain, &ta->id);
-
/* file name can be NULL */
- if (ta->name) {
- tan->name = BLI_strdup(ta->name);
- }
- else {
- tan->name = NULL;
+ if (ta_src->name) {
+ ta_dst->name = BLI_strdup(ta_src->name);
}
- tan->flags = ta->flags | TXT_ISDIRTY;
-
- BLI_listbase_clear(&tan->lines);
- tan->curl = tan->sell = NULL;
- tan->compiled = NULL;
-
- tan->nlines = ta->nlines;
+ ta_dst->flags |= TXT_ISDIRTY;
+
+ BLI_listbase_clear(&ta_dst->lines);
+ ta_dst->curl = ta_dst->sell = NULL;
+ ta_dst->compiled = NULL;
- line = ta->lines.first;
/* Walk down, reconstructing */
- while (line) {
- tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line = MEM_mallocN(line->len + 1, "textline_string");
- tmp->format = NULL;
-
- strcpy(tmp->line, line->line);
+ for (TextLine *line_src = ta_src->lines.first; line_src; line_src = line_src->next) {
+ TextLine *line_dst = MEM_mallocN(sizeof(*line_dst), __func__);
- tmp->len = line->len;
-
- BLI_addtail(&tan->lines, tmp);
-
- line = line->next;
- }
+ line_dst->line = BLI_strdup(line_src->line);
+ line_dst->format = NULL;
+ line_dst->len = line_src->len;
- tan->curl = tan->sell = tan->lines.first;
- tan->curc = tan->selc = 0;
+ BLI_addtail(&ta_dst->lines, line_dst);
+ }
- init_undo_text(tan);
+ ta_dst->curl = ta_dst->sell = ta_dst->lines.first;
+ ta_dst->curc = ta_dst->selc = 0;
- BKE_id_copy_ensure_local(bmain, &ta->id, &tan->id);
+ init_undo_text(ta_dst);
+}
- return tan;
+Text *BKE_text_copy(Main *bmain, const Text *ta)
+{
+ Text *ta_copy;
+ BKE_id_copy_ex(bmain, &ta->id, (ID **)&ta_copy, 0, false);
+ return ta_copy;
}
void BKE_text_make_local(Main *bmain, Text *text, const bool lib_local)
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index ba04dd9b8f4..8f0334a4752 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -707,7 +707,7 @@ Tex *BKE_texture_add(Main *bmain, const char *name)
{
Tex *tex;
- tex = BKE_libblock_alloc(bmain, ID_TE, name);
+ tex = BKE_libblock_alloc(bmain, ID_TE, name, 0);
BKE_texture_default(tex);
@@ -846,41 +846,71 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot)
/* ------------------------------------------------------------------------- */
-Tex *BKE_texture_copy(Main *bmain, Tex *tex)
+/**
+ * Only copy internal data of Texture ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const int flag)
{
- Tex *texn;
-
- texn = BKE_libblock_copy(bmain, &tex->id);
- if (BKE_texture_is_image_user(tex)) {
- id_us_plus((ID *)texn->ima);
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+
+ if (!BKE_texture_is_image_user(tex_src)) {
+ tex_dst->ima = NULL;
}
- else {
- texn->ima = NULL;
+
+ if (tex_dst->coba) {
+ tex_dst->coba = MEM_dupallocN(tex_dst->coba);
+ }
+ if (tex_dst->env) {
+ tex_dst->env = BKE_texture_envmap_copy(tex_dst->env, flag_subdata);
+ }
+ if (tex_dst->pd) {
+ tex_dst->pd = BKE_texture_pointdensity_copy(tex_dst->pd, flag_subdata);
+ }
+ if (tex_dst->vd) {
+ tex_dst->vd = MEM_dupallocN(tex_dst->vd);
+ }
+ if (tex_dst->ot) {
+ tex_dst->ot = BKE_texture_ocean_copy(tex_dst->ot, flag_subdata);
}
-
- if (texn->coba) texn->coba = MEM_dupallocN(texn->coba);
- if (texn->env) texn->env = BKE_texture_envmap_copy(texn->env);
- if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd);
- if (texn->vd) texn->vd = MEM_dupallocN(texn->vd);
- if (texn->ot) texn->ot = BKE_texture_ocean_copy(texn->ot);
- if (tex->nodetree) {
- if (tex->nodetree->execdata) {
- ntreeTexEndExecTree(tex->nodetree->execdata);
+ if (tex_src->nodetree) {
+ if (tex_src->nodetree->execdata) {
+ ntreeTexEndExecTree(tex_src->nodetree->execdata);
}
- texn->nodetree = ntreeCopyTree(bmain, tex->nodetree);
+ BKE_id_copy_ex(bmain, (ID *)tex_src->nodetree, (ID **)&tex_dst->nodetree, flag, false);
}
- BKE_previewimg_id_copy(&texn->id, &tex->id);
-
- BKE_id_copy_ensure_local(bmain, &tex->id, &texn->id);
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
+ BKE_previewimg_id_copy(&tex_dst->id, &tex_src->id);
+ }
+ else {
+ tex_dst->preview = NULL;
+ }
+}
- return texn;
+Tex *BKE_texture_copy(Main *bmain, const Tex *tex)
+{
+ Tex *tex_copy;
+ BKE_id_copy_ex(bmain, &tex->id, (ID **)&tex_copy, 0, false);
+ return tex_copy;
}
/* texture copy without adding to main dbase */
Tex *BKE_texture_localize(Tex *tex)
{
+ /* TODO replace with something like
+ * Tex *tex_copy;
+ * BKE_id_copy_ex(bmain, &tex->id, (ID **)&tex_copy, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT, false);
+ * return tex_copy;
+ *
+ * ... Once f*** nodes are fully converted to that too :( */
+
Tex *texn;
texn = BKE_libblock_copy_nolib(&tex->id, false);
@@ -889,17 +919,17 @@ Tex *BKE_texture_localize(Tex *tex)
if (texn->coba) texn->coba = MEM_dupallocN(texn->coba);
if (texn->env) {
- texn->env = BKE_texture_envmap_copy(texn->env);
+ texn->env = BKE_texture_envmap_copy(texn->env, LIB_ID_CREATE_NO_USER_REFCOUNT);
id_us_min(&texn->env->ima->id);
}
- if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd);
+ if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd, LIB_ID_CREATE_NO_USER_REFCOUNT);
if (texn->vd) {
texn->vd = MEM_dupallocN(texn->vd);
if (texn->vd->dataset)
texn->vd->dataset = MEM_dupallocN(texn->vd->dataset);
}
if (texn->ot) {
- texn->ot = BKE_texture_ocean_copy(tex->ot);
+ texn->ot = BKE_texture_ocean_copy(tex->ot, LIB_ID_CREATE_NO_USER_REFCOUNT);
}
texn->preview = NULL;
@@ -1099,6 +1129,8 @@ void set_active_mtex(ID *id, short act)
case ID_PA:
((ParticleSettings *)id)->texact = act;
break;
+ default:
+ break;
}
}
@@ -1263,16 +1295,20 @@ EnvMap *BKE_texture_envmap_add(void)
/* ------------------------------------------------------------------------- */
-EnvMap *BKE_texture_envmap_copy(EnvMap *env)
+EnvMap *BKE_texture_envmap_copy(const EnvMap *env, const int flag)
{
EnvMap *envn;
int a;
envn = MEM_dupallocN(env);
envn->ok = 0;
- for (a = 0; a < 6; a++) envn->cube[a] = NULL;
- if (envn->ima) id_us_plus((ID *)envn->ima);
-
+ for (a = 0; a < 6; a++) {
+ envn->cube[a] = NULL;
+ }
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus((ID *)envn->ima);
+ }
+
return envn;
}
@@ -1336,14 +1372,16 @@ PointDensity *BKE_texture_pointdensity_add(void)
return pd;
}
-PointDensity *BKE_texture_pointdensity_copy(PointDensity *pd)
+PointDensity *BKE_texture_pointdensity_copy(const PointDensity *pd, const int UNUSED(flag))
{
PointDensity *pdn;
pdn = MEM_dupallocN(pd);
pdn->point_tree = NULL;
pdn->point_data = NULL;
- if (pdn->coba) pdn->coba = MEM_dupallocN(pdn->coba);
+ if (pdn->coba) {
+ pdn->coba = MEM_dupallocN(pdn->coba);
+ }
pdn->falloff_curve = curvemapping_copy(pdn->falloff_curve); /* can be NULL */
return pdn;
}
@@ -1430,7 +1468,7 @@ OceanTex *BKE_texture_ocean_add(void)
return ot;
}
-OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot)
+OceanTex *BKE_texture_ocean_copy(const OceanTex *ot, const int UNUSED(flag))
{
OceanTex *otn = MEM_dupallocN(ot);
@@ -1519,3 +1557,33 @@ void BKE_texture_get_value(
{
BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management);
}
+
+static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePool *pool)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_IMAGE && node->id != NULL) {
+ Image *image = (Image *)node->id;
+ BKE_image_pool_acquire_ibuf(image, NULL, pool);
+ }
+ else if (node->type == NODE_GROUP && node->id != NULL) {
+ /* TODO(sergey): Do we need to control recursion here? */
+ bNodeTree *nested_tree = (bNodeTree *)node->id;
+ texture_nodes_fetch_images_for_pool(nested_tree, pool);
+ }
+ }
+}
+
+/* Make sure all images used by texture are loaded into pool. */
+void BKE_texture_fetch_images_for_pool(Tex *texture, struct ImagePool *pool)
+{
+ if (texture->nodetree != NULL) {
+ texture_nodes_fetch_images_for_pool(texture->nodetree, pool);
+ }
+ else {
+ if (texture->type == TEX_IMAGE) {
+ if (texture->ima != NULL) {
+ BKE_image_pool_acquire_ibuf(texture->ima, NULL, pool);
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index bfe8dcbb21e..b4ef381534f 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -190,7 +190,7 @@ void BKE_tracking_free(MovieTracking *tracking)
}
/* Copy the whole list of tracks. */
-static void tracking_tracks_copy(ListBase *tracks_dst, ListBase *tracks_src, GHash *tracks_mapping)
+static void tracking_tracks_copy(ListBase *tracks_dst, const ListBase *tracks_src, GHash *tracks_mapping, const int flag)
{
MovieTrackingTrack *track_dst, *track_src;
@@ -202,7 +202,9 @@ static void tracking_tracks_copy(ListBase *tracks_dst, ListBase *tracks_src, GHa
if (track_src->markers) {
track_dst->markers = MEM_dupallocN(track_src->markers);
}
- id_us_plus(&track_dst->gpd->id);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus(&track_dst->gpd->id);
+ }
BLI_addtail(tracks_dst, track_dst);
BLI_ghash_insert(tracks_mapping, track_src, track_dst);
}
@@ -210,7 +212,8 @@ static void tracking_tracks_copy(ListBase *tracks_dst, ListBase *tracks_src, GHa
/* copy the whole list of plane tracks (need whole MovieTracking structures due to embedded pointers to tracks).
* WARNING: implies tracking_[dst/src] and their tracks have already been copied. */
-static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, ListBase *plane_tracks_src, GHash *tracks_mapping)
+static void tracking_plane_tracks_copy(
+ ListBase *plane_tracks_dst, const ListBase *plane_tracks_src, GHash *tracks_mapping, const int flag)
{
MovieTrackingPlaneTrack *plane_track_dst, *plane_track_src;
@@ -225,14 +228,17 @@ static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, ListBase *pla
for (int i = 0; i < plane_track_dst->point_tracksnr; i++) {
plane_track_dst->point_tracks[i] = BLI_ghash_lookup(tracks_mapping, plane_track_src->point_tracks[i]);
}
- id_us_plus(&plane_track_dst->image->id);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus(&plane_track_dst->image->id);
+ }
BLI_addtail(plane_tracks_dst, plane_track_dst);
}
}
/* Copy reconstruction structure. */
static void tracking_reconstruction_copy(
- MovieTrackingReconstruction *reconstruction_dst, MovieTrackingReconstruction *reconstruction_src)
+ MovieTrackingReconstruction *reconstruction_dst, const MovieTrackingReconstruction *reconstruction_src,
+ const int UNUSED(flag))
{
*reconstruction_dst = *reconstruction_src;
if (reconstruction_src->cameras) {
@@ -242,23 +248,25 @@ static void tracking_reconstruction_copy(
/* Copy stabilization structure. */
static void tracking_stabilization_copy(
- MovieTrackingStabilization *stabilization_dst, MovieTrackingStabilization *stabilization_src)
+ MovieTrackingStabilization *stabilization_dst, const MovieTrackingStabilization *stabilization_src,
+ const int UNUSED(flag))
{
*stabilization_dst = *stabilization_src;
}
/* Copy tracking object. */
static void tracking_object_copy(
- MovieTrackingObject *object_dst, MovieTrackingObject *object_src, GHash *tracks_mapping)
+ MovieTrackingObject *object_dst, const MovieTrackingObject *object_src, GHash *tracks_mapping, const int flag)
{
*object_dst = *object_src;
- tracking_tracks_copy(&object_dst->tracks, &object_src->tracks, tracks_mapping);
- tracking_plane_tracks_copy(&object_dst->plane_tracks, &object_src->plane_tracks, tracks_mapping);
- tracking_reconstruction_copy(&object_dst->reconstruction, &object_src->reconstruction);
+ tracking_tracks_copy(&object_dst->tracks, &object_src->tracks, tracks_mapping, flag);
+ tracking_plane_tracks_copy(&object_dst->plane_tracks, &object_src->plane_tracks, tracks_mapping, flag);
+ tracking_reconstruction_copy(&object_dst->reconstruction, &object_src->reconstruction, flag);
}
/* Copy list of tracking objects. */
-static void tracking_objects_copy(ListBase *objects_dst, ListBase *objects_src, GHash *tracks_mapping)
+static void tracking_objects_copy(
+ ListBase *objects_dst, const ListBase *objects_src, GHash *tracks_mapping, const int flag)
{
MovieTrackingObject *object_dst, *object_src;
@@ -266,22 +274,22 @@ static void tracking_objects_copy(ListBase *objects_dst, ListBase *objects_src,
for (object_src = objects_src->first; object_src != NULL; object_src = object_src->next) {
object_dst = MEM_mallocN(sizeof(*object_dst), __func__);
- tracking_object_copy(object_dst, object_src, tracks_mapping);
+ tracking_object_copy(object_dst, object_src, tracks_mapping, flag);
BLI_addtail(objects_dst, object_dst);
}
}
/* Copy tracking structure content. */
-void BKE_tracking_copy(MovieTracking *tracking_dst, MovieTracking *tracking_src)
+void BKE_tracking_copy(MovieTracking *tracking_dst, const MovieTracking *tracking_src, const int flag)
{
GHash *tracks_mapping = BLI_ghash_ptr_new(__func__);
*tracking_dst = *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);
+ tracking_tracks_copy(&tracking_dst->tracks, &tracking_src->tracks, tracks_mapping, flag);
+ tracking_plane_tracks_copy(&tracking_dst->plane_tracks, &tracking_src->plane_tracks, tracks_mapping, flag);
+ tracking_reconstruction_copy(&tracking_dst->reconstruction, &tracking_src->reconstruction, flag);
+ tracking_stabilization_copy(&tracking_dst->stabilization, &tracking_src->stabilization, flag);
if (tracking_src->act_track) {
tracking_dst->act_track = BLI_ghash_lookup(tracks_mapping, tracking_src->act_track);
}
@@ -299,7 +307,7 @@ void BKE_tracking_copy(MovieTracking *tracking_dst, MovieTracking *tracking_src)
}
/* Warning! Will override tracks_mapping. */
- tracking_objects_copy(&tracking_dst->objects, &tracking_src->objects, tracks_mapping);
+ tracking_objects_copy(&tracking_dst->objects, &tracking_src->objects, tracks_mapping, flag);
/* Those remaining are runtime data, they will be reconstructed as needed, do not bother copying them. */
tracking_dst->dopesheet.ok = false;
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index 9475925cdda..30981ed8f23 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -312,7 +312,7 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
int num_total_tracks = BLI_listbase_count(tracksbase);
context->tracks =
- MEM_callocN(sizeof(MovieTrackingTrack*) * num_total_tracks,
+ MEM_callocN(sizeof(MovieTrackingTrack *) * num_total_tracks,
"auto track pointers");
context->image_accessor =
@@ -381,7 +381,7 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
bool BKE_autotrack_context_step(AutoTrackContext *context)
{
- int frame_delta = context->backwards ? -1 : 1;
+ const int frame_delta = context->backwards ? -1 : 1;
bool ok = false;
int track;
@@ -395,67 +395,64 @@ bool BKE_autotrack_context_step(AutoTrackContext *context)
libmv_reference_marker,
libmv_tracked_marker;
libmv_TrackRegionResult libmv_result;
- int frame = BKE_movieclip_remap_scene_to_clip_frame(
- context->clips[options->clip_index],
- context->user.framenr);
- bool has_marker;
-
+ const int frame = BKE_movieclip_remap_scene_to_clip_frame(
+ context->clips[options->clip_index],
+ context->user.framenr);
BLI_spin_lock(&context->spin_lock);
- has_marker = libmv_autoTrackGetMarker(context->autotrack,
- options->clip_index,
- frame,
- options->track_index,
- &libmv_current_marker);
+ const bool has_marker = libmv_autoTrackGetMarker(context->autotrack,
+ options->clip_index,
+ frame,
+ options->track_index,
+ &libmv_current_marker);
BLI_spin_unlock(&context->spin_lock);
-
- if (has_marker) {
- if (!tracking_check_marker_margin(&libmv_current_marker,
- options->track->margin,
- context->frame_width,
- context->frame_height))
- {
- continue;
- }
-
- libmv_tracked_marker = libmv_current_marker;
- libmv_tracked_marker.frame = frame + frame_delta;
-
- if (options->use_keyframe_match) {
- libmv_tracked_marker.reference_frame =
- libmv_current_marker.reference_frame;
- libmv_autoTrackGetMarker(context->autotrack,
- options->clip_index,
- libmv_tracked_marker.reference_frame,
- options->track_index,
- &libmv_reference_marker);
- }
- else {
- libmv_tracked_marker.reference_frame = frame;
- libmv_reference_marker = libmv_current_marker;
- }
-
- if (libmv_autoTrackMarker(context->autotrack,
- &options->track_region_options,
- &libmv_tracked_marker,
- &libmv_result))
- {
- BLI_spin_lock(&context->spin_lock);
- libmv_autoTrackAddMarker(context->autotrack,
- &libmv_tracked_marker);
- BLI_spin_unlock(&context->spin_lock);
- }
- else {
- options->is_failed = true;
- options->failed_frame = frame + frame_delta;
- }
- ok = true;
+ /* Check whether we've got marker to sync with. */
+ if (!has_marker) {
+ continue;
+ }
+ /* Check whether marker is going outside of allowed frame margin. */
+ if (!tracking_check_marker_margin(&libmv_current_marker,
+ options->track->margin,
+ context->frame_width,
+ context->frame_height))
+ {
+ continue;
+ }
+ libmv_tracked_marker = libmv_current_marker;
+ libmv_tracked_marker.frame = frame + frame_delta;
+ /* Update reference frame. */
+ if (options->use_keyframe_match) {
+ libmv_tracked_marker.reference_frame =
+ libmv_current_marker.reference_frame;
+ libmv_autoTrackGetMarker(context->autotrack,
+ options->clip_index,
+ libmv_tracked_marker.reference_frame,
+ options->track_index,
+ &libmv_reference_marker);
}
+ else {
+ libmv_tracked_marker.reference_frame = frame;
+ libmv_reference_marker = libmv_current_marker;
+ }
+ /* Perform actual tracking. */
+ if (libmv_autoTrackMarker(context->autotrack,
+ &options->track_region_options,
+ &libmv_tracked_marker,
+ &libmv_result))
+ {
+ BLI_spin_lock(&context->spin_lock);
+ libmv_autoTrackAddMarker(context->autotrack, &libmv_tracked_marker);
+ BLI_spin_unlock(&context->spin_lock);
+ }
+ else {
+ options->is_failed = true;
+ options->failed_frame = frame + frame_delta;
+ }
+ ok = true;
}
-
+ /* Advance the frame. */
BLI_spin_lock(&context->spin_lock);
context->user.framenr += frame_delta;
BLI_spin_unlock(&context->spin_lock);
-
return ok;
}
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 3dfaa1ed77d..b8dfb217c16 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -203,7 +203,7 @@ static float get_animated_scaleinf(StabContext *ctx, int framenr)
static void get_animated_target_pos(StabContext *ctx,
int framenr,
- float target_pos[2])
+ float target_pos[2])
{
target_pos[0] = fetch_from_fcurve(ctx->target_pos[0],
framenr,
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index a95399562d5..d8e98291117 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -58,6 +58,15 @@
#include "libmv-capi.h"
+/* Uncomment this to have caching-specific debug prints. */
+// #define DEBUG_CACHE
+
+#ifdef DEBUG_CACHE
+# define CACHE_PRINTF(...) printf(__VA_ARGS__)
+#else
+# define CACHE_PRINTF(...)
+#endif
+
/*********************** Tracks map *************************/
TracksMap *tracks_map_new(const char *object_name, bool is_camera, int num_tracks, int customdata_size)
@@ -523,6 +532,8 @@ typedef struct AccessCacheKey {
int frame;
int downscale;
libmv_InputMode input_mode;
+ bool has_region;
+ float region_min[2], region_max[2];
int64_t transform_key;
} AccessCacheKey;
@@ -537,23 +548,44 @@ static bool accesscache_hashcmp(const void *a_v, const void *b_v)
{
const AccessCacheKey *a = (const AccessCacheKey *) a_v;
const AccessCacheKey *b = (const AccessCacheKey *) b_v;
-
-#define COMPARE_FIELD(field)
- { \
- if (a->clip_index != b->clip_index) { \
- return false; \
- } \
- } (void) 0
-
- COMPARE_FIELD(clip_index);
- COMPARE_FIELD(frame);
- COMPARE_FIELD(downscale);
- COMPARE_FIELD(input_mode);
- COMPARE_FIELD(transform_key);
-
-#undef COMPARE_FIELD
-
- return true;
+ if (a->clip_index != b->clip_index ||
+ a->frame != b->frame ||
+ a->downscale != b->downscale ||
+ a->input_mode != b->input_mode ||
+ a->has_region != b->has_region ||
+ a->transform_key != b->transform_key)
+ {
+ return true;
+ }
+ /* If there is region applied, compare it. */
+ if (a->has_region) {
+ if (!equals_v2v2(a->region_min, b->region_min) ||
+ !equals_v2v2(a->region_max, b->region_max))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void accesscache_construct_key(AccessCacheKey *key,
+ int clip_index,
+ int frame,
+ libmv_InputMode input_mode,
+ int downscale,
+ const libmv_Region *region,
+ int64_t transform_key)
+{
+ key->clip_index = clip_index;
+ key->frame = frame;
+ key->input_mode = input_mode;
+ key->downscale = downscale;
+ key->has_region = (region != NULL);
+ if (key->has_region) {
+ copy_v2_v2(key->region_min, region->min);
+ copy_v2_v2(key->region_max, region->max);
+ }
+ key->transform_key = transform_key;
}
static void accesscache_put(TrackingImageAccessor *accessor,
@@ -561,15 +593,13 @@ static void accesscache_put(TrackingImageAccessor *accessor,
int frame,
libmv_InputMode input_mode,
int downscale,
+ const libmv_Region *region,
int64_t transform_key,
ImBuf *ibuf)
{
AccessCacheKey key;
- key.clip_index = clip_index;
- key.frame = frame;
- key.input_mode = input_mode;
- key.downscale = downscale;
- key.transform_key = transform_key;
+ accesscache_construct_key(&key, clip_index, frame, input_mode, downscale,
+ region, transform_key);
IMB_moviecache_put(accessor->cache, &key, ibuf);
}
@@ -578,14 +608,12 @@ static ImBuf *accesscache_get(TrackingImageAccessor *accessor,
int frame,
libmv_InputMode input_mode,
int downscale,
+ const libmv_Region *region,
int64_t transform_key)
{
AccessCacheKey key;
- key.clip_index = clip_index;
- key.frame = frame;
- key.input_mode = input_mode;
- key.downscale = downscale;
- key.transform_key = transform_key;
+ accesscache_construct_key(&key, clip_index, frame, input_mode, downscale,
+ region, transform_key);
return IMB_moviecache_get(accessor->cache, &key);
}
@@ -674,29 +702,37 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
{
ImBuf *ibuf, *orig_ibuf, *final_ibuf;
int64_t transform_key = 0;
-
if (transform != NULL) {
transform_key = libmv_frameAccessorgetTransformKey(transform);
}
-
/* First try to get fully processed image from the cache. */
+ BLI_spin_lock(&accessor->cache_lock);
ibuf = accesscache_get(accessor,
clip_index,
frame,
input_mode,
downscale,
+ region,
transform_key);
+ BLI_spin_unlock(&accessor->cache_lock);
if (ibuf != NULL) {
+ CACHE_PRINTF("Used cached buffer for frame %d\n", frame);
+ /* This is a little heuristic here: if we re-used image once, this is
+ * a high probability of the image to be related to a keyframe matched
+ * reference image. Those images we don't want to be thrown away because
+ * if we toss them out we'll be re-calculating them at the next
+ * iteration.
+ */
+ ibuf->userflags |= IB_PERSISTENT;
return ibuf;
}
-
+ CACHE_PRINTF("Calculate new buffer for frame %d\n", frame);
/* And now we do postprocessing of the original frame. */
orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame);
-
if (orig_ibuf == NULL) {
return NULL;
}
-
+ /* Cut a region if requested. */
if (region != NULL) {
int width = region->max[0] - region->min[0],
height = region->max[1] - region->min[1];
@@ -756,7 +792,7 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
BLI_unlock_thread(LOCK_MOVIECLIP);
final_ibuf = orig_ibuf;
}
-
+ /* Downscale if needed. */
if (downscale > 0) {
if (final_ibuf == orig_ibuf) {
final_ibuf = IMB_dupImBuf(orig_ibuf);
@@ -765,7 +801,7 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
orig_ibuf->x / (1 << downscale),
orig_ibuf->y / (1 << downscale));
}
-
+ /* Apply possible transformation. */
if (transform != NULL) {
libmv_FloatImage input_image, output_image;
ibuf_to_float_image(final_ibuf, &input_image);
@@ -778,12 +814,13 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
final_ibuf = float_image_to_ibuf(&output_image);
libmv_floatImageDestroy(&output_image);
}
-
+ /* Transform number of channels. */
if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
BLI_assert(orig_ibuf->channels == 3 || orig_ibuf->channels == 4);
/* pass */
}
else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
+ BLI_assert(input_mode == LIBMV_IMAGE_MODE_MONO);
if (final_ibuf->channels != 1) {
ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
if (final_ibuf != orig_ibuf) {
@@ -793,37 +830,25 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
final_ibuf = grayscale_ibuf;
}
}
-
- /* it's possible processing still didn't happen at this point,
+ /* It's possible processing still didn't happen at this point,
* but we really need a copy of the buffer to be transformed
* and to be put to the cache.
*/
if (final_ibuf == orig_ibuf) {
final_ibuf = IMB_dupImBuf(orig_ibuf);
}
-
IMB_freeImBuf(orig_ibuf);
-
- /* We put postprocessed frame to the cache always for now,
- * not the smartest thing in the world, but who cares at this point.
- */
-
- /* TODO(sergey): Disable cache for now, because we don't store region
- * in the cache key and can't check whether cached version is usable for
- * us or not.
- *
- * Need to think better about what to cache and when.
- */
- if (false) {
- accesscache_put(accessor,
- clip_index,
- frame,
- input_mode,
- downscale,
- transform_key,
- final_ibuf);
- }
-
+ BLI_spin_lock(&accessor->cache_lock);
+ /* Put final buffer to cache. */
+ accesscache_put(accessor,
+ clip_index,
+ frame,
+ input_mode,
+ downscale,
+ region,
+ transform_key,
+ final_ibuf);
+ BLI_spin_unlock(&accessor->cache_lock);
return final_ibuf;
}
@@ -876,7 +901,7 @@ static void accessor_release_image_callback(libmv_CacheKey cache_key)
}
static libmv_CacheKey accessor_get_mask_for_track_callback(
- libmv_FrameAccessorUserData* user_data,
+ libmv_FrameAccessorUserData *user_data,
int clip_index,
int frame,
int track_index,
@@ -958,6 +983,8 @@ TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR
accessor_get_mask_for_track_callback,
accessor_release_mask_callback);
+ BLI_spin_init(&accessor->cache_lock);
+
return accessor;
}
@@ -965,5 +992,6 @@ void tracking_image_accessor_destroy(TrackingImageAccessor *accessor)
{
IMB_moviecache_free(accessor->cache);
libmv_FrameAccessorDestroy(accessor->libmv_accessor);
+ BLI_spin_end(&accessor->cache_lock);
MEM_freeN(accessor);
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index c0a373395dc..8606da0743b 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -372,6 +372,12 @@ static size_t unit_as_string(char *str, int len_max, double value, int prec, con
value_conv = value / unit->scalar;
+ /* Adjust precision to expected number of significant digits.
+ * Note that here, we shall not have to worry about very big/small numbers, units are expected to replace
+ * 'scientific notation' in those cases. */
+ prec -= integer_digits_d(value_conv);
+ CLAMP(prec, 0, 6);
+
/* Convert to a string */
len = BLI_snprintf_rlen(str, len_max, "%.*f", prec, value_conv);
@@ -442,12 +448,15 @@ size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system
size_t i;
i = unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0');
+ prec -= integer_digits_d(value_a / unit_b->scalar) - integer_digits_d(value_b / unit_b->scalar);
+ prec = max_ii(prec, 0);
+
/* is there enough space for at least 1 char of the next unit? */
if (i + 2 < len_max) {
str[i++] = ' ';
/* use low precision since this is a smaller unit */
- i += unit_as_string(str + i, len_max - i, value_b, prec ? 1 : 0, usys, unit_b, '\0');
+ i += unit_as_string(str + i, len_max - i, value_b, prec, usys, unit_b, '\0');
}
return i;
}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index caa9a1e357f..e79b06a44fe 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -112,43 +112,59 @@ World *add_world(Main *bmain, const char *name)
{
World *wrld;
- wrld = BKE_libblock_alloc(bmain, ID_WO, name);
+ wrld = BKE_libblock_alloc(bmain, ID_WO, name, 0);
BKE_world_init(wrld);
return wrld;
}
-World *BKE_world_copy(Main *bmain, World *wrld)
+/**
+ * Only copy internal data of World ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_world_copy_data(Main *bmain, World *wrld_dst, const World *wrld_src, const int flag)
{
- World *wrldn;
- int a;
-
- wrldn = BKE_libblock_copy(bmain, &wrld->id);
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (wrld->mtex[a]) {
- wrldn->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_world_copy");
- memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex));
- id_us_plus((ID *)wrldn->mtex[a]->tex);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (wrld_src->mtex[a]) {
+ wrld_dst->mtex[a] = MEM_dupallocN(wrld_src->mtex[a]);
}
}
- if (wrld->nodetree) {
- wrldn->nodetree = ntreeCopyTree(bmain, wrld->nodetree);
+ if (wrld_src->nodetree) {
+ BKE_id_copy_ex(bmain, (ID *)wrld_src->nodetree, (ID **)&wrld_dst->nodetree, flag, false);
}
-
- BKE_previewimg_id_copy(&wrldn->id, &wrld->id);
- BLI_listbase_clear(&wrldn->gpumaterial);
+ BLI_listbase_clear(&wrld_dst->gpumaterial);
- BKE_id_copy_ensure_local(bmain, &wrld->id, &wrldn->id);
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
+ BKE_previewimg_id_copy(&wrld_dst->id, &wrld_src->id);
+ }
+ else {
+ wrld_dst->preview = NULL;
+ }
+}
- return wrldn;
+World *BKE_world_copy(Main *bmain, const World *wrld)
+{
+ World *wrld_copy;
+ BKE_id_copy_ex(bmain, &wrld->id, (ID **)&wrld_copy, 0, false);
+ return wrld_copy;
}
World *localize_world(World *wrld)
{
+ /* TODO replace with something like
+ * World *wrld_copy;
+ * BKE_id_copy_ex(bmain, &wrld->id, (ID **)&wrld_copy, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT, false);
+ * return wrld_copy;
+ *
+ * ... Once f*** nodes are fully converted to that too :( */
+
World *wrldn;
int a;
diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h
index 1a68a1cac6a..07236fb2096 100644
--- a/source/blender/blenkernel/tracking_private.h
+++ b/source/blender/blenkernel/tracking_private.h
@@ -125,6 +125,7 @@ typedef struct TrackingImageAccessor {
int num_tracks;
int start_frame;
struct libmv_FrameAccessor *libmv_accessor;
+ SpinLock cache_lock;
} TrackingImageAccessor;
TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP],
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index c645ff06c00..3ffca818c0d 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -135,11 +135,12 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
#define BLI_array_append_ret(arr) \
(BLI_array_reserve(arr, 1), &arr[(_##arr##_count++)])
-#define BLI_array_free(arr) \
+#define BLI_array_free(arr) { \
if (arr && (char *)arr != _##arr##_static) { \
- BLI_array_fake_user(arr); \
- MEM_freeN(arr); \
- } (void)0
+ BLI_array_fake_user(arr); \
+ MEM_freeN(arr); \
+ } \
+} ((void)0)
#define BLI_array_pop(arr) ( \
(arr && _##arr##_count) ? \
diff --git a/source/blender/blenlib/BLI_compiler_compat.h b/source/blender/blenlib/BLI_compiler_compat.h
index 01fc9d70207..0726e3bb343 100644
--- a/source/blender/blenlib/BLI_compiler_compat.h
+++ b/source/blender/blenlib/BLI_compiler_compat.h
@@ -48,12 +48,7 @@ extern "C++" {
#if defined(_MSC_VER)
# define BLI_INLINE static __forceinline
#else
-# if (defined(__APPLE__) && defined(__ppc__))
-/* static inline __attribute__ here breaks osx ppc gcc42 build */
-# define BLI_INLINE static __attribute__((always_inline)) __attribute__((__unused__))
-# else
-# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__))
-# endif
+# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__))
#endif
#endif /* __BLI_COMPILER_COMPAT_H__ */
diff --git a/source/blender/blenlib/BLI_dial.h b/source/blender/blenlib/BLI_dial.h
index ad7680fe03e..71ab57bb61a 100644
--- a/source/blender/blenlib/BLI_dial.h
+++ b/source/blender/blenlib/BLI_dial.h
@@ -52,8 +52,8 @@
typedef struct Dial Dial;
-Dial *BLI_dial_initialize(float start_position[2], float threshold);
+Dial *BLI_dial_initialize(const float start_position[2], float threshold);
-float BLI_dial_angle(Dial *dial, float current_position[2]);
+float BLI_dial_angle(Dial *dial, const float current_position[2]);
#endif /* __BLI_DIAL_H__ */
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 7cf3e97bdc9..b42a36a3567 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -43,7 +43,7 @@ extern "C" {
#ifndef GHASH_INTERNAL_API
# ifdef __GNUC__
# undef _GHASH_INTERNAL_ATTR
-# define _GHASH_INTERNAL_ATTR __attribute__ ((deprecated))
+# define _GHASH_INTERNAL_ATTR __attribute__ ((deprecated)) /* not deprecated, just private. */
# endif
#endif
@@ -90,6 +90,7 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfre
void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve);
void BLI_ghash_insert(GHash *gh, void *key, void *val);
bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+void *BLI_ghash_replace_key(GHash *gh, void *key);
void *BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT;
void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
@@ -248,6 +249,7 @@ void BLI_gset_insert(GSet *gh, void *key);
bool BLI_gset_add(GSet *gs, void *key);
bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key);
bool BLI_gset_reinsert(GSet *gh, void *key, GSetKeyFreeFP keyfreefp);
+void *BLI_gset_replace_key(GSet *gs, void *key);
bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT;
bool BLI_gset_pop(GSet *gs, GSetIterState *state, void **r_key) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp);
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index ba565fca522..564659ad21e 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -36,7 +36,7 @@
*/
#ifdef __cplusplus
-extern "C" {
+extern "C" {
#endif
struct BVHTree;
@@ -62,7 +62,7 @@ typedef struct BVHTreeNearest {
int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */
float co[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */
float no[3]; /* normal at nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */
- float dist_sq; /* squared distance to search arround */
+ float dist_sq; /* squared distance to search around */
int flags;
} BVHTreeNearest;
diff --git a/source/blender/blenlib/BLI_kdtree.h b/source/blender/blenlib/BLI_kdtree.h
index aa54e1c823c..18908f8c551 100644
--- a/source/blender/blenlib/BLI_kdtree.h
+++ b/source/blender/blenlib/BLI_kdtree.h
@@ -66,6 +66,10 @@ void BLI_kdtree_range_search_cb(
const KDTree *tree, const float co[3], float range,
bool (*search_cb)(void *user_data, int index, const float co[3], float dist_sq), void *user_data);
+int BLI_kdtree_calc_duplicates_fast(
+ const KDTree *tree, const float range, bool use_index_order,
+ int *doubles);
+
/* Normal use is deprecated */
/* remove __normal functions when last users drop */
int BLI_kdtree_find_nearest_n__normal(
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 0126e30d900..c44b666faea 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -138,6 +138,9 @@ MINLINE int signum_i(float a);
MINLINE float power_of_2(float f);
+MINLINE int integer_digits_f(const float f);
+MINLINE int integer_digits_d(const double d);
+
/* these don't really fit anywhere but were being copied about a lot */
MINLINE int is_power_of_2_i(int n);
MINLINE int power_of_2_max_i(int n);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index f1d9c9571f2..0fef849c8fa 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -166,8 +166,14 @@ void limit_dist_v3(float v1[3], float v2[3], const float dist);
int isect_seg_seg_v2(const float a1[2], const float a2[2], const float b1[2], const float b2[2]);
int isect_seg_seg_v2_int(const int a1[2], const int a2[2], const int b1[2], const int b2[2]);
-int isect_seg_seg_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float vi[2]);
-bool isect_seg_seg_v2_simple(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
+int isect_seg_seg_v2_point_ex(
+ const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float endpoint_bias,
+ float vi[2]);
+int isect_seg_seg_v2_point(
+ const float v0[2], const float v1[2], const float v2[2], const float v3[2],
+ float vi[2]);
+bool isect_seg_seg_v2_simple(
+ const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
int isect_line_sphere_v3(const float l1[3], const float l2[3], const float sp[3], const float r, float r_p1[3], float r_p2[3]);
int isect_line_sphere_v2(const float l1[2], const float l2[2], const float sp[2], const float r, float r_p1[2], float r_p2[2]);
diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h
index 840cf24f8cf..383abda5b2f 100644
--- a/source/blender/blenlib/BLI_math_inline.h
+++ b/source/blender/blenlib/BLI_math_inline.h
@@ -44,12 +44,7 @@ extern "C" {
# define MALWAYS_INLINE MINLINE
# else
# define MINLINE static inline
-# if (defined(__APPLE__) && defined(__ppc__))
- /* static inline __attribute__ here breaks osx ppc gcc42 build */
-# define MALWAYS_INLINE static __attribute__((always_inline)) __attribute__((unused))
-# else
-# define MALWAYS_INLINE static inline __attribute__((always_inline)) __attribute__((unused))
-# endif
+# define MALWAYS_INLINE static inline __attribute__((always_inline)) __attribute__((unused))
# endif
#else
# define MINLINE
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index d60be30e10d..e059327a490 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -218,8 +218,12 @@ float angle_wrap_deg(float angle);
float angle_compat_rad(float angle, float angle_compat);
-int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up,
- float r_mat[3][3]);
+bool mat3_from_axis_conversion(
+ int src_forward, int src_up, int dst_forward, int dst_up,
+ float r_mat[3][3]);
+bool mat3_from_axis_conversion_single(
+ int src_axis, int dst_axis,
+ float r_mat[3][3]);
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 8e0884ba347..4fdb33926a2 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -286,6 +286,8 @@ float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT;
float cos_v3v3v3(const float p1[3], const float p2[3], const float p3[3]) ATTR_WARN_UNUSED_RESULT;
float cos_v2v2v2(const float p1[2], const float p2[2], const float p3[2]) ATTR_WARN_UNUSED_RESULT;
+float angle_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT;
+float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT;
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT;
float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT;
float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT;
@@ -297,8 +299,12 @@ void angle_poly_v3(float *angles, const float *verts[3], int len);
void project_v2_v2v2(float out[2], const float p[2], const float v_proj[2]);
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3]);
+void project_v2_v2v2_normalized(float out[2], const float p[2], const float v_proj[2]);
+void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_proj[3]);
void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3]);
void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2]);
+void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3]);
+void project_plane_normalized_v2_v2v2(float out[2], const float p[2], const float v_plane[2]);
void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3]);
void reflect_v3_v3v3(float out[3], const float vec[3], const float normal[3]);
void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]);
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index 041679ef876..471d875c9af 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -55,6 +55,8 @@ void BLI_rcti_do_minmax_v(struct rcti *rect, const int xy[2]);
void BLI_rctf_do_minmax_v(struct rctf *rect, const float xy[2]);
void BLI_rctf_transform_pt_v(const rctf *dst, const rctf *src, float xy_dst[2], const float xy_src[2]);
+void BLI_rctf_transform_calc_m4_pivot_min_ex(const rctf *dst, const rctf *src, float matrix[4][4], uint x, uint y);
+void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4]);
void BLI_rctf_translate(struct rctf *rect, float x, float y);
void BLI_rcti_translate(struct rcti *rect, int x, int y);
@@ -97,6 +99,7 @@ void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2);
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src);
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src);
void BLI_rcti_rctf_copy_floor(struct rcti *dst, const struct rctf *src);
+void BLI_rcti_rctf_copy_round(struct rcti *dst, const struct rctf *src);
void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle);
diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h
index 222005ee92e..d54f2a7bab2 100644
--- a/source/blender/blenlib/BLI_stack.h
+++ b/source/blender/blenlib/BLI_stack.h
@@ -30,6 +30,10 @@
#include "BLI_compiler_attrs.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct BLI_Stack BLI_Stack;
BLI_Stack *BLI_stack_new_ex(
@@ -55,4 +59,8 @@ size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONN
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BLI_STACK_H__ */
diff --git a/source/blender/blenlib/BLI_strict_flags.h b/source/blender/blenlib/BLI_strict_flags.h
index 964ee06469d..86b7285655e 100644
--- a/source/blender/blenlib/BLI_strict_flags.h
+++ b/source/blender/blenlib/BLI_strict_flags.h
@@ -30,6 +30,8 @@
#ifdef __GNUC__
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
# pragma GCC diagnostic error "-Wsign-compare"
+# endif
+# if __GNUC__ >= 6 /* gcc6+ only */
# pragma GCC diagnostic error "-Wconversion"
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408
diff --git a/source/blender/blenlib/BLI_string_utils.h b/source/blender/blenlib/BLI_string_utils.h
index bb19ed574bb..63c1e0344ad 100644
--- a/source/blender/blenlib/BLI_string_utils.h
+++ b/source/blender/blenlib/BLI_string_utils.h
@@ -39,6 +39,7 @@ extern "C" {
#endif
#include "BLI_compiler_attrs.h"
+#include "BLI_variadic_defines.h"
struct ListBase;
@@ -49,6 +50,24 @@ size_t BLI_split_name_num(char *left, int *nr, const char *name, const char deli
void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, const size_t str_len);
void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, const size_t str_len);
+/* Join strings, return newly allocated string. */
+char *BLI_string_join_arrayN(
+ const char *strings[], uint strings_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+char *BLI_string_join_array_by_sep_charN(
+ char sep, const char *strings[], uint strings_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+char *BLI_string_join_array_by_sep_char_with_tableN(
+ char sep, char *table[], const char *strings[], uint strings_len) ATTR_NONNULL();
+/* Take multiple arguments, pass as (array, length). */
+#define BLI_string_joinN(...) \
+ BLI_string_join_arrayN( \
+ ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+#define BLI_string_join_by_sep_charN(sep, ...) \
+ BLI_string_join_array_by_sep_charN( \
+ sep, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+#define BLI_string_join_by_sep_char_with_tableN(sep, table, ...) \
+ BLI_string_join_array_by_sep_char_with_tableN( \
+ sep, table, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+
void BLI_string_flip_side_name(char *r_name, const char *from_name, const bool strip_number, const size_t name_len);
bool BLI_uniquename_cb(
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index c3c587275e1..721327d26a8 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -106,6 +106,13 @@ void *BLI_task_pool_userdata(TaskPool *pool);
/* optional mutex to use from run function */
ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
+/* Delayed push, use that to reduce thread overhead by accumulating
+ * all new tasks into local queue first and pushing it to scheduler
+ * from within a single mutex lock.
+ */
+void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id);
+void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id);
+
/* Parallel for routines */
typedef void (*TaskParallelRangeFunc)(void *userdata, const int iter);
typedef void (*TaskParallelRangeFuncEx)(void *userdata, void *userdata_chunk, const int iter, const int thread_id);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 746eb922c65..ae2f948a284 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -39,35 +39,12 @@ extern "C" {
/* avoid many includes for now */
#include "BLI_sys_types.h"
#include "BLI_compiler_compat.h"
+#include "BLI_variadic_defines.h"
#ifndef NDEBUG /* for BLI_assert */
#include <stdio.h>
#endif
-
-/* varargs macros (keep first so others can use) */
-/* --- internal helpers --- */
-#define _VA_NARGS_GLUE(x, y) x y
-#define _VA_NARGS_RETURN_COUNT(\
- _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10_, _11_, _12_, _13_, _14_, _15_, _16_, \
- _17_, _18_, _19_, _20_, _21_, _22_, _23_, _24_, _25_, _26_, _27_, _28_, _29_, _30_, _31_, _32_, \
- _33_, _34_, _35_, _36_, _37_, _38_, _39_, _40_, _41_, _42_, _43_, _44_, _45_, _46_, _47_, _48_, \
- _49_, _50_, _51_, _52_, _53_, _54_, _55_, _56_, _57_, _58_, _59_, _60_, _61_, _62_, _63_, _64_, \
- count, ...) count
-#define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args
-/* 64 args max */
-#define _VA_NARGS_COUNT(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
- 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \
- 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, \
- 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
- 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
-#define _VA_NARGS_OVERLOAD_MACRO2(name, count) name##count
-#define _VA_NARGS_OVERLOAD_MACRO1(name, count) _VA_NARGS_OVERLOAD_MACRO2(name, count)
-#define _VA_NARGS_OVERLOAD_MACRO(name, count) _VA_NARGS_OVERLOAD_MACRO1(name, count)
-/* --- expose for re-use --- */
-#define VA_NARGS_CALL_OVERLOAD(name, ...) \
- _VA_NARGS_GLUE(_VA_NARGS_OVERLOAD_MACRO(name, _VA_NARGS_COUNT(__VA_ARGS__)), (__VA_ARGS__))
-
/* useful for finding bad use of min/max */
#if 0
/* gcc only */
diff --git a/source/blender/blenlib/BLI_variadic_defines.h b/source/blender/blenlib/BLI_variadic_defines.h
new file mode 100644
index 00000000000..a2ff8ee09e7
--- /dev/null
+++ b/source/blender/blenlib/BLI_variadic_defines.h
@@ -0,0 +1,50 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_VARIADIC_DEFINES_H__
+#define __BLI_VARIADIC_DEFINES_H__
+
+/** \file BLI_variadic_defines.h
+ * \ingroup bli
+ */
+
+/* --- internal helpers --- */
+#define _VA_NARGS_GLUE(x, y) x y
+#define _VA_NARGS_RETURN_COUNT(\
+ _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10_, _11_, _12_, _13_, _14_, _15_, _16_, \
+ _17_, _18_, _19_, _20_, _21_, _22_, _23_, _24_, _25_, _26_, _27_, _28_, _29_, _30_, _31_, _32_, \
+ _33_, _34_, _35_, _36_, _37_, _38_, _39_, _40_, _41_, _42_, _43_, _44_, _45_, _46_, _47_, _48_, \
+ _49_, _50_, _51_, _52_, _53_, _54_, _55_, _56_, _57_, _58_, _59_, _60_, _61_, _62_, _63_, _64_, \
+ count, ...) count
+#define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args
+#define _VA_NARGS_OVERLOAD_MACRO2(name, count) name##count
+#define _VA_NARGS_OVERLOAD_MACRO1(name, count) _VA_NARGS_OVERLOAD_MACRO2(name, count)
+#define _VA_NARGS_OVERLOAD_MACRO(name, count) _VA_NARGS_OVERLOAD_MACRO1(name, count)
+/* --- expose for re-use --- */
+/* 64 args max */
+#define VA_NARGS_COUNT(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
+ 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \
+ 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, \
+ 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
+ 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
+#define VA_NARGS_CALL_OVERLOAD(name, ...) \
+ _VA_NARGS_GLUE(_VA_NARGS_OVERLOAD_MACRO(name, VA_NARGS_COUNT(__VA_ARGS__)), (__VA_ARGS__))
+
+#endif /* __BLI_VARIADIC_DEFINES_H__ */
diff --git a/source/blender/blenlib/BLI_vfontdata.h b/source/blender/blenlib/BLI_vfontdata.h
index 8a7079b6c5f..0cd50319a33 100644
--- a/source/blender/blenlib/BLI_vfontdata.h
+++ b/source/blender/blenlib/BLI_vfontdata.h
@@ -52,8 +52,10 @@ typedef struct VChar {
} VChar;
VFontData *BLI_vfontdata_from_freetypefont(struct PackedFile *pf);
+VFontData *BLI_vfontdata_copy(const VFontData *vfont_src, const int flag);
VChar *BLI_vfontchar_from_freetypefont(struct VFont *vfont, unsigned long character);
+VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int flag);
#endif
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index fcb02a86a84..f42848eec8f 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -205,6 +205,7 @@ set(SRC
BLI_timecode.h
BLI_utildefines.h
BLI_uvproject.h
+ BLI_variadic_defines.h
BLI_vfontdata.h
BLI_voronoi.h
BLI_voxel.h
diff --git a/source/blender/blenlib/intern/BLI_dial.c b/source/blender/blenlib/intern/BLI_dial.c
index cfbb52847fd..89f18fa10b4 100644
--- a/source/blender/blenlib/intern/BLI_dial.c
+++ b/source/blender/blenlib/intern/BLI_dial.c
@@ -46,7 +46,7 @@ struct Dial {
};
-Dial *BLI_dial_initialize(float start_position[2], float threshold)
+Dial *BLI_dial_initialize(const float start_position[2], float threshold)
{
Dial *dial = MEM_callocN(sizeof(Dial), "dial");
@@ -56,7 +56,7 @@ Dial *BLI_dial_initialize(float start_position[2], float threshold)
return dial;
}
-float BLI_dial_angle(Dial *dial, float current_position[2])
+float BLI_dial_angle(Dial *dial, const float current_position[2])
{
float current_direction[2];
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index d1fe3557801..1b2a27e33d8 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -116,6 +116,12 @@ struct GHash {
};
+/* -------------------------------------------------------------------- */
+/* GHash API */
+
+/** \name Internal Utility API
+ * \{ */
+
BLI_INLINE void ghash_entry_copy(
GHash *gh_dst, Entry *dst, GHash *gh_src, Entry *src,
GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
@@ -132,12 +138,6 @@ BLI_INLINE void ghash_entry_copy(
}
}
-/* -------------------------------------------------------------------- */
-/* GHash API */
-
-/** \name Internal Utility API
- * \{ */
-
/**
* Get the full hash for a key.
*/
@@ -763,6 +763,28 @@ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreef
}
/**
+ * Replaces the key of an item in the \a gh.
+ *
+ * Use when a key is re-allocated or it's memory location is changed.
+ *
+ * \returns The previous key or NULL if not found, the caller may free if it's needed.
+ */
+void *BLI_ghash_replace_key(GHash *gh, void *key)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
+ if (e != NULL) {
+ void *key_prev = e->e.key;
+ e->e.key = key;
+ return key_prev;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/**
* Lookup the value of \a key in \a gh.
*
* \param key The key to lookup.
@@ -1434,6 +1456,18 @@ bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp)
return ghash_insert_safe_keyonly((GHash *)gs, key, true, keyfreefp);
}
+/**
+ * Replaces the key to the set if it's found.
+ * Matching #BLI_ghash_replace_key
+ *
+ * \returns The old key or NULL if not found.
+ */
+void *BLI_gset_replace_key(GSet *gs, void *key)
+{
+ return BLI_ghash_replace_key((GHash *)gs, key);
+}
+
+
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
{
return BLI_ghash_remove((GHash *)gs, key, keyfreefp, NULL);
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 857c2a5201c..e5ca53a0193 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -62,6 +62,13 @@
/* used for iterative_raycast */
// #define USE_SKIP_LINKS
+/* Use to print balanced output. */
+// #define USE_PRINT_TREE
+
+/* Check tree is valid. */
+// #define USE_VERIFY_TREE
+
+
#define MAX_TREETYPE 32
/* Setting zero so we can catch bugs in BLI_task/KDOPBVH.
@@ -571,10 +578,12 @@ static void node_join(BVHTree *tree, BVHNode *node)
}
}
-/*
+#ifdef USE_PRINT_TREE
+
+/**
* Debug and information functions
*/
-#if 0
+
static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth)
{
int i;
@@ -597,30 +606,29 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth)
static void bvhtree_info(BVHTree *tree)
{
- printf("BVHTree info\n");
- printf("tree_type = %d, axis = %d, epsilon = %f\n",
+ printf("BVHTree Info: tree_type = %d, axis = %d, epsilon = %f\n",
tree->tree_type, tree->axis, tree->epsilon);
printf("nodes = %d, branches = %d, leafs = %d\n",
tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf);
- printf("Memory per node = %ldbytes\n",
- sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis);
- printf("BV memory = %dbytes\n",
- (int)MEM_allocN_len(tree->nodebv));
-
- printf("Total memory = %ldbytes\n", sizeof(BVHTree) +
- MEM_allocN_len(tree->nodes) +
- MEM_allocN_len(tree->nodearray) +
- MEM_allocN_len(tree->nodechild) +
- MEM_allocN_len(tree->nodebv));
-
-// bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0);
+ printf("Memory per node = %ubytes\n",
+ (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis));
+ printf("BV memory = %ubytes\n",
+ (uint)MEM_allocN_len(tree->nodebv));
+
+ printf("Total memory = %ubytes\n",
+ (uint)(sizeof(BVHTree) +
+ MEM_allocN_len(tree->nodes) +
+ MEM_allocN_len(tree->nodearray) +
+ MEM_allocN_len(tree->nodechild) +
+ MEM_allocN_len(tree->nodebv)));
+
+ bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0);
}
-#endif
+#endif /* USE_PRINT_TREE */
-#if 0
+#ifdef USE_VERIFY_TREE
-
-static void verify_tree(BVHTree *tree)
+static void bvhtree_verify(BVHTree *tree)
{
int i, j, check = 0;
@@ -661,7 +669,7 @@ static void verify_tree(BVHTree *tree)
printf("branches: %d, leafs: %d, total: %d\n",
tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf);
}
-#endif
+#endif /* USE_VERIFY_TREE */
/* Helper data and structures to build a min-leaf generalized implicit tree
* This code can be easily reduced
@@ -907,16 +915,24 @@ static void non_recursive_bvh_div_nodes(
/* Loop tree levels (log N) loops */
for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) {
const int first_of_next_level = i * tree_type + tree_offset;
- const int end_j = min_ii(first_of_next_level, num_branches + 1); /* index of last branch on this level */
+ const int i_stop = min_ii(first_of_next_level, num_branches + 1); /* index of last branch on this level */
/* Loop all branches on this level */
cb_data.first_of_next_level = first_of_next_level;
cb_data.i = i;
cb_data.depth = depth;
- BLI_task_parallel_range(
- i, end_j, &cb_data, non_recursive_bvh_div_nodes_task_cb,
- num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD);
+ if (true) {
+ BLI_task_parallel_range(
+ i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb,
+ num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD);
+ }
+ else {
+ /* Less hassle for debugging. */
+ for (int i_task = i; i_task < i_stop; i_task++) {
+ non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task);
+ }
+ }
}
}
@@ -1050,7 +1066,13 @@ void BLI_bvhtree_balance(BVHTree *tree)
build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL);
#endif
- /* bvhtree_info(tree); */
+#ifdef USE_VERIFY_TREE
+ bvhtree_verify(tree);
+#endif
+
+#ifdef USE_PRINT_TREE
+ bvhtree_info(tree);
+#endif
}
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c
index a81f9b28b83..84ac339cc4d 100644
--- a/source/blender/blenlib/intern/BLI_kdtree.c
+++ b/source/blender/blenlib/intern/BLI_kdtree.c
@@ -674,3 +674,123 @@ finally:
if (stack != defaultstack)
MEM_freeN(stack);
}
+
+/**
+ * Use when we want to loop over nodes ordered by index.
+ * Requires indices to be aligned with nodes.
+ */
+static uint *kdtree_order(const KDTree *tree)
+{
+ const KDTreeNode *nodes = tree->nodes;
+ uint *order = MEM_mallocN(sizeof(uint) * tree->totnode, __func__);
+ for (uint i = 0; i < tree->totnode; i++) {
+ order[nodes[i].index] = i;
+ }
+ return order;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name BLI_kdtree_calc_duplicates_fast
+ * \{ */
+
+struct DeDuplicateParams {
+ /* Static */
+ const KDTreeNode *nodes;
+ float range;
+ float range_sq;
+ int *duplicates;
+ int *duplicates_found;
+
+ /* Per Search */
+ float search_co[3];
+ int search;
+};
+
+static void deduplicate_recursive(const struct DeDuplicateParams *p, uint i)
+{
+ const KDTreeNode *node = &p->nodes[i];
+ if (p->search_co[node->d] + p->range <= node->co[node->d]) {
+ if (node->left != KD_NODE_UNSET) {
+ deduplicate_recursive(p, node->left);
+ }
+ }
+ else if (p->search_co[node->d] - p->range >= node->co[node->d]) {
+ if (node->right != KD_NODE_UNSET) {
+ deduplicate_recursive(p, node->right);
+ }
+ }
+ else {
+ if ((p->search != node->index) && (p->duplicates[node->index] == -1)) {
+ if (compare_len_squared_v3v3(node->co, p->search_co, p->range_sq)) {
+ p->duplicates[node->index] = (int)p->search;
+ *p->duplicates_found += 1;
+ }
+ }
+ if (node->left != KD_NODE_UNSET) {
+ deduplicate_recursive(p, node->left);
+ }
+ if (node->right != KD_NODE_UNSET) {
+ deduplicate_recursive(p, node->right);
+ }
+ }
+}
+
+/**
+ * Find duplicate points in \a range.
+ * Favors speed over quality since it doesn't find the best target vertex for merging.
+ * Nodes are looped over, duplicates are added when found.
+ * Nevertheless results are predictable.
+ *
+ * \param range: Coordinates in this range are candidates to be merged.
+ * \param use_index_order: Loop over the coordinates ordered by #KDTreeNode.index
+ * At the expense of some performance, this ensures the layout of the tree doesn't influence
+ * the iteration order.
+ * \param duplicates: An array of int's the length of #KDTree.totnode
+ * Values initialized to -1 are candidates to me merged.
+ * Setting the index to it's own position in the array prevents it from being touched,
+ * although it can still be used as a target.
+ * \returns The numebr of merges found (includes any merges already in the \a duplicates array).
+ *
+ * \note Merging is always a single step (target indices wont be marked for merging).
+ */
+int BLI_kdtree_calc_duplicates_fast(
+ const KDTree *tree, const float range, bool use_index_order,
+ int *duplicates)
+{
+ int found = 0;
+ struct DeDuplicateParams p = {
+ .nodes = tree->nodes,
+ .range = range,
+ .range_sq = range * range,
+ .duplicates = duplicates,
+ .duplicates_found = &found,
+ };
+
+ if (use_index_order) {
+ uint *order = kdtree_order(tree);
+ for (uint i = 0; i < tree->totnode; i++) {
+ const uint node_index = order[i];
+ const int index = (int)i;
+ if (ELEM(duplicates[index], -1, index)) {
+ p.search = index;
+ copy_v3_v3(p.search_co, tree->nodes[node_index].co);
+ deduplicate_recursive(&p, tree->root);
+ }
+ }
+ MEM_freeN(order);
+ }
+ else {
+ for (uint i = 0; i < tree->totnode; i++) {
+ const uint node_index = i;
+ const int index = p.nodes[node_index].index;
+ if (ELEM(duplicates[index], -1, index)) {
+ p.search = index;
+ copy_v3_v3(p.search_co, tree->nodes[node_index].co);
+ deduplicate_recursive(&p, tree->root);
+ }
+ }
+ }
+ return found;
+}
+
+/** \} */
diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c
index 5d1b2433084..d3a63aceb89 100644
--- a/source/blender/blenlib/intern/array_store.c
+++ b/source/blender/blenlib/intern/array_store.c
@@ -1560,7 +1560,7 @@ BArrayState *BLI_array_store_state_add(
const void *data, const size_t data_len,
const BArrayState *state_reference)
{
- /* ensure we're aligned to the stride */
+ /* ensure we're aligned to the stride */
BLI_assert((data_len % bs->info.chunk_stride) == 0);
#ifdef USE_PARANOID_CHECKS
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index 8719c92a2a6..e990f0b663c 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -481,6 +481,22 @@ VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf)
return vfd;
}
+static void *vfontdata_copy_characters_value_cb(const void *src)
+{
+ return BLI_vfontchar_copy(src, 0);
+}
+
+VFontData *BLI_vfontdata_copy(const VFontData *vfont_src, const int UNUSED(flag))
+{
+ VFontData *vfont_dst = MEM_dupallocN(vfont_src);
+
+ if (vfont_src->characters != NULL) {
+ vfont_dst->characters = BLI_ghash_copy(vfont_src->characters, NULL, vfontdata_copy_characters_value_cb);
+ }
+
+ return vfont_dst;
+}
+
VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
{
VChar *che = NULL;
@@ -503,6 +519,20 @@ VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
return che;
}
+/* Yeah, this is very bad... But why is this in BLI in the first place, since it uses Nurb data?
+ * Anyway, do not feel like duplicating whole Nurb copy code here, so unless someone has a better idea... */
+#include "../../blenkernel/BKE_curve.h"
+
+VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int UNUSED(flag))
+{
+ VChar *vchar_dst = MEM_dupallocN(vchar_src);
+
+ BLI_listbase_clear(&vchar_dst->nurbsbase);
+ BKE_nurbList_duplicate(&vchar_dst->nurbsbase, &vchar_src->nurbsbase);
+
+ return vchar_dst;
+}
+
#if 0
/* Freetype2 Outline struct */
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 8d2d80c2a35..6574c001a23 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -314,6 +314,21 @@ MINLINE int signum_i(float a)
else return 0;
}
+/** Returns number of (base ten) *significant* digits of integer part of given float
+ * (negative in case of decimal-only floats, 0.01 returns -1 e.g.). */
+MINLINE int integer_digits_f(const float f)
+{
+ return (f == 0.0f) ? 0 : (int)floor(log10(fabs(f))) + 1;
+}
+
+/** Returns number of (base ten) *significant* digits of integer part of given double
+ * (negative in case of decimal-only floats, 0.01 returns -1 e.g.). */
+MINLINE int integer_digits_d(const double d)
+{
+ return (d == 0.0) ? 0 : (int)floor(log10(fabs(d))) + 1;
+}
+
+
/* Internal helpers for SSE2 implementation.
*
* NOTE: Are to be called ONLY from inside `#ifdef __SSE2__` !!!
diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
index 048ab71c6dc..dc3874f83a2 100644
--- a/source/blender/blenlib/intern/math_color_blend_inline.c
+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
@@ -444,7 +444,7 @@ MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const ch
else if (src2[i] == 0) {
temp = 0;
}
- else if (src2[i] > 127) {
+ else if (src2[i] > 127) {
temp = min_ii(((src1[i]) * 255) / (2 * (255 - src2[i])), 255);
}
else {
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 58699a0593b..53fcf9c745c 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -572,8 +572,8 @@ float dist_squared_to_ray_v3(
}
/**
* Find the closest point in a seg to a ray and return the distance squared.
- * \param r_point : Is the point on segment closest to ray (or to ray_origin if the ray and the segment are parallel).
- * \param depth: the distance of r_point projection on ray to the ray_origin.
+ * \param r_point: Is the point on segment closest to ray (or to ray_origin if the ray and the segment are parallel).
+ * \param r_depth: the distance of r_point projection on ray to the ray_origin.
*/
float dist_squared_ray_to_seg_v3(
const float ray_origin[3], const float ray_direction[3],
@@ -765,18 +765,29 @@ int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], co
return ISECT_LINE_LINE_NONE;
}
-/* get intersection point of two 2D segments and return intersection type:
- * -1: collinear
- * 1: intersection
+/**
+ * Get intersection point of two 2D segments.
+ *
+ * \param endpoint_bias: Bias to use when testing for end-point overlap.
+ * A positive value considers intersections that extend past the endpoints,
+ * negative values contract the endpoints.
+ * Note the bias is applied to a 0-1 factor, not scaled to the length of segments.
+ *
+ * \returns intersection type:
+ * - -1: collinear.
+ * - 1: intersection.
+ * - 0: no intersection.
*/
-int isect_seg_seg_v2_point(
+int isect_seg_seg_v2_point_ex(
const float v0[2], const float v1[2],
const float v2[2], const float v3[2],
+ const float endpoint_bias,
float r_vi[2])
{
float s10[2], s32[2], s30[2], d;
const float eps = 1e-6f;
- const float eps_sq = eps * eps;
+ const float endpoint_min = -endpoint_bias;
+ const float endpoint_max = endpoint_bias + 1.0f;
sub_v2_v2v2(s10, v1, v0);
sub_v2_v2v2(s32, v3, v2);
@@ -790,8 +801,8 @@ int isect_seg_seg_v2_point(
u = cross_v2v2(s30, s32) / d;
v = cross_v2v2(s10, s30) / d;
- if ((u >= -eps && u <= 1.0f + eps) &&
- (v >= -eps && v <= 1.0f + eps))
+ if ((u >= endpoint_min && u <= endpoint_max) &&
+ (v >= endpoint_min && v <= endpoint_max))
{
/* intersection */
float vi_test[2];
@@ -810,7 +821,7 @@ int isect_seg_seg_v2_point(
sub_v2_v2v2(s_vi_v2, vi_test, v2);
v = (dot_v2v2(s32, s_vi_v2) / dot_v2v2(s32, s32));
#endif
- if (v >= -eps && v <= 1.0f + eps) {
+ if (v >= endpoint_min && v <= endpoint_max) {
copy_v2_v2(r_vi, vi_test);
return 1;
}
@@ -828,7 +839,7 @@ int isect_seg_seg_v2_point(
float u_a, u_b;
if (equals_v2v2(v0, v1)) {
- if (len_squared_v2v2(v2, v3) > eps_sq) {
+ if (len_squared_v2v2(v2, v3) > SQUARE(eps)) {
/* use non-point segment as basis */
SWAP(const float *, v0, v2);
SWAP(const float *, v1, v3);
@@ -855,7 +866,7 @@ int isect_seg_seg_v2_point(
if (u_a > u_b)
SWAP(float, u_a, u_b);
- if (u_a > 1.0f + eps || u_b < -eps) {
+ if (u_a > endpoint_max || u_b < endpoint_min) {
/* non-overlapping segments */
return -1;
}
@@ -871,6 +882,15 @@ int isect_seg_seg_v2_point(
}
}
+int isect_seg_seg_v2_point(
+ const float v0[2], const float v1[2],
+ const float v2[2], const float v3[2],
+ float r_vi[2])
+{
+ const float endpoint_bias = 1e-6f;
+ return isect_seg_seg_v2_point_ex(v0, v1, v2, v3, endpoint_bias, r_vi);
+}
+
bool isect_seg_seg_v2_simple(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
{
#define CCW(A, B, C) \
@@ -1828,7 +1848,7 @@ bool isect_tri_tri_epsilon_v3(
(range[0].max < range[1].min)) == 0)
{
if (r_i1 && r_i2) {
- project_plane_v3_v3v3(plane_co, plane_co, plane_no);
+ project_plane_normalized_v3_v3v3(plane_co, plane_co, plane_no);
madd_v3_v3v3fl(r_i1, plane_co, plane_no, max_ff(range[0].min, range[1].min));
madd_v3_v3v3fl(r_i2, plane_co, plane_no, min_ff(range[0].max, range[1].max));
}
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 9a60c670ec7..d1a219c196a 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -1663,6 +1663,9 @@ void rotate_m4(float mat[4][4], const char axis, const float angle)
mat[0][col] = temp;
}
break;
+ default:
+ BLI_assert(0);
+ break;
}
}
@@ -1738,16 +1741,16 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa
/**
* A polar-decomposition-based interpolation between matrix A and matrix B.
*
- * \note This code is about five times slower as the 'naive' interpolation done by \a blend_m3_m3m3
- * (it typically remains below 2 usec on an average i74700, while \a blend_m3_m3m3 remains below 0.4 usec).
+ * \note This code is about five times slower as the 'naive' interpolation done by #blend_m3_m3m3
+ * (it typically remains below 2 usec on an average i74700, while #blend_m3_m3m3 remains below 0.4 usec).
* However, it gives expected results even with non-uniformaly scaled matrices, see T46418 for an example.
*
* Based on "Matrix Animation and Polar Decomposition", by Ken Shoemake & Tom Duff
*
- * @return R the interpolated matrix.
- * @param A the intput matrix which is totally effective with \a t = 0.0.
- * @param B the intput matrix which is totally effective with \a t = 1.0.
- * @param t the interpolation factor.
+ * \param R: Resulting interpolated matrix.
+ * \param A: Input matrix which is totally effective with `t = 0.0`.
+ * \param B: Input matrix which is totally effective with `t = 1.0`.
+ * \param t: Interpolation factor.
*/
void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
{
@@ -1777,12 +1780,12 @@ void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
}
/**
- * Complete transform matrix interpolation, based on polar-decomposition-based interpolation from interp_m3_m3m3.
+ * Complete transform matrix interpolation, based on polar-decomposition-based interpolation from #interp_m3_m3m3.
*
- * @return R the interpolated matrix.
- * @param A the intput matrix which is totally effective with \a t = 0.0.
- * @param B the intput matrix which is totally effective with \a t = 1.0.
- * @param t the interpolation factor.
+ * \param R: Resulting interpolated matrix.
+ * \param A: Input matrix which is totally effective with `t = 0.0`.
+ * \param B: Input matrix which is totally effective with `t = 1.0`.
+ * \param t: Interpolation factor.
*/
void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
{
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index fa58fe368d1..23bd5e60e22 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -2147,38 +2147,37 @@ BLI_INLINE int _axis_signed(const int axis)
return (axis < 3) ? axis : axis - 3;
}
-/*
+/**
* Each argument us an axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z']
* where the first 2 are a source and the second 2 are the target.
*/
-int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up,
- float r_mat[3][3])
+bool mat3_from_axis_conversion(
+ int src_forward, int src_up, int dst_forward, int dst_up,
+ float r_mat[3][3])
{
// from functools import reduce
int value;
- unsigned int i;
- if (from_forward == to_forward && from_up == to_up) {
+ if (src_forward == dst_forward && src_up == dst_up) {
unit_m3(r_mat);
return false;
}
- if ((_axis_signed(from_forward) == _axis_signed(from_up)) ||
- (_axis_signed(to_forward) == _axis_signed(to_up)))
+ if ((_axis_signed(src_forward) == _axis_signed(src_up)) ||
+ (_axis_signed(dst_forward) == _axis_signed(dst_up)))
{
/* we could assert here! */
unit_m3(r_mat);
return false;
}
- value = ((from_forward << (0 * 3)) |
- (from_up << (1 * 3)) |
- (to_forward << (2 * 3)) |
- (to_up << (3 * 3)));
+ value = ((src_forward << (0 * 3)) |
+ (src_up << (1 * 3)) |
+ (dst_forward << (2 * 3)) |
+ (dst_up << (3 * 3)));
- for (i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) {
- unsigned int j;
- for (j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) {
+ for (uint i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) {
+ for (uint j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) {
if (_axis_convert_lut[i][j] == value) {
copy_m3_m3(r_mat, _axis_convert_matrix[i]);
return true;
@@ -2189,3 +2188,27 @@ int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int
// BLI_assert(0);
return false;
}
+
+/**
+ * Use when the second axis can be guessed.
+ */
+bool mat3_from_axis_conversion_single(
+ int src_axis, int dst_axis,
+ float r_mat[3][3])
+{
+ if (src_axis == dst_axis) {
+ unit_m3(r_mat);
+ return false;
+ }
+
+ /* Pick predictable next axis. */
+ int src_axis_next = (src_axis + 1) % 3;
+ int dst_axis_next = (dst_axis + 1) % 3;
+
+ if ((src_axis < 3) != (dst_axis < 3)) {
+ /* Flip both axis so matrix sign remains positive. */
+ dst_axis_next += 3;
+ }
+
+ return mat3_from_axis_conversion(src_axis, src_axis_next, dst_axis, dst_axis_next, r_mat);
+}
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 37897e2cd32..5f44c93e169 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -518,38 +518,27 @@ float angle_normalized_v2v2(const float v1[2], const float v2[2])
}
/**
- * angle between 2 vectors defined by 3 coords, about an axis. */
-float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
+ * Angle between 2 vectors, about an axis (axis can be considered a plane).
+ */
+float angle_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3])
{
- float v1_proj[3], v2_proj[3], tproj[3];
-
- sub_v3_v3v3(v1_proj, v1, v2);
- sub_v3_v3v3(v2_proj, v3, v2);
+ float v1_proj[3], v2_proj[3];
/* project the vectors onto the axis */
- project_v3_v3v3(tproj, v1_proj, axis);
- sub_v3_v3(v1_proj, tproj);
-
- project_v3_v3v3(tproj, v2_proj, axis);
- sub_v3_v3(v2_proj, tproj);
+ project_plane_normalized_v3_v3v3(v1_proj, v1, axis);
+ project_plane_normalized_v3_v3v3(v2_proj, v2, axis);
return angle_v3v3(v1_proj, v2_proj);
}
-float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
+float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3])
{
float v1_proj[3], v2_proj[3], tproj[3];
float angle;
- sub_v3_v3v3(v1_proj, v1, v2);
- sub_v3_v3v3(v2_proj, v3, v2);
-
/* project the vectors onto the axis */
- project_v3_v3v3(tproj, v1_proj, axis);
- sub_v3_v3(v1_proj, tproj);
-
- project_v3_v3v3(tproj, v2_proj, axis);
- sub_v3_v3(v2_proj, tproj);
+ project_plane_normalized_v3_v3v3(v1_proj, v1, axis);
+ project_plane_normalized_v3_v3v3(v2_proj, v2, axis);
angle = angle_v3v3(v1_proj, v2_proj);
@@ -562,6 +551,29 @@ float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const
return angle;
}
+/**
+ * Angle between 2 vectors defined by 3 coords, about an axis (axis can be considered a plane).
+ */
+float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
+{
+ float vec1[3], vec2[3];
+
+ sub_v3_v3v3(vec1, v1, v2);
+ sub_v3_v3v3(vec2, v3, v2);
+
+ return angle_on_axis_v3v3_v3(vec1, vec2, axis);
+}
+
+float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
+{
+ float vec1[3], vec2[3];
+
+ sub_v3_v3v3(vec1, v1, v2);
+ sub_v3_v3v3(vec2, v3, v2);
+
+ return angle_signed_on_axis_v3v3_v3(vec1, vec2, axis);
+}
+
void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3])
{
float ed1[3], ed2[3], ed3[3];
@@ -640,6 +652,31 @@ void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
}
/**
+ * Project \a p onto a unit length \a v_proj
+ */
+void project_v2_v2v2_normalized(float out[2], const float p[2], const float v_proj[2])
+{
+ BLI_ASSERT_UNIT_V2(v_proj);
+ const float mul = dot_v2v2(p, v_proj);
+
+ out[0] = mul * v_proj[0];
+ out[1] = mul * v_proj[1];
+}
+
+/**
+ * Project \a p onto a unit length \a v_proj
+ */
+void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_proj[3])
+{
+ BLI_ASSERT_UNIT_V3(v_proj);
+ const float mul = dot_v3v3(p, v_proj);
+
+ out[0] = mul * v_proj[0];
+ out[1] = mul * v_proj[1];
+ out[2] = mul * v_proj[2];
+}
+
+/**
* In this case plane is a 3D vector only (no 4th component).
*
* Projecting will make \a c a copy of \a v orthogonal to \a v_plane.
@@ -669,6 +706,25 @@ void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2
out[1] = p[1] - (mul * v_plane[1]);
}
+void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
+{
+ BLI_ASSERT_UNIT_V3(v_plane);
+ const float mul = dot_v3v3(p, v_plane);
+
+ out[0] = p[0] - (mul * v_plane[0]);
+ out[1] = p[1] - (mul * v_plane[1]);
+ out[2] = p[2] - (mul * v_plane[2]);
+}
+
+void project_plane_normalized_v2_v2v2(float out[2], const float p[2], const float v_plane[2])
+{
+ BLI_ASSERT_UNIT_V2(v_plane);
+ const float mul = dot_v2v2(p, v_plane);
+
+ out[0] = p[0] - (mul * v_plane[0]);
+ out[1] = p[1] - (mul * v_plane[1]);
+}
+
/* project a vector on a plane defined by normal and a plane point p */
void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3])
{
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index f834c5b4c74..86c24307ae2 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -1394,6 +1394,11 @@ static float voronoi_CrS(float x, float y, float z)
/* returns unsigned cellnoise */
static float cellNoiseU(float x, float y, float z)
{
+ /* avoid precision issues on unit coordinates */
+ x = (x + 0.000001f)*1.00001f;
+ y = (y + 0.000001f)*1.00001f;
+ z = (z + 0.000001f)*1.00001f;
+
int xi = (int)(floor(x));
int yi = (int)(floor(y));
int zi = (int)(floor(z));
@@ -1411,6 +1416,11 @@ float cellNoise(float x, float y, float z)
/* returns a vector/point/color in ca, using point hasharray directly */
void cellNoiseV(float x, float y, float z, float ca[3])
{
+ /* avoid precision issues on unit coordinates */
+ x = (x + 0.000001f)*1.00001f;
+ y = (y + 0.000001f)*1.00001f;
+ z = (z + 0.000001f)*1.00001f;
+
int xi = (int)(floor(x));
int yi = (int)(floor(y));
int zi = (int)(floor(z));
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index fd24a00156d..3adc6b30f6e 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -32,6 +32,7 @@
* A minimalist lib for functions doing stuff with rectangle structs.
*/
+#include <stdlib.h>
#include <stdio.h>
#include <math.h>
@@ -41,6 +42,9 @@
#include "DNA_vec_types.h"
#include "BLI_rect.h"
+/* avoid including BLI_math */
+static void unit_m4(float m[4][4]);
+
/**
* Determine if a rect is empty. An empty
* rect is one with a zero (or negative)
@@ -405,6 +409,31 @@ void BLI_rctf_transform_pt_v(const rctf *dst, const rctf *src, float xy_dst[2],
xy_dst[1] = dst->ymin + ((dst->ymax - dst->ymin) * xy_dst[1]);
}
+/**
+ * Calculate a 4x4 matrix representing the transformation between two rectangles.
+ *
+ * \note Multiplying a vector by this matrix does *not* give the same value as #BLI_rctf_transform_pt_v.
+ */
+void BLI_rctf_transform_calc_m4_pivot_min_ex(
+ const rctf *dst, const rctf *src, float matrix[4][4],
+ uint x, uint y)
+{
+ BLI_assert(x < 3 && y < 3);
+
+ unit_m4(matrix);
+
+ matrix[x][x] = BLI_rctf_size_x(src) / BLI_rctf_size_x(dst);
+ matrix[y][y] = BLI_rctf_size_y(src) / BLI_rctf_size_y(dst);
+ matrix[3][x] = (src->xmin - dst->xmin) * matrix[x][x];
+ matrix[3][y] = (src->ymin - dst->ymin) * matrix[y][y];
+}
+
+void BLI_rctf_transform_calc_m4_pivot_min(
+ const rctf *dst, const rctf *src, float matrix[4][4])
+{
+ BLI_rctf_transform_calc_m4_pivot_min_ex(dst, src, matrix, 0, 1);
+}
+
void BLI_rcti_translate(rcti *rect, int x, int y)
{
rect->xmin += x;
@@ -693,6 +722,14 @@ void BLI_rcti_rctf_copy_floor(rcti *dst, const rctf *src)
dst->ymax = floorf(src->ymax);
}
+void BLI_rcti_rctf_copy_round(rcti *dst, const rctf *src)
+{
+ dst->xmin = floorf(src->xmin + 0.5f);
+ dst->xmax = floorf(src->xmax + 0.5f);
+ dst->ymin = floorf(src->ymin + 0.5f);
+ dst->ymax = floorf(src->ymax + 0.5f);
+}
+
void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
{
dst->xmin = src->xmin;
@@ -755,3 +792,12 @@ void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle)
#undef ROTATE_SINCOS
/** \} */
+
+static void unit_m4(float m[4][4])
+{
+ m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
+ m[0][1] = m[0][2] = m[0][3] = 0.0f;
+ m[1][0] = m[1][2] = m[1][3] = 0.0f;
+ m[2][0] = m[2][1] = m[2][3] = 0.0f;
+ m[3][0] = m[3][1] = m[3][2] = 0.0f;
+}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 48280c14d7d..b819c513fbd 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -422,13 +422,13 @@ void BLI_file_free_lines(LinkNode *lines)
bool BLI_file_older(const char *file1, const char *file2)
{
#ifdef WIN32
- struct _stat st1, st2;
+ struct _stat st1, st2;
UTF16_ENCODE(file1);
UTF16_ENCODE(file2);
if (_wstat(file1_16, &st1)) return false;
- if (_wstat(file2_16, &st2)) return false;
+ if (_wstat(file2_16, &st2)) return false;
UTF16_UN_ENCODE(file2);
UTF16_UN_ENCODE(file1);
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index b7e5e3e101e..229a97a2fa7 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -167,7 +167,7 @@ utf8_error:
/**
* Remove any invalid utf-8 byte (taking into account multi-bytes sequence of course).
*
- * @return number of stripped bytes.
+ * \return number of stripped bytes.
*/
int BLI_utf8_invalid_strip(char *str, size_t length)
{
diff --git a/source/blender/blenlib/intern/string_utils.c b/source/blender/blenlib/intern/string_utils.c
index 8d91a55a5ad..a693463a302 100644
--- a/source/blender/blenlib/intern/string_utils.c
+++ b/source/blender/blenlib/intern/string_utils.c
@@ -383,3 +383,91 @@ bool BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim
return BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
}
+
+/* ------------------------------------------------------------------------- */
+/** \name Join Strings
+ *
+ * For non array versions of these functions, use the macros:
+ * - #BLI_string_joinN
+ * - #BLI_string_join_by_sep_charN
+ * - #BLI_string_join_by_sep_char_with_tableN
+ *
+ * \{ */
+
+/**
+ * Join an array of strings into a newly allocated, null terminated string.
+ */
+char *BLI_string_join_arrayN(
+ const char *strings[], uint strings_len)
+{
+ uint total_len = 1;
+ for (uint i = 0; i < strings_len; i++) {
+ total_len += strlen(strings[i]);
+ }
+ char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
+ char *c = result;
+ for (uint i = 0; i < strings_len; i++) {
+ c += BLI_strcpy_rlen(c, strings[i]);
+ }
+ return result;
+}
+
+/**
+ * A version of #BLI_string_joinN that takes a separator which can be any character including '\0'.
+ */
+char *BLI_string_join_array_by_sep_charN(
+ char sep, const char *strings[], uint strings_len)
+{
+ uint total_len = 0;
+ for (uint i = 0; i < strings_len; i++) {
+ total_len += strlen(strings[i]) + 1;
+ }
+ if (total_len == 0) {
+ total_len = 1;
+ }
+
+ char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
+ char *c = result;
+ if (strings_len != 0) {
+ for (uint i = 0; i < strings_len; i++) {
+ c += BLI_strcpy_rlen(c, strings[i]);
+ *c = sep;
+ c++;
+ }
+ c--;
+ }
+ *c = '\0';
+ return result;
+}
+
+/**
+ * A version of #BLI_string_join_array_by_sep_charN that takes a table array.
+ * The new location of each string is written into this array.
+ */
+char *BLI_string_join_array_by_sep_char_with_tableN(
+ char sep, char *table[], const char *strings[], uint strings_len)
+{
+ uint total_len = 0;
+ for (uint i = 0; i < strings_len; i++) {
+ total_len += strlen(strings[i]) + 1;
+ }
+ if (total_len == 0) {
+ total_len = 1;
+ }
+
+ char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
+ char *c = result;
+ if (strings_len != 0) {
+ for (uint i = 0; i < strings_len; i++) {
+ table[i] = c; /* <-- only difference to BLI_string_join_array_by_sep_charN. */
+ c += BLI_strcpy_rlen(c, strings[i]);
+ *c = sep;
+ c++;
+ }
+ c--;
+ }
+ *c = '\0';
+ return result;
+}
+
+/** \} */
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index eb4e6e91aee..e050f3148b8 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -52,7 +52,14 @@
*
* This allows thread to fetch next task without locking the whole queue.
*/
-#define LOCALQUEUE_SIZE 1
+#define LOCAL_QUEUE_SIZE 1
+
+/* Number of tasks which are allowed to be scheduled in a delayed manner.
+ *
+ * This allows to use less locks per graph node children schedule. More details
+ * could be found at TaskThreadLocalStorage::do_delayed_push.
+ */
+#define DELAYED_QUEUE_SIZE 4096
#ifndef NDEBUG
# define ASSERT_THREAD_ID(scheduler, thread_id) \
@@ -129,9 +136,28 @@ typedef struct TaskMemPoolStats {
#endif
typedef struct TaskThreadLocalStorage {
+ /* Memory pool for faster task allocation.
+ * The idea is to re-use memory of finished/discarded tasks by this thread.
+ */
TaskMemPool task_mempool;
+
+ /* Local queue keeps thread alive by keeping small amount of tasks ready
+ * to be picked up without causing global thread locks for synchronization.
+ */
int num_local_queue;
- Task *local_queue[LOCALQUEUE_SIZE];
+ Task *local_queue[LOCAL_QUEUE_SIZE];
+
+ /* Thread can be marked for delayed tasks push. This is helpful when it's
+ * know that lots of subsequent task pushed will happen from the same thread
+ * without "interrupting" for task execution.
+ *
+ * We try to accumulate as much tasks as possible in a local queue without
+ * any locks first, and then we push all of them into a scheduler's queue
+ * from within a single mutex lock.
+ */
+ bool do_delayed_push;
+ int num_delayed_queue;
+ Task *delayed_queue[DELAYED_QUEUE_SIZE];
} TaskThreadLocalStorage;
struct TaskPool {
@@ -378,6 +404,7 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task
BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls,
const int thread_id)
{
+ BLI_assert(!tls->do_delayed_push);
while (tls->num_local_queue > 0) {
/* We pop task from queue before handling it so handler of the task can
* push next job to the local queue.
@@ -391,6 +418,7 @@ BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls,
local_task->run(local_pool, local_task->taskdata, thread_id);
task_free(local_pool, local_task, thread_id);
}
+ BLI_assert(!tls->do_delayed_push);
}
static void *task_scheduler_thread_run(void *thread_p)
@@ -408,7 +436,9 @@ static void *task_scheduler_thread_run(void *thread_p)
TaskPool *pool = task->pool;
/* run task */
+ BLI_assert(!tls->do_delayed_push);
task->run(pool, task->taskdata, thread_id);
+ BLI_assert(!tls->do_delayed_push);
/* delete task */
task_free(pool, task, thread_id);
@@ -547,6 +577,27 @@ static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriori
BLI_mutex_unlock(&scheduler->queue_mutex);
}
+static void task_scheduler_push_all(TaskScheduler *scheduler,
+ TaskPool *pool,
+ Task **tasks,
+ int num_tasks)
+{
+ if (num_tasks == 0) {
+ return;
+ }
+
+ task_pool_num_increase(pool, num_tasks);
+
+ BLI_mutex_lock(&scheduler->queue_mutex);
+
+ for (int i = 0; i < num_tasks; i++) {
+ BLI_addhead(&scheduler->queue, tasks[i]);
+ }
+
+ BLI_condition_notify_all(&scheduler->queue_cond);
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+}
+
static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
{
Task *task, *nexttask;
@@ -714,38 +765,59 @@ void BLI_task_pool_free(TaskPool *pool)
BLI_end_threaded_malloc();
}
+BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id)
+{
+ return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work));
+}
+
static void task_pool_push(
TaskPool *pool, TaskRunFunction run, void *taskdata,
bool free_taskdata, TaskFreeFunction freedata, TaskPriority priority,
int thread_id)
{
+ /* Allocate task and fill it's properties. */
Task *task = task_alloc(pool, thread_id);
-
task->run = run;
task->taskdata = taskdata;
task->free_taskdata = free_taskdata;
task->freedata = freedata;
task->pool = pool;
-
+ /* For suspended pools we put everything yo a global queue first
+ * and exit as soon as possible.
+ *
+ * This tasks will be moved to actual execution when pool is
+ * activated by work_and_wait().
+ */
if (pool->is_suspended) {
BLI_addhead(&pool->suspended_queue, task);
atomic_fetch_and_add_z(&pool->num_suspended, 1);
return;
}
-
- if (thread_id != -1 &&
- (thread_id != pool->thread_id || pool->do_work))
- {
+ /* Populate to any local queue first, this is cheapest push ever. */
+ if (task_can_use_local_queues(pool, thread_id)) {
ASSERT_THREAD_ID(pool->scheduler, thread_id);
-
TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
- if (tls->num_local_queue < LOCALQUEUE_SIZE) {
+ /* Try to push to a local execution queue.
+ * These tasks will be picked up next.
+ */
+ if (tls->num_local_queue < LOCAL_QUEUE_SIZE) {
tls->local_queue[tls->num_local_queue] = task;
tls->num_local_queue++;
return;
}
+ /* If we are in the delayed tasks push mode, we push tasks to a
+ * temporary local queue first without any locks, and then move them
+ * to global execution queue with a single lock.
+ */
+ if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) {
+ tls->delayed_queue[tls->num_delayed_queue] = task;
+ tls->num_delayed_queue++;
+ return;
+ }
}
-
+ /* Do push to a global execution ppol, slowest possible method,
+ * causes quite reasonable amount of threading overhead.
+ */
task_scheduler_push(pool->scheduler, task, priority);
}
@@ -816,7 +888,9 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* if found task, do it, otherwise wait until other tasks are done */
if (found_task) {
/* run task */
+ BLI_assert(!tls->do_delayed_push);
work_task->run(pool, work_task->taskdata, pool->thread_id);
+ BLI_assert(!tls->do_delayed_push);
/* delete task */
task_free(pool, task, pool->thread_id);
@@ -871,6 +945,30 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool)
return &pool->user_mutex;
}
+void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id)
+{
+ if (task_can_use_local_queues(pool, thread_id)) {
+ ASSERT_THREAD_ID(pool->scheduler, thread_id);
+ TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
+ tls->do_delayed_push = true;
+ }
+}
+
+void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id)
+{
+ if (task_can_use_local_queues(pool, thread_id)) {
+ ASSERT_THREAD_ID(pool->scheduler, thread_id);
+ TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
+ BLI_assert(tls->do_delayed_push);
+ task_scheduler_push_all(pool->scheduler,
+ pool,
+ tls->delayed_queue,
+ tls->num_delayed_queue);
+ tls->do_delayed_push = false;
+ tls->num_delayed_queue = 0;
+ }
+}
+
/* Parallel range routines */
/**
@@ -1029,7 +1127,7 @@ static void task_parallel_range_ex(
atomic_fetch_and_add_uint32((uint32_t *)(&state.iter), 0);
if (use_userdata_chunk) {
- userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks);
+ userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks);
}
for (i = 0; i < num_tasks; i++) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 01951b0266f..ff4c52967f3 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -638,7 +638,7 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
/* Add library datablock itself to 'main' Main, since libraries are **never** linked data.
* Fixes bug where you could end with all ID_LI datablocks having the same name... */
- lib = BKE_libblock_alloc(mainlist->first, ID_LI, "Lib");
+ lib = BKE_libblock_alloc(mainlist->first, ID_LI, "Lib", 0);
lib->id.us = ID_FAKE_USERS(lib); /* Important, consistency with main ID reading code from read_libblock(). */
BLI_strncpy(lib->name, filepath, sizeof(lib->name));
BLI_strncpy(lib->filepath, name1, sizeof(lib->filepath));
@@ -9912,6 +9912,8 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_CF:
expand_cachefile(fd, mainvar, (CacheFile *)id);
break;
+ default:
+ break;
}
do_it = true;
@@ -10159,7 +10161,7 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh)
static ID *link_named_part_ex(
Main *mainl, FileData *fd, const short idcode, const char *name, const short flag,
- Scene *scene, View3D *v3d, const bool use_placeholders, const bool force_indirect)
+ Scene *scene, View3D *v3d, const bool use_placeholders, const bool force_indirect)
{
ID *id = link_named_part(mainl, fd, idcode, name, use_placeholders, force_indirect);
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 1d5bd7d33d1..8459e080f99 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1237,12 +1237,19 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
SEQ_BEGIN (scene->ed, seq)
{
- if (seq->type == SEQ_TYPE_TEXT) {
- TextVars *data = seq->effectdata;
- if (data->color[3] == 0.0f) {
- copy_v4_fl(data->color, 1.0f);
- data->shadow_color[3] = 1.0f;
- }
+ if (seq->type != SEQ_TYPE_TEXT) {
+ continue;
+ }
+
+ if (seq->effectdata == NULL) {
+ struct SeqEffectHandle effect_handle = BKE_sequence_get_effect(seq);
+ effect_handle.init(seq);
+ }
+
+ TextVars *data = seq->effectdata;
+ if (data->color[3] == 0.0f) {
+ copy_v4_fl(data->color, 1.0f);
+ data->shadow_color[3] = 1.0f;
}
}
SEQ_END
@@ -1670,7 +1677,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
} FOREACH_NODETREE_END
}
- {
+ if (!MAIN_VERSION_ATLEAST(main, 279, 0)) {
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
if (scene->r.im_format.exr_codec == R_IMF_EXR_CODEC_DWAB) {
scene->r.im_format.exr_codec = R_IMF_EXR_CODEC_DWAA;
@@ -1682,12 +1689,23 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
CustomData_set_layer_name(&me->vdata, CD_MDEFORMVERT, 0, "");
}
}
+
+ {
+ /* Fix for invalid state of screen due to bug in older versions. */
+ for (bScreen *sc = main->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ if(sa->full && sc->state == SCREENNORMAL) {
+ sa->full = NULL;
+ }
+ }
+ }
+ }
}
void do_versions_after_linking_270(Main *main)
{
/* To be added to next subversion bump! */
- {
+ if (!MAIN_VERSION_ATLEAST(main, 279, 0)) {
FOREACH_NODETREE(main, ntree, id) {
if (ntree->type == NTREE_COMPOSIT) {
ntreeSetTypes(NULL, ntree);
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 845f8ff0523..eb8a72e12a7 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -58,6 +58,9 @@ void BLO_update_defaults_userpref_blend(void)
U.uiflag |= USER_QUIT_PROMPT;
U.uiflag |= USER_CONTINUOUS_MOUSE;
+ /* See T45301 */
+ U.uiflag |= USER_LOCK_CURSOR_ADJUST;
+
U.versions = 1;
U.savetime = 2;
@@ -252,13 +255,13 @@ void BLO_update_defaults_startup_blend(Main *bmain)
/* remove polish brush (flatten/contrast does the same) */
br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Polish");
if (br) {
- BKE_libblock_free(bmain, br);
+ BKE_libblock_delete(bmain, br);
}
/* remove brush brush (huh?) from some modes (draw brushes do the same) */
br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Brush");
if (br) {
- BKE_libblock_free(bmain, br);
+ BKE_libblock_delete(bmain, br);
}
/* remove draw brush from texpaint (draw brushes do the same) */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index ee9665dc834..6c5bfb01829 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -3841,6 +3841,9 @@ static bool write_file_handle(
}
for (; id; id = id->next) {
+ /* We should never attempt to write non-regular IDs (i.e. all kind of temp/runtime ones). */
+ BLI_assert((id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0);
+
switch ((ID_Type)GS(id->name)) {
case ID_WM:
write_windowmanager(wd, (wmWindowManager *)id);
diff --git a/source/blender/blentranslation/CMakeLists.txt b/source/blender/blentranslation/CMakeLists.txt
index c0dce5b4f0d..320a784ea25 100644
--- a/source/blender/blentranslation/CMakeLists.txt
+++ b/source/blender/blentranslation/CMakeLists.txt
@@ -61,4 +61,6 @@ endif()
blender_add_lib(bf_blentranslation "${SRC}" "${INC}" "${INC_SYS}")
-add_subdirectory(msgfmt)
+if(WITH_INTERNATIONAL)
+ add_subdirectory(msgfmt)
+endif()
diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c
index 487d9fee7b4..3abce7b1d3f 100644
--- a/source/blender/blentranslation/msgfmt/msgfmt.c
+++ b/source/blender/blentranslation/msgfmt/msgfmt.c
@@ -160,7 +160,8 @@ static char **get_keys_sorted(GHash *messages, const uint32_t num_keys)
return keys;
}
-BLI_INLINE size_t uint32_to_bytes(const int value, char *bytes) {
+BLI_INLINE size_t uint32_to_bytes(const int value, char *bytes)
+{
size_t i;
for (i = 0; i < sizeof(value); i++) {
bytes[i] = (char) ((value >> ((int)i * 8)) & 0xff);
@@ -168,7 +169,8 @@ BLI_INLINE size_t uint32_to_bytes(const int value, char *bytes) {
return i;
}
-BLI_INLINE size_t msg_to_bytes(char *msg, char *bytes, uint32_t size) {
+BLI_INLINE size_t msg_to_bytes(char *msg, char *bytes, uint32_t size)
+{
/* Note that we also perform replacing of our NULLSEP placeholder by real NULL char... */
size_t i;
for (i = 0; i < size; i++, msg++, bytes++) {
@@ -452,7 +454,8 @@ static int make(const char *input_file_name, const char *output_file_name)
return EXIT_SUCCESS;
}
-int main(int argc, char **argv) {
+int main(int argc, char **argv)
+{
if (argc != 3) {
printf("Usage: %s <input.po> <output.mo>\n", argv[0]);
return EXIT_FAILURE;
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 4fe14fdf5c9..6b22fd0a85c 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -2415,7 +2415,8 @@ static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separ
/* don't visit again */
n_prev->next = n_step->next;
}
- } while ((n_prev = n_step),
+ } while ((void)
+ (n_prev = n_step),
(n_step = n_step->next));
} while ((n_orig = n_orig->next) && n_orig->next);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 59ce91a3e70..7787d704b59 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -219,6 +219,11 @@ static BMFace *bm_face_create_from_mpoly(
/**
* \brief Mesh -> BMesh
+ * \param bm: The mesh to write into, while this is typically a newly created BMesh,
+ * merging into existing data is supported.
+ * Note the custom-data layout isn't used.
+ * If more comprehensive merging is needed we should move this into a separate function
+ * since this should be kept fast for edit-mode switching and storing undo steps.
*
* \warning This function doesn't calculate face normals.
*/
@@ -226,6 +231,9 @@ void BM_mesh_bm_from_me(
BMesh *bm, Mesh *me,
const struct BMeshFromMeshParams *params)
{
+ const bool is_new =
+ !(bm->totvert ||
+ (bm->vdata.totlayer || bm->edata.totlayer || bm->pdata.totlayer || bm->ldata.totlayer));
MVert *mvert;
MEdge *medge;
MLoop *mloop;
@@ -233,19 +241,12 @@ void BM_mesh_bm_from_me(
KeyBlock *actkey, *block;
BMVert *v, **vtable = NULL;
BMEdge *e, **etable = NULL;
- BMFace *f;
+ BMFace *f, **ftable = NULL;
float (*keyco)[3] = NULL;
- int totuv, totloops, i, j;
-
- /* free custom data */
- /* this isnt needed in most cases but do just incase */
- CustomData_free(&bm->vdata, bm->totvert);
- CustomData_free(&bm->edata, bm->totedge);
- CustomData_free(&bm->ldata, bm->totloop);
- CustomData_free(&bm->pdata, bm->totface);
+ int totuv, totloops, i;
if (!me || !me->totvert) {
- if (me) { /*no verts? still copy customdata layout*/
+ if (me && is_new) { /*no verts? still copy customdata layout*/
CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_ASSIGN, 0);
CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_ASSIGN, 0);
CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_ASSIGN, 0);
@@ -259,19 +260,27 @@ void BM_mesh_bm_from_me(
return; /* sanity check */
}
- vtable = MEM_mallocN(sizeof(void **) * me->totvert, "mesh to bmesh vtable");
+ if (is_new) {
+ CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
- CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
- CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
- CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
- CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ /* make sure uv layer names are consisten */
+ totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ for (i = 0; i < totuv; i++) {
+ int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i);
+ CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
+ }
+ }
- /* make sure uv layer names are consisten */
- totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
- for (i = 0; i < totuv; i++) {
- int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i);
- CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
+ /* -------------------------------------------------------------------- */
+ /* Shape Key */
+ int tot_shape_keys = me->key ? BLI_listbase_count(&me->key->block) : 0;
+ if (is_new == false) {
+ tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY));
}
+ const float (**shape_key_table)[3] = tot_shape_keys ? BLI_array_alloca(shape_key_table, tot_shape_keys) : NULL;
if ((params->active_shapekey != 0) && (me->key != NULL)) {
actkey = BLI_findlink(&me->key->block, params->active_shapekey - 1);
@@ -280,63 +289,68 @@ void BM_mesh_bm_from_me(
actkey = NULL;
}
- const int tot_shape_keys = me->key ? BLI_listbase_count(&me->key->block) : 0;
- const float (**shape_key_table)[3] = tot_shape_keys ? BLI_array_alloca(shape_key_table, tot_shape_keys) : NULL;
-
- if (tot_shape_keys || params->add_key_index) {
- CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
+ if (is_new) {
+ if (tot_shape_keys || params->add_key_index) {
+ CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
+ }
}
if (tot_shape_keys) {
- /* check if we need to generate unique ids for the shapekeys.
- * this also exists in the file reading code, but is here for
- * a sanity check */
- if (!me->key->uidgen) {
- fprintf(stderr,
- "%s had to generate shape key uid's in a situation we shouldn't need to! "
- "(bmesh internal error)\n",
- __func__);
-
- me->key->uidgen = 1;
- for (block = me->key->block.first; block; block = block->next) {
- block->uid = me->key->uidgen++;
+ if (is_new) {
+ /* check if we need to generate unique ids for the shapekeys.
+ * this also exists in the file reading code, but is here for
+ * a sanity check */
+ if (!me->key->uidgen) {
+ fprintf(stderr,
+ "%s had to generate shape key uid's in a situation we shouldn't need to! "
+ "(bmesh internal error)\n",
+ __func__);
+
+ me->key->uidgen = 1;
+ for (block = me->key->block.first; block; block = block->next) {
+ block->uid = me->key->uidgen++;
+ }
}
}
if (actkey && actkey->totelem == me->totvert) {
- keyco = actkey->data;
- bm->shapenr = params->active_shapekey;
+ keyco = params->use_shapekey ? actkey->data : NULL;
+ if (is_new) {
+ bm->shapenr = params->active_shapekey;
+ }
}
- for (i = 0, block = me->key->block.first; block; block = block->next, i++) {
- CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY,
- CD_ASSIGN, NULL, 0, block->name);
-
- j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
- bm->vdata.layers[j].uid = block->uid;
-
+ for (i = 0, block = me->key->block.first; i < tot_shape_keys; block = block->next, i++) {
+ if (is_new) {
+ CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY,
+ CD_ASSIGN, NULL, 0, block->name);
+ int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
+ bm->vdata.layers[j].uid = block->uid;
+ }
shape_key_table[i] = (const float (*)[3])block->data;
}
}
- CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
- CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
- CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
- CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
+ if (is_new) {
+ CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
+ CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
+ CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
+ CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
- BM_mesh_cd_flag_apply(bm, me->cd_flag);
+ BM_mesh_cd_flag_apply(bm, me->cd_flag);
+ }
const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
const int cd_shape_key_offset = me->key ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) : -1;
- const int cd_shape_keyindex_offset = (tot_shape_keys || params->add_key_index) ?
+ const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ?
CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : -1;
+ vtable = MEM_mallocN(sizeof(BMVert **) * me->totvert, __func__);
+
for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
- v = vtable[i] = BM_vert_create(
- bm, keyco && params->use_shapekey ? keyco[i] : mvert->co, NULL,
- BM_CREATE_SKIP_CD);
+ v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD);
BM_elem_index_set(v, i); /* set_ok */
/* transfer flag */
@@ -360,20 +374,16 @@ void BM_mesh_bm_from_me(
/* set shapekey data */
if (tot_shape_keys) {
float (*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset);
- for (j = 0; j < tot_shape_keys; j++, co_dst++) {
+ for (int j = 0; j < tot_shape_keys; j++, co_dst++) {
copy_v3_v3(*co_dst, shape_key_table[j][i]);
}
}
}
-
- bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */
-
- if (!me->totedge) {
- MEM_freeN(vtable);
- return;
+ if (is_new) {
+ bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */
}
- etable = MEM_mallocN(sizeof(void **) * me->totedge, "mesh to bmesh etable");
+ etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__);
medge = me->medge;
for (i = 0; i < me->totedge; i++, medge++) {
@@ -395,8 +405,14 @@ void BM_mesh_bm_from_me(
if (cd_edge_crease_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge->crease / 255.0f);
}
+ if (is_new) {
+ bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */
+ }
- bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */
+ /* only needed for selection. */
+ if (me->mselect && me->totselect != 0) {
+ ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__);
+ }
mloop = me->mloop;
mp = me->mpoly;
@@ -406,6 +422,9 @@ void BM_mesh_bm_from_me(
f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart,
bm, vtable, etable);
+ if (ftable != NULL) {
+ ftable[i] = f;
+ }
if (UNLIKELY(f == NULL)) {
printf("%s: Warning! Bad face in mesh"
@@ -428,7 +447,7 @@ void BM_mesh_bm_from_me(
f->mat_nr = mp->mat_nr;
if (i == me->act_face) bm->act_face = f;
- j = mp->loopstart;
+ int j = mp->loopstart;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
/* don't use 'j' since we may have skipped some faces, hence some loops. */
@@ -445,54 +464,49 @@ void BM_mesh_bm_from_me(
BM_face_normal_update(f);
}
}
+ if (is_new) {
+ bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */
+ }
- bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */
+ /* -------------------------------------------------------------------- */
+ /* MSelect clears the array elements (avoid adding multiple times).
+ *
+ * Take care to keep this last and not use (v/e/ftable) after this.
+ */
if (me->mselect && me->totselect != 0) {
-
- BMVert **vert_array = MEM_mallocN(sizeof(BMVert *) * bm->totvert, "VSelConv");
- BMEdge **edge_array = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, "ESelConv");
- BMFace **face_array = MEM_mallocN(sizeof(BMFace *) * bm->totface, "FSelConv");
MSelect *msel;
-
-#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
- {
-#pragma omp section
- { BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)vert_array, bm->totvert); }
-#pragma omp section
- { BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edge_array, bm->totedge); }
-#pragma omp section
- { BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)face_array, bm->totface); }
- }
-
for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) {
+ BMElem **ele_p;
switch (msel->type) {
case ME_VSEL:
- BM_select_history_store(bm, (BMElem *)vert_array[msel->index]);
+ ele_p = (BMElem **)&vtable[msel->index];
break;
case ME_ESEL:
- BM_select_history_store(bm, (BMElem *)edge_array[msel->index]);
+ ele_p = (BMElem **)&etable[msel->index];
break;
case ME_FSEL:
- BM_select_history_store(bm, (BMElem *)face_array[msel->index]);
+ ele_p = (BMElem **)&ftable[msel->index];
break;
+ default:
+ continue;
}
- }
- MEM_freeN(vert_array);
- MEM_freeN(edge_array);
- MEM_freeN(face_array);
+ if (*ele_p != NULL) {
+ BM_select_history_store_notest(bm, *ele_p);
+ *ele_p = NULL;
+ }
+ }
}
else {
- me->totselect = 0;
- if (me->mselect) {
- MEM_freeN(me->mselect);
- me->mselect = NULL;
- }
+ BM_select_history_clear(bm);
}
MEM_freeN(vtable);
MEM_freeN(etable);
+ if (ftable) {
+ MEM_freeN(ftable);
+ }
}
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index d2f0fc1721c..a55df234264 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1037,7 +1037,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
/* slots_in */
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */
{"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
- {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */
+ {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */
{"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
@@ -1741,6 +1741,8 @@ static BMOpDefine bmo_bevel_def = {
},
/* slots_out */
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */
+ {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
{{'\0'}},
},
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index e515f9af63f..1b35f049838 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -725,10 +725,30 @@ BLI_INLINE bool edge_isect_verts_point_2d(
const BMEdge *e, const BMVert *v_a, const BMVert *v_b,
float r_isect[2])
{
- return ((isect_seg_seg_v2_point(v_a->co, v_b->co, e->v1->co, e->v2->co, r_isect) == 1) &&
+ /* This bias seems like it could be too large,
+ * mostly its not needed, see T52329 for example where it is. */
+ const float endpoint_bias = 1e-4f;
+ return ((isect_seg_seg_v2_point_ex(v_a->co, v_b->co, e->v1->co, e->v2->co, endpoint_bias, r_isect) == 1) &&
((e->v1 != v_a) && (e->v2 != v_a) && (e->v1 != v_b) && (e->v2 != v_b)));
}
+BLI_INLINE int axis_pt_cmp(const float pt_a[2], const float pt_b[2])
+{
+ if (pt_a[0] < pt_b[0]) {
+ return -1;
+ }
+ if (pt_a[0] > pt_b[0]) {
+ return 1;
+ }
+ if (pt_a[1] < pt_b[1]) {
+ return -1;
+ }
+ if (pt_a[1] > pt_b[1]) {
+ return 1;
+ }
+ return 0;
+}
+
/**
* Represents isolated edge-links,
* each island owns contiguous slices of the vert array.
@@ -749,7 +769,8 @@ struct EdgeGroupIsland {
struct {
BMVert *min, *max;
/* used for sorting only */
- float min_axis;
+ float min_axis[2];
+ float max_axis[2];
} vert_span;
};
@@ -758,12 +779,11 @@ static int group_min_cmp_fn(const void *p1, const void *p2)
const struct EdgeGroupIsland *g1 = *(struct EdgeGroupIsland **)p1;
const struct EdgeGroupIsland *g2 = *(struct EdgeGroupIsland **)p2;
/* min->co[SORT_AXIS] hasn't been applied yet */
- const float f1 = g1->vert_span.min_axis;
- const float f2 = g2->vert_span.min_axis;
-
- if (f1 < f2) return -1;
- if (f1 > f2) return 1;
- else return 0;
+ int test = axis_pt_cmp(g1->vert_span.min_axis, g2->vert_span.min_axis);
+ if (UNLIKELY(test == 0)) {
+ test = axis_pt_cmp(g1->vert_span.max_axis, g2->vert_span.max_axis);
+ }
+ return test;
}
struct Edges_VertVert_BVHTreeTest {
@@ -993,8 +1013,8 @@ static int bm_face_split_edgenet_find_connection(
for (int j = 0; j < 2; j++) {
BMVert *v_iter = v_pair[j];
if (BM_elem_flag_test(v_iter, VERT_IS_VALID)) {
- if (direction_sign ? (v_iter->co[SORT_AXIS] >= v_origin->co[SORT_AXIS]) :
- (v_iter->co[SORT_AXIS] <= v_origin->co[SORT_AXIS]))
+ if (direction_sign ? (v_iter->co[SORT_AXIS] > v_origin->co[SORT_AXIS]) :
+ (v_iter->co[SORT_AXIS] < v_origin->co[SORT_AXIS]))
{
BLI_SMALLSTACK_PUSH(vert_search, v_iter);
BLI_SMALLSTACK_PUSH(vert_blacklist, v_iter);
@@ -1360,8 +1380,8 @@ bool BM_face_split_edgenet_connect_islands(
/* init with *any* different verts */
g->vert_span.min = ((BMEdge *)edge_links->link)->v1;
g->vert_span.max = ((BMEdge *)edge_links->link)->v2;
- float min_axis = FLT_MAX;
- float max_axis = -FLT_MAX;
+ float min_axis[2] = {FLT_MAX, FLT_MAX};
+ float max_axis[2] = {-FLT_MAX, -FLT_MAX};
do {
BMEdge *e = edge_links->link;
@@ -1372,24 +1392,29 @@ bool BM_face_split_edgenet_connect_islands(
BLI_assert(v_iter->head.htype == BM_VERT);
/* ideally we could use 'v_iter->co[SORT_AXIS]' here,
* but we need to sort the groups before setting the vertex array order */
+ const float axis_value[2] = {
#if SORT_AXIS == 0
- const float axis_value = dot_m3_v3_row_x(axis_mat, v_iter->co);
+ dot_m3_v3_row_x(axis_mat, v_iter->co),
+ dot_m3_v3_row_y(axis_mat, v_iter->co),
#else
- const float axis_value = dot_m3_v3_row_y(axis_mat, v_iter->co);
+ dot_m3_v3_row_y(axis_mat, v_iter->co),
+ dot_m3_v3_row_x(axis_mat, v_iter->co),
#endif
+ };
- if (axis_value < min_axis) {
+ if (axis_pt_cmp(axis_value, min_axis) == -1) {
g->vert_span.min = v_iter;
- min_axis = axis_value;
+ copy_v2_v2(min_axis, axis_value);
}
- if (axis_value > max_axis ) {
+ if (axis_pt_cmp(axis_value, max_axis) == 1) {
g->vert_span.max = v_iter;
- max_axis = axis_value;
+ copy_v2_v2(max_axis, axis_value);
}
}
} while ((edge_links = edge_links->next));
- g->vert_span.min_axis = min_axis;
+ copy_v2_v2(g->vert_span.min_axis, min_axis);
+ copy_v2_v2(g->vert_span.max_axis, max_axis);
g->has_prev_edge = false;
@@ -1449,8 +1474,10 @@ bool BM_face_split_edgenet_connect_islands(
bm->elem_index_dirty |= BM_VERT;
- /* Now create bvh tree*/
- BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 0.0f, 8, 8);
+ /* Now create bvh tree
+ *
+ * Note that a large epsilon is used because meshes with dimensions of around 100+ need it. see T52329. */
+ BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 1e-4f, 8, 8);
for (uint i = 0; i < edge_arr_len; i++) {
const float e_cos[2][3] = {
{UNPACK2(edge_arr[i]->v1->co), 0.0f},
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index 4161fbe90fb..4dcf97e3f35 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -44,13 +44,14 @@
# define BM_CHECK_ELEMENT(el) (void)(el)
#else
int bmesh_elem_check(void *element, const char htype);
-# define BM_CHECK_ELEMENT(el) \
+# define BM_CHECK_ELEMENT(el) { \
if (bmesh_elem_check(el, ((BMHeader *)el)->htype)) { \
printf("check_element failure, with code %i on line %i in file\n" \
" \"%s\"\n\n", \
bmesh_elem_check(el, ((BMHeader *)el)->htype), \
__LINE__, __FILE__); \
- } (void)0
+ } \
+} ((void)0)
#endif
int bmesh_radial_length(const BMLoop *l);
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index a774f278c98..668fb998254 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -1511,20 +1511,68 @@ float BM_loop_calc_face_angle(const BMLoop *l)
* Calculate the normal at this loop corner or fallback to the face normal on straight lines.
*
* \param l The loop to calculate the normal at
+ * \param epsilon: Value to avoid numeric errors (1e-5f works well).
* \param r_normal Resulting normal
*/
-void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
+float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3])
{
- if (normal_tri_v3(r_normal,
- l->prev->v->co,
- l->v->co,
- l->next->v->co) != 0.0f)
- {
- /* pass */
+ /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line)
+ * from zero value, because it does not normalize both vectors before making crossproduct.
+ * Instead of adding two costly normalize computations, just check ourselves for colinear case. */
+ /* Note: FEPSILON might need some finer tweaking at some point? Seems to be working OK for now though. */
+ float v1[3], v2[3], v_tmp[3];
+ sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(v2, l->next->v->co, l->v->co);
+
+ const float fac =
+ ((v2[0] == 0.0f) ?
+ ((v2[1] == 0.0f) ?
+ ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0]);
+
+ mul_v3_v3fl(v_tmp, v2, fac);
+ sub_v3_v3(v_tmp, v1);
+ if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) {
+ /* Not co-linear, we can compute crossproduct and normalize it into normal. */
+ cross_v3_v3v3(r_normal, v1, v2);
+ return normalize_v3(r_normal);
}
else {
copy_v3_v3(r_normal, l->f->no);
+ return 0.0f;
+ }
+}
+
+/**
+ * #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon.
+ *
+ * Since this doesn't scale baed on triangle size, fixed value works well.
+ */
+float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
+{
+ return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal);
+}
+
+/**
+ * \brief BM_loop_calc_face_normal
+ *
+ * Calculate the normal at this loop corner or fallback to the face normal on straight lines.
+ *
+ * \param l The loop to calculate the normal at
+ * \param r_normal Resulting normal
+ * \return The length of the cross product (double the area).
+ */
+float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
+{
+ float v1[3], v2[3];
+ sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(v2, l->next->v->co, l->v->co);
+
+ cross_v3_v3v3(r_normal, v1, v2);
+ const float len = normalize_v3(r_normal);
+ if (UNLIKELY(len == 0.0f)) {
+ copy_v3_v3(r_normal, l->f->no);
}
+ return len;
}
/**
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 903fdc59cb8..83977fa8be0 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -113,7 +113,9 @@ BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq
BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq);
float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3]) ATTR_NONNULL();
void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]);
void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index d5afb39d7b7..2ae87b64286 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -66,5 +66,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material, loop_slide);
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "verts.out", BM_VERT, BM_ELEM_TAG);
}
}
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index a73c86fd122..b474ad9fc7b 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -530,8 +530,8 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
float basis_nor_b[3];
/* align normal to direction */
- project_plane_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir);
- project_plane_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir);
+ project_plane_normalized_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir);
+ project_plane_normalized_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir);
/* don't normalize before combining so as normals approach the direction, they have less effect (T46784). */
@@ -569,7 +569,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
float angle_cos_test;
/* project basis dir onto the normal to find its closest angle */
- project_plane_v3_v3v3(basis_dir_proj, basis_dir, l->f->no);
+ project_plane_normalized_v3_v3v3(basis_dir_proj, basis_dir, l->f->no);
if (normalize_v3(basis_dir_proj) > eps) {
angle_cos_test = dot_v3v3(basis_dir_proj, basis_dir);
@@ -586,7 +586,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
* note: we could add the directions,
* but this more often gives 45d rotated matrix, so just use the best one. */
copy_v3_v3(basis_nor, axis_pair[axis_pair[0].angle_cos < axis_pair[1].angle_cos].nor);
- project_plane_v3_v3v3(basis_nor, basis_nor, basis_dir);
+ project_plane_normalized_v3_v3v3(basis_nor, basis_nor, basis_dir);
cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index a980baf8626..fa08d009d40 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -74,13 +74,13 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMVert *verts[2];
BMEdge *e;
- BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)verts, 2);
-
- /* create edge */
- e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
- BMO_edge_flag_enable(bm, e, ELE_OUT);
- tote += 1;
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
+ if (BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)verts, 2) == 2) {
+ /* create edge */
+ e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
+ BMO_edge_flag_enable(bm, e, ELE_OUT);
+ tote += 1;
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
+ }
return;
}
@@ -283,13 +283,13 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
*/
if (totv > 2) {
/* TODO, some of these vertes may be connected by edges,
- * this connectivity could be used rather then treating
+ * this connectivity could be used rather than treating
* them as a bunch of isolated verts. */
BMVert **vert_arr = MEM_mallocN(sizeof(BMVert *) * totv, __func__);
BMFace *f;
- BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv);
+ totv = BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv);
BM_verts_sort_radial_plane(vert_arr, totv);
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index cca0f7387cd..d8f83d786b4 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -839,7 +839,7 @@ void BM_mesh_calc_uvs_grid(
const float dx = 1.0f / (float)(x_segments - 1);
const float dy = 1.0f / (float)(y_segments - 1);
float x = 0.0f;
- float y = 0.0f;
+ float y = dy;
int loop_index;
@@ -854,16 +854,16 @@ void BM_mesh_calc_uvs_grid(
switch (loop_index) {
case 0:
- x += dx;
+ y -= dy;
break;
case 1:
- y += dy;
+ x += dx;
break;
case 2:
- x -= dx;
+ y += dy;
break;
case 3:
- y -= dy;
+ x -= dx;
break;
default:
break;
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 18704a6679f..d8e6f250adf 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -30,6 +30,7 @@
#include "BLI_math.h"
#include "BLI_alloca.h"
+#include "BLI_kdtree.h"
#include "BLI_stackdefines.h"
#include "BLI_stack.h"
@@ -277,22 +278,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
BMO_mesh_delete_oflag_context(bm, ELE_DEL, DEL_ONLYTAGGED);
}
-static int vergaverco(const void *e1, const void *e2)
-{
- const BMVert *v1 = *(const void **)e1, *v2 = *(const void **)e2;
- float x1 = v1->co[0] + v1->co[1] + v1->co[2];
- float x2 = v2->co[0] + v2->co[1] + v2->co[2];
-
- if (x1 > x2) return 1;
- else if (x1 < x2) return -1;
- else return 0;
-}
-
-// #define VERT_TESTED 1 // UNUSED
-#define VERT_DOUBLE 2
-#define VERT_TARGET 4
#define VERT_KEEP 8
-// #define VERT_MARK 16 // UNUSED
#define VERT_IN 32
#define EDGE_MARK 1
@@ -440,20 +426,24 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- float min[3], max[3], center[3];
+ float center[3];
+ int count = 0;
BMVert *v_tar;
+ zero_v3(center);
+
if (!BMO_edge_flag_test(bm, e, EDGE_MARK))
continue;
BLI_assert(BLI_stack_is_empty(edge_stack));
- INIT_MINMAX(min, max);
for (e = BMW_begin(&walker, e->v1); e; e = BMW_step(&walker)) {
BLI_stack_push(edge_stack, &e);
- minmax_v3v3_v3(min, max, e->v1->co);
- minmax_v3v3_v3(min, max, e->v2->co);
+ add_v3_v3(center, e->v1->co);
+ add_v3_v3(center, e->v2->co);
+
+ count += 2;
/* prevent adding to slot_targetmap multiple times */
BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
@@ -461,8 +451,7 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
}
if (!BLI_stack_is_empty(edge_stack)) {
-
- mid_v3_v3v3(center, min, max);
+ mul_v3_fl(center, 1.0f / count);
/* snap edges to a point. for initial testing purposes anyway */
e = *(BMEdge **)BLI_stack_peek(edge_stack);
@@ -581,77 +570,62 @@ static void bmesh_find_doubles_common(
BMesh *bm, BMOperator *op,
BMOperator *optarget, BMOpSlot *optarget_slot)
{
- BMVert **verts;
- int verts_len;
+ const BMOpSlot *slot_verts = BMO_slot_get(op->slots_in, "verts");
+ BMVert * const *verts = (BMVert **)slot_verts->data.buf;
+ const int verts_len = slot_verts->len;
- int i, j, keepvert = 0;
+ bool has_keep_vert = false;
+ bool found_duplicates = false;
const float dist = BMO_slot_float_get(op->slots_in, "dist");
- const float dist_sq = dist * dist;
- const float dist3 = ((float)M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */
/* Test whether keep_verts arg exists and is non-empty */
if (BMO_slot_exists(op->slots_in, "keep_verts")) {
BMOIter oiter;
- keepvert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL;
+ has_keep_vert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL;
}
- /* get the verts as an array we can sort */
- verts = BMO_slot_as_arrayN(op->slots_in, "verts", &verts_len);
-
- /* sort by vertex coordinates added together */
- qsort(verts, verts_len, sizeof(BMVert *), vergaverco);
-
/* Flag keep_verts */
- if (keepvert) {
+ if (has_keep_vert) {
BMO_slot_buffer_flag_enable(bm, op->slots_in, "keep_verts", BM_VERT, VERT_KEEP);
}
- for (i = 0; i < verts_len; i++) {
- BMVert *v_check = verts[i];
-
- if (BMO_vert_flag_test(bm, v_check, VERT_DOUBLE | VERT_TARGET)) {
- continue;
+ int *duplicates = MEM_mallocN(sizeof(int) * verts_len, __func__);
+ {
+ KDTree *tree = BLI_kdtree_new(verts_len);
+ for (int i = 0; i < verts_len; i++) {
+ BLI_kdtree_insert(tree, i, verts[i]->co);
+ if (has_keep_vert && BMO_vert_flag_test(bm, verts[i], VERT_KEEP)) {
+ duplicates[i] = i;
+ }
+ else {
+ duplicates[i] = -1;
+ }
}
- for (j = i + 1; j < verts_len; j++) {
- BMVert *v_other = verts[j];
-
- /* a match has already been found, (we could check which is best, for now don't) */
- if (BMO_vert_flag_test(bm, v_other, VERT_DOUBLE | VERT_TARGET)) {
- continue;
- }
+ BLI_kdtree_balance(tree);
+ found_duplicates = BLI_kdtree_calc_duplicates_fast(tree, dist, false, duplicates) != 0;
+ BLI_kdtree_free(tree);
+ }
- /* Compare sort values of the verts using 3x tolerance (allowing for the tolerance
- * on each of the three axes). This avoids the more expensive length comparison
- * for most vertex pairs. */
- if ((v_other->co[0] + v_other->co[1] + v_other->co[2]) -
- (v_check->co[0] + v_check->co[1] + v_check->co[2]) > dist3)
- {
- break;
+ if (found_duplicates) {
+ for (int i = 0; i < verts_len; i++) {
+ BMVert *v_check = verts[i];
+ if (duplicates[i] == -1) {
+ /* nop (others can use as target) */
}
-
- if (keepvert) {
- if (BMO_vert_flag_test(bm, v_other, VERT_KEEP) == BMO_vert_flag_test(bm, v_check, VERT_KEEP))
- continue;
+ else if (duplicates[i] == i) {
+ /* keep (others can use as target) */
}
-
- if (compare_len_squared_v3v3(v_check->co, v_other->co, dist_sq)) {
-
- /* If one vert is marked as keep, make sure it will be the target */
- if (BMO_vert_flag_test(bm, v_other, VERT_KEEP)) {
- SWAP(BMVert *, v_check, v_other);
- }
-
- BMO_vert_flag_enable(bm, v_other, VERT_DOUBLE);
- BMO_vert_flag_enable(bm, v_check, VERT_TARGET);
-
- BMO_slot_map_elem_insert(optarget, optarget_slot, v_other, v_check);
+ else {
+ BMVert *v_other = verts[duplicates[i]];
+ BLI_assert(ELEM(duplicates[duplicates[i]], -1, duplicates[i]));
+ BMO_slot_map_elem_insert(optarget, optarget_slot, v_check, v_other);
}
}
}
- MEM_freeN(verts);
+ MEM_freeN(duplicates);
}
void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op)
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 74841dc2756..51a0fa4b2cc 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -205,13 +205,36 @@ static int bev_debug_flags = 0;
#define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2)
#define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4)
+/* this flag values will get set on geom we want to return in 'out' slots for edges and verts */
+#define EDGE_OUT 4
+#define VERT_OUT 8
+
+/* If we're called from the modifier, tool flags aren't available, but don't need output geometry */
+static void flag_out_edge(BMesh *bm, BMEdge *bme)
+{
+ if (bm->use_toolflags)
+ BMO_edge_flag_enable(bm, bme, EDGE_OUT);
+}
+
+static void flag_out_vert(BMesh *bm, BMVert *bmv)
+{
+ if (bm->use_toolflags)
+ BMO_vert_flag_enable(bm, bmv, VERT_OUT);
+}
+
+static void disable_flag_out_edge(BMesh *bm, BMEdge *bme)
+{
+ if (bm->use_toolflags)
+ BMO_edge_flag_disable(bm, bme, EDGE_OUT);
+}
+
/* Are d1 and d2 parallel or nearly so? */
static bool nearly_parallel(const float d1[3], const float d2[3])
{
float ang;
ang = angle_v3v3(d1, d2);
- return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - M_PI) < BEVEL_EPSILON_ANG);
+ return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG);
}
/* Make a new BoundVert of the given kind, insert it at the end of the circular linked
@@ -262,6 +285,7 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert
NewVert *nv = mesh_vert(vm, i, j, k);
nv->v = BM_vert_create(bm, nv->co, eg, BM_CREATE_NOP);
BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
+ flag_out_vert(bm, nv->v);
}
static void copy_mesh_vert(
@@ -504,9 +528,12 @@ static BMFace *bev_create_ngon(
}
/* not essential for bevels own internal logic,
- * this is done so the operator can select newly created faces */
+ * this is done so the operator can select newly created geometry */
if (f) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BM_ITER_ELEM(bme, &iter, f, BM_EDGES_OF_FACE) {
+ flag_out_edge(bm, bme);
+ }
}
if (mat_nr >= 0)
@@ -3213,6 +3240,7 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
BMFace *f_new;
BLI_assert(v_fan == l_fan->v);
f_new = BM_face_split(bm, f, l_fan, l_fan->next->next, &l_new, NULL, false);
+ flag_out_edge(bm, l_new->e);
if (f_new->len > f->len) {
f = f_new;
@@ -3259,6 +3287,7 @@ static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv)
else {
BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
f = l_new->f;
+ flag_out_edge(bm, l_new->e);
/* walk around the new face to get the next verts to split */
l_a = l_new->prev;
@@ -3278,7 +3307,7 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
{
VMesh *vm = bv->vmesh;
BMVert *v1, *v2;
- BMEdge *e_eg;
+ BMEdge *e_eg, *bme;
Profile *pro;
float co[3];
BoundVert *bndv;
@@ -3320,7 +3349,9 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
v1 = mesh_vert(vm, 0, 0, k)->v;
v2 = mesh_vert(vm, 0, 0, k + 1)->v;
BLI_assert(v1 != NULL && v2 != NULL);
- BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+ bme = BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+ if (bme)
+ flag_out_edge(bm, bme);
}
}
}
@@ -3901,7 +3932,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
/* Face f has at least one beveled vertex. Rebuild f */
static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
{
- BMIter liter;
+ BMIter liter, eiter, fiter;
BMLoop *l, *lprev;
BevVert *bv;
BoundVert *v, *vstart, *vend;
@@ -3909,10 +3940,10 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
VMesh *vm;
int i, k, n;
bool do_rebuild = false;
- bool go_ccw, corner3special;
+ bool go_ccw, corner3special, keep;
BMVert *bmv;
BMEdge *bme, *bme_new, *bme_prev;
- BMFace *f_new;
+ BMFace *f_new, *f_other;
BMVert **vv = NULL;
BMVert **vv_fix = NULL;
BMEdge **ee = NULL;
@@ -4050,9 +4081,21 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
}
- /* don't select newly created boundary faces... */
+ /* don't select newly or return created boundary faces... */
if (f_new) {
BM_elem_flag_disable(f_new, BM_ELEM_TAG);
+ /* Also don't want new edges that aren't part of a new bevel face */
+ BM_ITER_ELEM(bme, &eiter, f_new, BM_EDGES_OF_FACE) {
+ keep = false;
+ BM_ITER_ELEM(f_other, &fiter, bme, BM_FACES_OF_EDGE) {
+ if (BM_elem_flag_test(f_other, BM_ELEM_TAG)) {
+ keep = true;
+ break;
+ }
+ }
+ if (!keep)
+ disable_flag_out_edge(bm, bme);
+ }
}
}
@@ -4134,8 +4177,9 @@ static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
}
}
} while ((bndv = bndv->next) != bv->vmesh->boundstart);
- if (vclosest)
+ if (vclosest) {
BM_edge_create(bm, vclosest, votherclosest, e, BM_CREATE_NO_DOUBLE);
+ }
}
}
@@ -4487,61 +4531,206 @@ static void set_profile_spacing(BevelParams *bp)
}
/*
- * Calculate and return an offset that is the lesser of the current
+ * Assume we have a situation like:
+ *
+ * a d
+ * \ /
+ * A \ / C
+ * \ th1 th2/
+ * b---------c
+ * B
+ *
+ * where edges are A, B, and C,
+ * following a face around vertices a, b, c, d;
+ * th1 is angle abc and th2 is angle bcd;
+ * and the argument EdgeHalf eb is B, going from b to c.
+ * In general case, edge offset specs for A, B, C have
+ * the form ka*t, kb*t, kc*t where ka, kb, kc are some factors
+ * (may be 0) and t is the current bp->offset.
+ * We want to calculate t at which the clone of B parallel
+ * to it collapses. This can be calculated using trig.
+ * Another case of geometry collision that can happen is
+ * When B slides along A because A is unbeveled.
+ * Then it might collide with a. Similarly for B sliding along C.
+ */
+static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
+{
+ EdgeHalf *ea, *ec, *ebother;
+ BevVert *bvc;
+ BMLoop *lb;
+ BMVert *va, *vb, *vc, *vd;
+ float ka, kb, kc, g, h, t, den, no_collide_offset, th1, th2, sin1, sin2, tan1, tan2, limit;
+
+ limit = no_collide_offset = bp->offset + 1e6;
+ if (bp->offset == 0.0f)
+ return no_collide_offset;
+ kb = eb->offset_l_spec;
+ ea = eb->next; /* note: this is in direction b --> a */
+ ka = ea->offset_r_spec;
+ if (eb->is_rev) {
+ vc = eb->e->v1;
+ vb = eb->e->v2;
+ }
+ else {
+ vb = eb->e->v1;
+ vc = eb->e->v2;
+ }
+ va = ea->is_rev ? ea->e->v1 : ea->e->v2;
+ bvc = NULL;
+ ebother = find_other_end_edge_half(bp, eb, &bvc);
+ if (ebother != NULL) {
+ ec = ebother->prev; /* note: this is in direction c --> d*/
+ vc = bvc->v;
+ kc = ec->offset_l_spec;
+ vd = ec->is_rev ? ec->e->v1 : ec->e->v2;
+ }
+ else {
+ /* No bevvert for w, so C can't be beveled */
+ kc = 0.0f;
+ ec = NULL;
+ /* Find an edge from c that has same face */
+ lb = BM_face_edge_share_loop(eb->fnext, eb->e);
+ if (!lb) {
+ return no_collide_offset;
+ }
+ if (lb->next->v == vc)
+ vd = lb->next->next->v;
+ else if (lb->v == vc)
+ vd = lb->prev->v;
+ else {
+ return no_collide_offset;
+ }
+ }
+ if (ea->e == eb->e || (ec && ec->e == eb->e))
+ return no_collide_offset;
+ ka = ka / bp->offset;
+ kb = kb / bp->offset;
+ kc = kc / bp->offset;
+ th1 = angle_v3v3v3(va->co, vb->co, vc->co);
+ th2 = angle_v3v3v3(vb->co, vc->co, vd->co);
+
+ /* First calculate offset at which edge B collapses, which happens
+ * when advancing clones of A, B, C all meet at a point.
+ * This only happens if at least two of those three edges have non-zero k's */
+ sin1 = sinf(th1);
+ sin2 = sinf(th2);
+ if ((ka > 0.0f) + (kb > 0.0f) + (kc > 0.0f) >= 2) {
+ tan1 = tanf(th1);
+ tan2 = tanf(th2);
+ g = tan1 * tan2;
+ h = sin1 * sin2;
+ den = g * (ka * sin2 + kc * sin1) + kb * h * (tan1 + tan2);
+ if (den != 0.0f) {
+ t = BM_edge_calc_length(eb->e);
+ t *= g * h / den;
+ if (t >= 0.0f)
+ limit = t;
+ }
+ }
+
+ /* Now check edge slide cases */
+ if (kb > 0.0f && ka == 0.0f /*&& bvb->selcount == 1 && bvb->edgecount > 2*/) {
+ t = BM_edge_calc_length(ea->e);
+ t *= sin1 / kb;
+ if (t >= 0.0f && t < limit)
+ limit = t;
+ }
+ if (kb > 0.0f && kc == 0.0f /* && bvc && ec && bvc->selcount == 1 && bvc->edgecount > 2 */) {
+ t = BM_edge_calc_length(ec->e);
+ t *= sin2 / kb;
+ if (t >= 0.0f && t < limit)
+ limit = t;
+ }
+ return limit;
+}
+
+/*
+ * We have an edge A between vertices a and b,
+ * where EdgeHalf ea is the half of A that starts at a.
+ * For vertex-only bevels, the new vertices slide from a at a rate ka*t
+ * and from b at a rate kb*t.
+ * We want to calculate the t at which the two meet.
+ */
+static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea)
+{
+ float limit, ka, kb, no_collide_offset, la, kab;
+ EdgeHalf *eb;
+
+ limit = no_collide_offset = bp->offset + 1e6;
+ if (bp->offset == 0.0f)
+ return no_collide_offset;
+ ka = ea->offset_l_spec / bp->offset;
+ eb = find_other_end_edge_half(bp, ea, NULL);
+ kb = eb ? eb->offset_l_spec / bp->offset : 0.0f;
+ kab = ka + kb;
+ la = BM_edge_calc_length(ea->e);
+ if (kab <= 0.0f)
+ return no_collide_offset;
+ limit = la / kab;
+ return limit;
+}
+
+/*
+ * Calculate an offset that is the lesser of the current
* bp.offset and the maximum possible offset before geometry
* collisions happen.
- * Currently this is a quick and dirty estimate of the max
- * possible: half the minimum edge length of any vertex involved
- * in a bevel. This is usually conservative.
- * The correct calculation is quite complicated.
- * TODO: implement this correctly.
+ * If the offset changes as a result of this, adjust the
+ * current edge offset specs to reflect this clamping,
+ * and store the new offset in bp.offset.
*/
-static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
+static void bevel_limit_offset(BevelParams *bp)
{
- BMVert *v;
- BMEdge *e;
- BMIter v_iter, e_iter;
- float limited_offset, half_elen;
- bool vbeveled;
+ BevVert *bv;
+ EdgeHalf *eh;
+ GHashIterator giter;
+ float limited_offset, offset_factor, collision_offset;
+ int i;
limited_offset = bp->offset;
- if (bp->offset_type == BEVEL_AMT_PERCENT) {
- if (limited_offset > 50.0f)
- limited_offset = 50.0f;
- return limited_offset;
- }
- BM_ITER_MESH (v, &v_iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ GHASH_ITER(giter, bp->vert_hash) {
+ bv = BLI_ghashIterator_getValue(&giter);
+ for (i = 0; i < bv->edgecount; i++) {
+ eh = &bv->edges[i];
if (bp->vertex_only) {
- vbeveled = true;
+ collision_offset = vertex_collide_offset(bp, eh);
+ if (collision_offset < limited_offset)
+ limited_offset = collision_offset;
}
else {
- vbeveled = false;
- BM_ITER_ELEM (e, &e_iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) {
- vbeveled = true;
- break;
- }
- }
+ collision_offset = geometry_collide_offset(bp, eh);
+ if (collision_offset < limited_offset)
+ limited_offset = collision_offset;
}
- if (vbeveled) {
- BM_ITER_ELEM (e, &e_iter, v, BM_EDGES_OF_VERT) {
- half_elen = 0.5f * BM_edge_calc_length(e);
- if (half_elen < limited_offset)
- limited_offset = half_elen;
- }
+ }
+ }
+
+ if (limited_offset < bp->offset) {
+ /* All current offset specs have some number times bp->offset,
+ * so we can just multiply them all by the reduction factor
+ * of the offset to have the effect of recalculating the specs
+ * with the new limited_offset.
+ */
+ offset_factor = limited_offset / bp->offset;
+ GHASH_ITER(giter, bp->vert_hash) {
+ bv = BLI_ghashIterator_getValue(&giter);
+ for (i = 0; i < bv->edgecount; i++) {
+ eh = &bv->edges[i];
+ eh->offset_l_spec *= offset_factor;
+ eh->offset_r_spec *= offset_factor;
+ eh->offset_l *= offset_factor;
+ eh->offset_r *= offset_factor;
}
}
+ bp->offset = limited_offset;
}
- return limited_offset;
}
/**
* - Currently only bevels BM_ELEM_TAG'd verts and edges.
*
- * - Newly created faces are BM_ELEM_TAG'd too,
- * the caller needs to ensure this is cleared before calling
- * if its going to use this face tag.
+ * - Newly created faces, edges, and verts are BM_ELEM_TAG'd too,
+ * the caller needs to ensure these are cleared before calling
+ * if its going to use this tag.
*
* - If limit_offset is set, adjusts offset down if necessary
* to avoid geometry collisions.
@@ -4560,6 +4749,7 @@ void BM_mesh_bevel(
BMEdge *e;
BevVert *bv;
BevelParams bp = {NULL};
+ GHashIterator giter;
bp.offset = offset;
bp.offset_type = offset_type;
@@ -4583,24 +4773,33 @@ void BM_mesh_bevel(
BLI_memarena_use_calloc(bp.mem_arena);
set_profile_spacing(&bp);
- if (limit_offset)
- bp.offset = bevel_limit_offset(bm, &bp);
-
/* Analyze input vertices, sorting edges and assigning initial new vertex positions */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bv = bevel_vert_construct(bm, &bp, v);
- if (bv)
+ if (!limit_offset && bv)
build_boundary(&bp, bv, true);
}
}
+ /* Perhaps clamp offset to avoid geometry colliisions */
+ if (limit_offset) {
+ bevel_limit_offset(&bp);
+
+ /* Assign initial new vertex positions */
+ GHASH_ITER(giter, bp.vert_hash) {
+ bv = BLI_ghashIterator_getValue(&giter);
+ build_boundary(&bp, bv, true);
+ }
+ }
+
/* Perhaps do a pass to try to even out widths */
if (!bp.vertex_only) {
adjust_offsets(&bp);
}
/* Build the meshes around vertices, now that positions are final */
+ /* Note: could use GHASH_ITER over bp.vert_hash when backward compatibility no longer matters */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bv = find_bevvert(&bp, v);
@@ -4633,6 +4832,20 @@ void BM_mesh_bevel(
}
}
+ /* When called from operator (as opposed to modifier), bm->use_toolflags
+ * will be set, and we to transfer the oflags to BM_ELEM_TAGs */
+ if (bm->use_toolflags) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, VERT_OUT))
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm, e, EDGE_OUT)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
+ }
+
/* primary free */
BLI_ghash_free(bp.vert_hash, NULL, NULL);
BLI_memarena_free(bp.mem_arena);
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index 3bff20e846b..b3d512204be 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -530,7 +530,7 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_
addSampler(sampler);
- std::string target = translate_id(bone_name) + "/transform";
+ std::string target = get_joint_id(bone, ob_arm) + "/transform";
addChannel(COLLADABU::URI(empty, sampler_id), target);
closeAnimation();
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 9348f3b3285..d2495a8cb9f 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -116,7 +116,10 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
ins.add();
return true;
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index 1c2642e8313..5cd5e6d271a 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -98,7 +98,10 @@ bool ControllerExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
ins.add();
return true;
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index bd32e989ae3..634071bc90f 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -138,7 +138,8 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
{
int layer_index = CustomData_get_layer_index(data, type);
- if (layer_index < 0) return NULL;
+ if (layer_index < 0)
+ return NULL;
return data->layers[layer_index + n].name;
}
@@ -147,9 +148,10 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
- if (layer_index < 0) return NULL;
+ if (layer_index < 1)
+ return NULL;
- return data->layers[layer_index].name;
+ return bc_CustomData_get_layer_name(data, type, layer_index-1);
}
DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 226f319cefd..435eaa0208a 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -388,9 +388,7 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera
Camera *cam = uid_camera_map[cam_uid];
Camera *old_cam = (Camera *)ob->data;
ob->data = cam;
- id_us_min(&old_cam->id);
- if (old_cam->id.us == 0)
- BKE_libblock_free(G.main, old_cam);
+ BKE_libblock_free_us(G.main, old_cam);
return ob;
}
@@ -406,9 +404,7 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce
Lamp *la = uid_lamp_map[lamp_uid];
Lamp *old_lamp = (Lamp *)ob->data;
ob->data = la;
- id_us_min(&old_lamp->id);
- if (old_lamp->id.us == 0)
- BKE_libblock_free(G.main, old_lamp);
+ BKE_libblock_free_us(G.main, old_lamp);
return ob;
}
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 76b51148509..2bf0859b0f0 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -27,7 +27,6 @@
#include <map>
-#include <set>
#include "COLLADASWEffectProfile.h"
#include "COLLADAFWColorOrTexture.h"
@@ -49,21 +48,10 @@ extern "C" {
#include "BKE_material.h"
}
-// OB_MESH is assumed
-static std::string getActiveUVLayerName(Object *ob)
-{
- Mesh *me = (Mesh *)ob->data;
-
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- if (num_layers)
- return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
-
- return "";
-}
-
EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
}
+
bool EffectsExporter::hasEffects(Scene *sce)
{
Base *base = (Base *)sce->base.first;
@@ -86,13 +74,49 @@ bool EffectsExporter::hasEffects(Scene *sce)
void EffectsExporter::exportEffects(Scene *sce)
{
- if (hasEffects(sce)) {
- this->scene = sce;
- openLibrary();
- MaterialFunctor mf;
- mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
-
- closeLibrary();
+ this->scene = sce;
+
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
+ if (hasEffects(sce)) {
+ MaterialFunctor mf;
+ openLibrary();
+ mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
+ closeLibrary();
+ }
+ }
+ else {
+ std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only);
+ std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
+ if (uv_images.size() > 0) {
+ openLibrary();
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string key(id_name(ima));
+ key = translate_id(key);
+ COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
+ key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
+ key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
+ sampler.setImageId(key);
+
+ openEffect(key + "-effect");
+ COLLADASW::EffectProfile ep(mSW);
+ ep.setProfileType(COLLADASW::EffectProfile::COMMON);
+ ep.setShaderType(COLLADASW::EffectProfile::PHONG);
+ ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse");
+ COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f);
+ ep.setSpecular(cot, false, "specular");
+ ep.openProfile();
+ ep.addProfileElements();
+ ep.addExtraTechniques(mSW);
+ ep.closeProfile();
+ closeEffect();
+ }
+ closeLibrary();
+ }
}
}
@@ -176,8 +200,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
{
// create a list of indices to textures of type TEX_IMAGE
std::vector<int> tex_indices;
- if (this->export_settings->include_material_textures)
- createTextureIndices(ma, tex_indices);
+ createTextureIndices(ma, tex_indices);
openEffect(translate_id(id_name(ma)) + "-effect");
@@ -311,61 +334,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
}
}
- int active_uv_layer = -1;
- std::set<Image *> uv_textures;
- if (ob->type == OB_MESH && ob->totcol && this->export_settings->include_uv_textures) {
- bool active_uv_only = this->export_settings->active_uv_only;
- Mesh *me = (Mesh *) ob->data;
- active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
-
- BKE_mesh_tessface_ensure(me);
- for (int i = 0; i < me->pdata.totlayer; i++) {
- if (!active_uv_only || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Material *mat = give_current_material(ob, mpoly->mat_nr + 1);
- if (mat != ma)
- continue;
-
- Image *ima = txface->tpage;
- if (ima == NULL)
- continue;
-
-
- bool not_in_list = uv_textures.find(ima)==uv_textures.end();
- if (not_in_list) {
- std::string name = id_name(ima);
- std::string key(name);
- key = translate_id(key);
-
- // create only one <sampler>/<surface> pair for each unique image
- if (im_samp_map.find(key) == im_samp_map.end()) {
- //<newparam> <sampler> <source>
- COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
- key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
- key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
- sampler.setImageId(key);
- samplers[a] = sampler;
- samp_surf[b] = &samplers[a];
- im_samp_map[key] = b;
- b++;
- a++;
- uv_textures.insert(ima);
- }
- }
- }
- }
- }
- }
- }
-
// used as fallback when MTex->uvname is "" (this is pretty common)
// it is indeed the correct value to use in that case
- std::string active_uv(getActiveUVLayerName(ob));
+ std::string active_uv(bc_get_active_uvlayer_name(ob));
// write textures
// XXX very slow
@@ -385,19 +356,6 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
writeTextures(ep, key, sampler, t, ima, uvname);
}
- std::set<Image *>::iterator uv_t_iter;
- int idx;
- for (idx = 0, uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++, idx++ ) {
- if (active_uv_layer>-1 && idx==active_uv_layer) {
- Image *ima = *uv_t_iter;
- std::string key(id_name(ima));
- key = translate_id(key);
- int i = im_samp_map[key];
- COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i];
- ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse");
- }
- }
-
// performs the actual writing
ep.addProfileElements();
bool twoSided = false;
diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h
index d20cbfdfe0b..7d45a085777 100644
--- a/source/blender/collada/EffectExporter.h
+++ b/source/blender/collada/EffectExporter.h
@@ -48,7 +48,6 @@ class EffectsExporter: COLLADASW::LibraryEffects
public:
EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
void exportEffects(Scene *sce);
-
void operator()(Material *ma, Object *ob);
COLLADASW::ColorOrTexture createTexture(Image *ima,
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index 98aa85f8a9b..32aa5636e08 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -49,7 +49,7 @@ ErrorHandler::~ErrorHandler()
//--------------------------------------------------------------------
bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
{
- bool isError = true;
+ bool isError = false;
if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) {
COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error;
@@ -81,10 +81,7 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
* Accept non critical errors as warnings (i.e. texture not found)
* This makes the importer more graceful, so it now imports what makes sense.
*/
- if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) {
- isError = false;
- }
-
+ isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL);
std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl;
}
else {
@@ -93,5 +90,5 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
mError |= isError;
- return false; // let OpenCollada decide when to abort
+ return isError; // let OpenCollada decide when to abort
}
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index de91f68a492..6d90edd2f67 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -28,7 +28,6 @@
#define __EXPORTSETTINGS_H__
#include "collada.h"
-#include "collada.h"
struct ExportSettings {
public:
@@ -42,8 +41,7 @@ public:
bool deform_bones_only;
bool active_uv_only;
- bool include_uv_textures;
- bool include_material_textures;
+ BC_export_texture_type export_texture_type;
bool use_texture_copies;
bool triangulate;
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index 7a72c77b2af..6c5968bdf2a 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -52,6 +52,7 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
+
// TODO: optimize UV sets by making indexed list with duplicates removed
GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
{
@@ -134,13 +135,22 @@ void GeometryExporter::operator()(Object *ob)
// Only create Polylists if number of faces > 0
if (me->totface > 0) {
// XXX slow
- if (ob->totcol) {
- for (int a = 0; a < ob->totcol; a++) {
- createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
+ std::set<Image *> uv_images = bc_getUVImages(ob, !this->export_settings->active_uv_only);
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT || uv_images.size() == 0) {
+ if (ob->totcol) {
+ for (int a = 0; a < ob->totcol; a++) {
+ createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+ }
+ else {
+ int i = 0;
+ createPolylist(i, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+ bool all_uv_layers = !this->export_settings->active_uv_only;
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
}
}
@@ -220,13 +230,15 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
//createLooseEdgeList(ob, me, geom_id, norind);
// XXX slow
- if (ob->totcol) {
+ if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
for (int a = 0; a < ob->totcol; a++) {
createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+ bool all_uv_layers = !this->export_settings->active_uv_only;
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
}
closeMesh();
@@ -295,7 +307,44 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char
return result;
}
-// powerful because it handles both cases when there is material and when there's not
+static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase *facelist, std::vector<unsigned long> &vcount_list)
+{
+ // performs the actual writing
+ if (is_triangulated) {
+ ((COLLADASW::Triangles *)facelist)->prepareToAppendValues();
+ }
+ else {
+ // sets <vcount>
+ facelist->setVCountList(vcount_list);
+ ((COLLADASW::Polylist *)facelist)-> prepareToAppendValues();
+ }
+}
+
+static void finishList(bool is_triangulated, COLLADASW::PrimitivesBase *facelist)
+{
+ if (is_triangulated) {
+ ((COLLADASW::Triangles *)facelist)->finish();
+ }
+ else {
+ ((COLLADASW::Polylist *)facelist)->finish();
+ }
+}
+
+COLLADASW::PrimitivesBase *getFacelist(bool is_triangulated, COLLADASW::StreamWriter *mSW)
+{
+ COLLADASW::PrimitivesBase *facelist;
+
+ if (is_triangulated)
+ {
+ facelist = new COLLADASW::Triangles(mSW);
+ }
+ else {
+ facelist = new COLLADASW::Polylist(mSW);
+ }
+ return facelist;
+}
+
+// Export meshes with Materials
void GeometryExporter::createPolylist(short material_index,
bool has_uvs,
bool has_color,
@@ -313,7 +362,7 @@ void GeometryExporter::createPolylist(short material_index,
int i;
int faces_in_polylist = 0;
std::vector<unsigned long> vcount_list;
-
+ bool is_triangulated = true;
// count faces with this material
for (i = 0; i < totpolys; i++) {
MPoly *p = &mpolys[i];
@@ -321,6 +370,9 @@ void GeometryExporter::createPolylist(short material_index,
if (p->mat_nr == material_index) {
faces_in_polylist++;
vcount_list.push_back(p->totloop);
+ if (p->totloop != 3) {
+ is_triangulated = false;
+ }
}
}
@@ -331,20 +383,21 @@ void GeometryExporter::createPolylist(short material_index,
}
Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
- COLLADASW::Polylist polylist(mSW);
+ COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
+
// sets count attribute in <polylist>
- polylist.setCount(faces_in_polylist);
+ facelist->setCount(faces_in_polylist);
// sets material name
if (ma) {
std::string material_id = get_material_id(ma);
std::ostringstream ostr;
ostr << translate_id(material_id);
- polylist.setMaterial(ostr.str());
+ facelist->setMaterial(ostr.str());
}
- COLLADASW::InputList &til = polylist.getInputList();
+ COLLADASW::InputList &til = facelist->getInputList();
// creates <input> in <polylist> for vertices
COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
@@ -360,13 +413,21 @@ void GeometryExporter::createPolylist(short material_index,
int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
for (i = 0; i < num_layers; i++) {
if (!this->export_settings->active_uv_only || i == active_uv_index) {
-
- // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
+
+ std::string uv_name(bc_get_uvlayer_name(me, i));
+ std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ i, this->export_settings->active_uv_only);
+
+ /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
+ For now this is always 2 (This may change sometime/maybe)
+ */
COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
- 2, // this is only until we have optimized UV sets
- (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
- );
+ makeUrl(layer_id),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
+ );
til.push_back(input3);
}
}
@@ -387,12 +448,10 @@ void GeometryExporter::createPolylist(short material_index,
}
}
- // sets <vcount>
- polylist.setVCountList(vcount_list);
// performs the actual writing
- polylist.prepareToAppendValues();
-
+ prepareToAppendValues(is_triangulated, facelist, vcount_list);
+
// <p>
int texindex = 0;
for (i = 0; i < totpolys; i++) {
@@ -404,22 +463,202 @@ void GeometryExporter::createPolylist(short material_index,
BCPolygonNormalsIndices normal_indices = norind[i];
for (int j = 0; j < loop_count; j++) {
- polylist.appendValues(l[j].v);
- polylist.appendValues(normal_indices[j]);
+ facelist->appendValues(l[j].v);
+ facelist->appendValues(normal_indices[j]);
if (has_uvs)
- polylist.appendValues(texindex + j);
+ facelist->appendValues(texindex + j);
if (has_color)
- polylist.appendValues(texindex + j);
+ facelist->appendValues(texindex + j);
}
}
texindex += loop_count;
}
-
- polylist.finish();
+
+ finishList(is_triangulated, facelist);
+ delete facelist;
+}
+
+void GeometryExporter::createPolylists(std::set<Image *> uv_images,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind)
+{
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string imageid(id_name(ima));
+ createPolylist(imageid, has_uvs,
+ has_color,
+ ob,
+ me,
+ geom_id,
+ norind);
+ }
+
+ /* We msut add an additional collector for the case when
+ * some parts of the object are not textured at all.
+ * The next call creates a polylist for all untextured polygons
+ */
+
+ createPolylist("", has_uvs,
+ has_color,
+ ob,
+ me,
+ geom_id,
+ norind);
+
}
+/* ===========================================================================
+ * Export Meshes with UV Textures (export as materials, see also in
+ * effectExporter and MaterialExporter)
+ *
+ * If imageid is the empty string, then collect only untextured polygons
+ * =========================================================================== */
+void GeometryExporter::createPolylist(std::string imageid,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind)
+{
+
+ MPoly *mpolys = me->mpoly;
+ MLoop *mloops = me->mloop;
+ MTexPoly *mtpolys = me->mtpoly;
+
+ int totpolys = me->totpoly;
+
+ // <vcount>
+ int i;
+ int faces_in_polylist = 0;
+ std::vector<unsigned long> vcount_list;
+ bool is_triangulated = true;
+ // count faces with this material
+ for (i = 0; i < totpolys; i++) {
+ MTexPoly *tp = &mtpolys[i];
+ MPoly *p = &mpolys[i];
+
+ std::string tpageid = (tp->tpage) ? id_name(tp->tpage):"";
+ if (tpageid == imageid) {
+ faces_in_polylist++;
+ vcount_list.push_back(p->totloop);
+ if (p->totloop != 3) {
+ is_triangulated = false;
+ }
+ }
+ }
+
+ // no faces using this imageid
+ if (faces_in_polylist == 0) {
+ if (imageid != "")
+ fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid.c_str());
+ return;
+ }
+
+ COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
+
+ // sets count attribute in <polylist>
+ facelist->setCount(faces_in_polylist);
+
+ if (imageid != "") {
+ // sets material name
+ std::string material_id = get_material_id_from_id(imageid);
+ std::ostringstream ostr;
+ ostr << translate_id(material_id);
+ facelist->setMaterial(ostr.str());
+ }
+ COLLADASW::InputList &til = facelist->getInputList();
+
+ // creates <input> in <polylist> for vertices
+ COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
+
+ // creates <input> in <polylist> for normals
+ COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
+
+ til.push_back(input1);
+ til.push_back(input2);
+
+ // if mesh has uv coords writes <input> for TEXCOORD
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+ for (i = 0; i < num_layers; i++) {
+ if (!this->export_settings->active_uv_only || i == active_uv_index) {
+
+ std::string uv_name(bc_get_uvlayer_name(me, i));
+ std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ i, this->export_settings->active_uv_only);
+
+ /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
+ For now this is always 2 (This may change sometime/maybe)
+ */
+ COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
+ makeUrl(layer_id),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
+ );
+ til.push_back(input3);
+ }
+ }
+
+ int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
+ if (totlayer_mcol > 0) {
+ int map_index = 0;
+
+ for (int a = 0; a < totlayer_mcol; a++) {
+ char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
+ COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
+ makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
+ (has_uvs) ? 3 : 2, // all color layers have same index order
+ map_index // set number equals color map index
+ );
+ til.push_back(input4);
+ map_index++;
+ }
+ }
+
+ // performs the actual writing
+ prepareToAppendValues(is_triangulated, facelist, vcount_list);
+
+ // <p>
+ int texindex = 0;
+ for (i = 0; i < totpolys; i++) {
+ MTexPoly *tp = &mtpolys[i];
+ MPoly *p = &mpolys[i];
+ int loop_count = p->totloop;
+ std::string tpageid = (tp->tpage) ? id_name(tp->tpage) : "";
+ if (tpageid == imageid) {
+ MLoop *l = &mloops[p->loopstart];
+ BCPolygonNormalsIndices normal_indices = norind[i];
+
+ for (int j = 0; j < loop_count; j++) {
+ facelist->appendValues(l[j].v);
+ facelist->appendValues(normal_indices[j]);
+ if (has_uvs)
+ facelist->appendValues(texindex + j);
+
+ if (has_color)
+ facelist->appendValues(texindex + j);
+ }
+ }
+
+ texindex += loop_count;
+ }
+
+ finishList(is_triangulated, facelist);
+ delete facelist;
+}
// creates <source> for positions
void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
@@ -539,7 +778,13 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
- std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
+ std::string active_uv_name(bc_get_active_uvlayer_name(me));
+ std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ a,
+ this->export_settings->active_uv_only );
+
source.setId(layer_id);
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 69d1067e6f4..890304f4568 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -85,15 +85,33 @@ public:
Mesh *me,
std::string& geom_id);
- // powerful because it handles both cases when there is material and when there's not
+ // Create polylists for meshes with Materials
void createPolylist(short material_index,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
-
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
+ // Create polylists for meshes with UV Textures
+ void createPolylists(std::set<Image *> uv_images,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
+ // Create polylists for meshes with UV Textures
+ void createPolylist(std::string imageid,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
// creates <source> for positions
void createVertsSource(std::string geom_id, Mesh *me);
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index aac41e2e93c..93be7de6236 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -55,9 +55,9 @@ ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings
void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
{
- std::string name(id_name(image));
- std::string translated_name(translate_id(name));
- bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end();
+ std::string id(id_name(image));
+ std::string translated_id(translate_id(id));
+ bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end();
if (not_yet_exported) {
@@ -88,7 +88,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
// make absolute destination path
- BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
+ BLI_strncpy(export_file, id.c_str(), sizeof(export_file));
BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
@@ -143,10 +143,11 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
}
}
- COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+ /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+ COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id);
img.add(mSW);
fprintf(stdout, "Collada export: Added image: %s\n", export_file);
- mImages.push_back(translated_name);
+ mImages.push_back(translated_id);
BKE_image_release_ibuf(image, imbuf, NULL);
}
@@ -161,7 +162,7 @@ void ImagesExporter::export_UV_Images()
for (node = this->export_settings->export_set; node; node = node->next) {
Object *ob = (Object *)node->link;
- if (ob->type == OB_MESH && ob->totcol) {
+ if (ob->type == OB_MESH) {
Mesh *me = (Mesh *) ob->data;
BKE_mesh_tessface_ensure(me);
int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
@@ -189,7 +190,13 @@ void ImagesExporter::export_UV_Images()
}
}
-
+/* ============================================================
+ * Check if there are any images to be exported
+ * Returns true as soon as an object is detected that
+ * either has an UV Texture assigned, or has a material
+ * assigned that uses an Image Texture.
+ * ============================================================
+ */
bool ImagesExporter::hasImages(Scene *sce)
{
LinkNode *node;
@@ -232,11 +239,10 @@ void ImagesExporter::exportImages(Scene *sce)
openLibrary();
MaterialFunctor mf;
- if (this->export_settings->include_material_textures) {
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
mf.forEachMaterialInExportSet<ImagesExporter>(sce, *this, this->export_settings->export_set);
}
-
- if (this->export_settings->include_uv_textures) {
+ else {
export_UV_Images();
}
diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp
index 71371d280df..de1a4075462 100644
--- a/source/blender/collada/InstanceWriter.cpp
+++ b/source/blender/collada/InstanceWriter.cpp
@@ -32,43 +32,76 @@
#include "COLLADASWInstanceMaterial.h"
extern "C" {
- #include "BKE_customdata.h"
- #include "BKE_material.h"
- #include "DNA_mesh_types.h"
+#include "BKE_customdata.h"
+#include "BKE_material.h"
+#include "DNA_mesh_types.h"
}
#include "InstanceWriter.h"
#include "collada_internal.h"
#include "collada_utils.h"
-void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only)
+void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
{
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
-
- COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
+ bool all_uv_layers = !active_uv_only;
+ COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
- if (ma) {
- std::string matid(get_material_id(ma));
- matid = translate_id(matid);
+ if (export_texture_type == BC_TEXTURE_TYPE_UV)
+ {
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+ Image *ima = *uv_images_iter;
+ std::string matid(id_name(ima));
+ matid = get_material_id_from_id(matid);
std::ostringstream ostr;
ostr << matid;
COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
-
+
// create <bind_vertex_input> for each uv map
Mesh *me = (Mesh *)ob->data;
int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-
+
int map_index = 0;
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) -1;
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
for (int b = 0; b < totlayer; b++) {
if (!active_uv_only || b == active_uv_index) {
char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
}
}
-
+
iml.push_back(im);
}
}
+
+ else {
+ for (int a = 0; a < ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a + 1);
+ if (ma) {
+ std::string matid(get_material_id(ma));
+ matid = translate_id(matid);
+ std::ostringstream ostr;
+ ostr << matid;
+ COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
+
+ // create <bind_vertex_input> for each uv map
+ Mesh *me = (Mesh *)ob->data;
+ int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+
+ int map_index = 0;
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+ for (int b = 0; b < totlayer; b++) {
+ if (!active_uv_only || b == active_uv_index) {
+ char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
+ im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
+ }
+ }
+
+ iml.push_back(im);
+ }
+ }
+ }
}
diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h
index 49ddf091b1c..a46027325a2 100644
--- a/source/blender/collada/InstanceWriter.h
+++ b/source/blender/collada/InstanceWriter.h
@@ -31,11 +31,12 @@
#include "COLLADASWBindMaterial.h"
#include "DNA_object_types.h"
+#include "collada.h"
class InstanceWriter
{
protected:
- void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only);
+ void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type);
};
#endif
diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp
index 4aece997f72..6e6cc24be20 100644
--- a/source/blender/collada/MaterialExporter.cpp
+++ b/source/blender/collada/MaterialExporter.cpp
@@ -38,14 +38,39 @@ MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSe
void MaterialsExporter::exportMaterials(Scene *sce)
{
- if (hasMaterials(sce)) {
- openLibrary();
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT)
+ {
+ if (hasMaterials(sce)) {
+ openLibrary();
- MaterialFunctor mf;
- mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
+ MaterialFunctor mf;
+ mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
- closeLibrary();
+ closeLibrary();
+ }
}
+
+ else {
+ std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
+ if (uv_images.size() > 0) {
+ openLibrary();
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string matid(id_name(ima));
+
+ openMaterial(get_material_id_from_id(matid), translate_id(matid));
+ std::string efid = translate_id(matid) + "-effect";
+ addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid));
+ closeMaterial();
+ }
+ closeLibrary();
+ }
+ }
+
}
bool MaterialsExporter::hasMaterials(Scene *sce)
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index a1bfce88131..6ca53c64299 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -1173,8 +1173,9 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
BKE_mesh_assign_object(ob, new_mesh);
BKE_mesh_calc_normals(new_mesh);
- if (old_mesh->id.us == 0) BKE_libblock_free(G.main, old_mesh);
-
+ id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */
+ BKE_libblock_free_us(G.main, old_mesh);
+
char layername[100];
layername[0] = '\0';
MTFace *texture_face = NULL;
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 30cd6ddf197..73945539931 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -151,7 +151,10 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
COLLADASW::InstanceGeometry instGeom(mSW);
instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
instGeom.setName(translate_id(id_name(ob)));
- InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(instGeom.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
instGeom.add();
}
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index bfe3180909b..024bc4a4a5c 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -80,8 +80,7 @@ int collada_export(Scene *sce,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ BC_export_texture_type export_texture_type,
int use_texture_copies,
int triangulate,
@@ -106,8 +105,7 @@ int collada_export(Scene *sce,
export_settings.deform_bones_only = deform_bones_only != 0;
export_settings.active_uv_only = active_uv_only != 0;
- export_settings.include_uv_textures = include_uv_textures != 0;
- export_settings.include_material_textures= include_material_textures != 0;
+ export_settings.export_texture_type = export_texture_type;
export_settings.use_texture_copies = use_texture_copies != 0;
export_settings.triangulate = triangulate != 0;
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index 8035af59c8b..d31f5a8ba62 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -46,6 +46,11 @@ typedef enum BC_export_transformation_type {
BC_TRANSFORMATION_TYPE_TRANSROTLOC
} BC_export_transformation_type;
+typedef enum BC_export_texture_type {
+ BC_TEXTURE_TYPE_MAT,
+ BC_TEXTURE_TYPE_UV
+} BC_export_texture_type;
+
struct bContext;
struct Scene;
@@ -74,8 +79,7 @@ int collada_export(struct Scene *sce,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ BC_export_texture_type export_texture_type,
int use_texture_copies,
int triangulate,
@@ -84,9 +88,9 @@ int collada_export(struct Scene *sce,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim,
- int limit_precision,
- int keep_bind_info);
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info);
#ifdef __cplusplus
}
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index 6ebde6bd773..8974acb3460 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -344,7 +344,13 @@ std::string get_camera_id(Object *ob)
std::string get_material_id(Material *mat)
{
- return translate_id(id_name(mat)) + "-material";
+ std::string id = id_name(mat);
+ return get_material_id_from_id(id);
+}
+
+std::string get_material_id_from_id(std::string id)
+{
+ return translate_id(id) + "-material";
}
std::string get_morph_id(Object *ob)
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index 1c7aa160f57..5f3fa34edc1 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -103,6 +103,7 @@ extern std::string get_joint_sid(Bone *bone, Object *ob_arm);
extern std::string get_camera_id(Object *ob);
extern std::string get_material_id(Material *mat);
+extern std::string get_material_id_from_id(std::string id);
extern std::string get_morph_id(Object *ob);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index ac4395e1430..b09732f9102 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -32,6 +32,8 @@
#include "COLLADAFWMeshPrimitive.h"
#include "COLLADAFWMeshVertexData.h"
+#include <set>
+
extern "C" {
#include "DNA_modifier_types.h"
#include "DNA_customdata_types.h"
@@ -831,4 +833,160 @@ void bc_sanitize_mat(float mat[4][4], int precision)
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
mat[i][j] = double_round(mat[i][j], precision);
+}
+
+/*
+* Returns name of Active UV Layer or empty String if no active UV Layer defined.
+* Assuming the Object is of type MESH
+*/
+std::string bc_get_active_uvlayer_name(Object *ob)
+{
+ Mesh *me = (Mesh *)ob->data;
+ return bc_get_active_uvlayer_name(me);
+}
+
+/*
+ * Returns name of Active UV Layer or empty String if no active UV Layer defined
+ */
+std::string bc_get_active_uvlayer_name(Mesh *me)
+{
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers) {
+ return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
+ }
+ return "";
+}
+
+/*
+ * Returns UV Layer name or empty string if layer index is out of range
+ */
+std::string bc_get_uvlayer_name(Mesh *me, int layer)
+{
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers && layer < num_layers) {
+ return std::string(bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer));
+ }
+ return "";
+}
+
+/**********************************************************************
+*
+* Return the list of Mesh objects with assigned UVtextures and Images
+* Note: We need to create artificaial materials for each of them
+*
+***********************************************************************/
+std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
+{
+ std::set <Object *> UVObjects;
+ Base *base = (Base *)sce->base.first;
+
+ while (base) {
+ Object *ob = base->object;
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ has_uvimage = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (has_uvimage) {
+ UVObjects.insert(ob);
+ }
+ }
+ base = base->next;
+ }
+ return UVObjects;
+}
+
+/**********************************************************************
+*
+* Return the list of UV Texture images from all exported Mesh Items
+* Note: We need to create one artificial material for each Image.
+*
+***********************************************************************/
+std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
+{
+ std::set <Image *> UVImages;
+ Base *base = (Base *)sce->base.first;
+
+ while (base) {
+ Object *ob = base->object;
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ if (UVImages.find(ima) == UVImages.end())
+ UVImages.insert(ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ base = base->next;
+ }
+ return UVImages;
+}
+
+/**********************************************************************
+*
+* Return the list of UV Texture images for the given Object
+* Note: We need to create one artificial material for each Image.
+*
+***********************************************************************/
+std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
+{
+ std::set <Image *> UVImages;
+
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ if (UVImages.find(ima) == UVImages.end())
+ UVImages.insert(ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ return UVImages;
} \ No newline at end of file
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 38c0bd5096a..5447c39e902 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -34,6 +34,7 @@
#include <vector>
#include <map>
+#include <set>
#include <algorithm>
extern "C" {
@@ -80,6 +81,7 @@ extern void bc_set_mark(Object *ob);
extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n);
extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type);
+extern char *bc_CustomData_get_layer_name(const CustomData *data, int layer_index, int type);
extern void bc_bubble_sort_by_Object_name(LinkNode *export_set);
extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only);
@@ -109,6 +111,14 @@ extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space);
+extern std::string bc_get_active_uvlayer_name(Object *ob);
+extern std::string bc_get_active_uvlayer_name(Mesh *me);
+extern std::string bc_get_uvlayer_name(Mesh *me, int layer);
+
+extern std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers);
+extern std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers);
+extern std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers);
+
class BCPolygonNormalsIndices
{
std::vector<unsigned int> normal_indices;
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index 462947f32a3..81891d853d2 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -99,6 +99,11 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name));
int view = 0;
+ if (STREQ(storage->pass_name, RE_PASSNAME_COMBINED) && STREQ(bnodeSocket->name, "Alpha")) {
+ /* Alpha output is already handled with the associated combined output. */
+ continue;
+ }
+
/* returns the image view to use for the current active view */
if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) {
const int view_image = imageuser->view;
@@ -140,16 +145,24 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
converter.addPreview(operation->getOutputSocket());
}
if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
- BLI_assert(operation != NULL);
- BLI_assert(index < numberOfOutputs - 1);
- NodeOutput *outputSocket = this->getOutputSocket(index + 1);
- SeparateChannelOperation *separate_operation;
- separate_operation = new SeparateChannelOperation();
- separate_operation->setChannel(3);
- converter.addOperation(separate_operation);
- converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0));
- converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket());
- index++;
+ for (int alphaIndex = 0; alphaIndex < numberOfOutputs; alphaIndex++) {
+ NodeOutput *alphaSocket = this->getOutputSocket(alphaIndex);
+ bNodeSocket *bnodeAlphaSocket = alphaSocket->getbNodeSocket();
+ if (!STREQ(bnodeAlphaSocket->name, "Alpha")) {
+ continue;
+ }
+ NodeImageLayer *alphaStorage = (NodeImageLayer *)bnodeSocket->storage;
+ if (!STREQ(alphaStorage->pass_name, RE_PASSNAME_COMBINED)) {
+ continue;
+ }
+ SeparateChannelOperation *separate_operation;
+ separate_operation = new SeparateChannelOperation();
+ separate_operation->setChannel(3);
+ converter.addOperation(separate_operation);
+ converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0));
+ converter.mapOutputSocket(alphaSocket, separate_operation->getOutputSocket());
+ break;
+ }
}
}
diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
index 57aa3a1bac2..94f407dad86 100644
--- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
@@ -65,10 +65,10 @@ void GlareSimpleStarOperation::generateGlare(float *data, MemoryBuffer *inputTil
}
}
// // B
- for (y = tbuf1->getHeight() - 1 && (!breaked); y >= 0; y--) {
+ for (y = this->getHeight() - 1; y >= 0 && (!breaked); y--) {
ym = y - i;
yp = y + i;
- for (x = tbuf1->getWidth() - 1; x >= 0; x--) {
+ for (x = this->getWidth() - 1; x >= 0; x--) {
xm = x - i;
xp = x + i;
tbuf1->read(c, x, y);
diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp
index 41f7da7c49f..0c2da8415f8 100644
--- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp
@@ -28,55 +28,58 @@ extern "C" {
MovieClipAttributeOperation::MovieClipAttributeOperation() : NodeOperation()
{
this->addOutputSocket(COM_DT_VALUE);
- this->m_valueSet = false;
this->m_framenumber = 0;
this->m_attribute = MCA_X;
this->m_invert = false;
}
-void MovieClipAttributeOperation::executePixelSampled(float output[4],
- float /*x*/, float /*y*/,
- PixelSampler /*sampler*/)
+void MovieClipAttributeOperation::initExecution()
{
- /* TODO(sergey): This code isn't really thread-safe. */
- if (!this->m_valueSet) {
- float loc[2], scale, angle;
- loc[0] = 0.0f;
- loc[1] = 0.0f;
- scale = 1.0f;
- 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, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle);
- }
- switch (this->m_attribute) {
- case MCA_SCALE:
- this->m_value = scale;
- break;
- case MCA_ANGLE:
- this->m_value = angle;
- break;
- case MCA_X:
- this->m_value = loc[0];
- break;
- case MCA_Y:
- this->m_value = loc[1];
- break;
+ float loc[2], scale, angle;
+ loc[0] = 0.0f;
+ loc[1] = 0.0f;
+ scale = 1.0f;
+ angle = 0.0f;
+ int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(
+ this->m_clip, this->m_framenumber);
+ BKE_tracking_stabilization_data_get(this->m_clip,
+ clip_framenr,
+ getWidth(), getHeight(),
+ loc, &scale, &angle);
+ switch (this->m_attribute) {
+ case MCA_SCALE:
+ this->m_value = scale;
+ break;
+ case MCA_ANGLE:
+ this->m_value = angle;
+ break;
+ case MCA_X:
+ this->m_value = loc[0];
+ break;
+ case MCA_Y:
+ this->m_value = loc[1];
+ break;
+ }
+ if (this->m_invert) {
+ if (this->m_attribute != MCA_SCALE) {
+ this->m_value = -this->m_value;
}
- if (this->m_invert) {
- if (this->m_attribute != MCA_SCALE) {
- this->m_value = -this->m_value;
- }
- else {
- this->m_value = 1.0f / this->m_value;
- }
+ else {
+ this->m_value = 1.0f / this->m_value;
}
- this->m_valueSet = true;
}
+}
+
+void MovieClipAttributeOperation::executePixelSampled(float output[4],
+ float /*x*/, float /*y*/,
+ PixelSampler /*sampler*/)
+{
output[0] = this->m_value;
}
-void MovieClipAttributeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void MovieClipAttributeOperation::determineResolution(
+ unsigned int resolution[2],
+ unsigned int preferredResolution[2])
{
resolution[0] = preferredResolution[0];
resolution[1] = preferredResolution[1];
diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
index 731b9debaf0..659f54c1ca2 100644
--- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
+++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
@@ -39,16 +39,18 @@ class MovieClipAttributeOperation : public NodeOperation {
private:
MovieClip *m_clip;
float m_value;
- bool m_valueSet;
int m_framenumber;
bool m_invert;
MovieClipAttribute m_attribute;
+
public:
/**
* Default constructor
*/
MovieClipAttributeOperation();
-
+
+ void initExecution();
+
/**
* the inner loop of this program
*/
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
index f2f1b211a97..26654b31e16 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -246,4 +246,4 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float
unsigned int offset = (iy * this->getWidth() + ix);
output[0] = inputBuffer[offset];
}
-} \ No newline at end of file
+}
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp
index 117ae743ee7..46e155e43b5 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.cpp
+++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp
@@ -271,9 +271,9 @@ bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, Read
{
rcti newInput;
- newInput.xmax = (input->xmax - m_offsetX) * this->m_relX;
+ newInput.xmax = (input->xmax - m_offsetX) * this->m_relX + 1;
newInput.xmin = (input->xmin - m_offsetX) * this->m_relX;
- newInput.ymax = (input->ymax - m_offsetY) * this->m_relY;
+ newInput.ymax = (input->ymax - m_offsetY) * this->m_relY + 1;
newInput.ymin = (input->ymin - m_offsetY) * this->m_relY;
return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
index 1ec52571be8..9ff0bf9ce12 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
@@ -286,9 +286,9 @@ void InverseSearchRadiusOperation::initExecution()
this->m_inputRadius = this->getInputSocketReader(0);
}
-voi *InverseSearchRadiusOperation::initializeTileData(rcti *rect)
+void *InverseSearchRadiusOperation::initializeTileData(rcti *rect)
{
- MemoryBuffer * data = new MemoryBuffer(NULL, rect);
+ MemoryBuffer * data = new MemoryBuffer(COM_DT_COLOR, rect);
float *buffer = data->getBuffer();
int x, y;
int width = this->m_inputRadius->getWidth();
@@ -343,7 +343,7 @@ voi *InverseSearchRadiusOperation::initializeTileData(rcti *rect)
void InverseSearchRadiusOperation::executePixelChunk(float output[4], int x, int y, void *data)
{
MemoryBuffer *buffer = (MemoryBuffer *)data;
- buffer->readNoCheck(color, x, y);
+ buffer->readNoCheck(output, x, y);
}
void InverseSearchRadiusOperation::deinitializeTileData(rcti *rect, void *data)
diff --git a/source/blender/datatoc/datatoc.c b/source/blender/datatoc/datatoc.c
index 4e49a9a7694..ffccca98f99 100644
--- a/source/blender/datatoc/datatoc.c
+++ b/source/blender/datatoc/datatoc.c
@@ -91,6 +91,11 @@ int main(int argc, char **argv)
}
fprintf(fpout, "/* DataToC output of file <%s> */\n\n", argv[1]);
+
+ /* Quiet 'missing-variable-declarations' warning. */
+ fprintf(fpout, "extern int datatoc_%s_size;\n", argv[1]);
+ fprintf(fpout, "extern char datatoc_%s[];\n\n", argv[1]);
+
fprintf(fpout, "int datatoc_%s_size = %d;\n", argv[1], (int)size);
fprintf(fpout, "char datatoc_%s[] = {\n", argv[1]);
while (size--) {
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index b664af570b1..33a7628c68d 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -87,6 +87,7 @@ set(SRC
intern/depsgraph_intern.h
intern/depsgraph_types.h
+ util/deg_util_foreach.h
util/deg_util_function.h
)
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index fdc86540171..b65d921cfd1 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -153,7 +153,8 @@ void DEG_add_object_cache_relation(struct DepsNodeHandle *handle,
eDepsObjectComponentType component,
const char *description);
-/* TODO(sergey): Remove once all geometry update is granular. */
+
+struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *handle);
void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag);
/* Utility functions for physics modifiers */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index 143f9908db8..e3494e4756e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -36,10 +36,7 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-
-extern "C" {
#include "BLI_stack.h"
-}
#include "intern/depsgraph.h"
#include "intern/depsgraph_types.h"
@@ -72,14 +69,14 @@ static bool check_object_needs_evaluation(Object *object)
void deg_graph_build_flush_layers(Depsgraph *graph)
{
- BLI_Stack *stack = BLI_stack_new(sizeof(OperationDepsNode*),
+ BLI_Stack *stack = BLI_stack_new(sizeof(OperationDepsNode *),
"DEG flush layers stack");
foreach (OperationDepsNode *node, graph->operations) {
IDDepsNode *id_node = node->owner->owner;
node->done = 0;
node->num_links_pending = 0;
foreach (DepsRelation *rel, node->outlinks) {
- if ((rel->from->type == DEPSNODE_TYPE_OPERATION) &&
+ if ((rel->from->type == DEG_NODE_TYPE_OPERATION) &&
(rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
{
++node->num_links_pending;
@@ -97,14 +94,14 @@ void deg_graph_build_flush_layers(Depsgraph *graph)
BLI_stack_pop(stack, &node);
/* Flush layers to parents. */
foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
OperationDepsNode *from = (OperationDepsNode *)rel->from;
from->owner->layers |= node->owner->layers;
}
}
/* Schedule parent nodes. */
foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
OperationDepsNode *from = (OperationDepsNode *)rel->from;
if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
BLI_assert(from->num_links_pending > 0);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index 1420b5fc8a5..3eed0697b5e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -33,10 +33,8 @@
#include <cstdio>
#include <cstdlib>
-extern "C" {
#include "BLI_utildefines.h"
#include "BLI_stack.h"
-}
#include "util/deg_util_foreach.h"
@@ -71,7 +69,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
foreach (OperationDepsNode *node, graph->operations) {
bool has_inlinks = false;
foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
has_inlinks = true;
}
}
@@ -95,7 +93,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
bool all_child_traversed = true;
for (int i = node->done; i < node->outlinks.size(); ++i) {
DepsRelation *rel = node->outlinks[i];
- if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
+ if (rel->to->type == DEG_NODE_TYPE_OPERATION) {
OperationDepsNode *to = (OperationDepsNode *)rel->to;
if (to->tag == NODE_IN_STACK) {
printf("Dependency cycle detected:\n");
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index fa47b4dfb19..d70d8116178 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -37,11 +37,11 @@
#include "MEM_guardedalloc.h"
-extern "C" {
#include "BLI_blenlib.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+extern "C" {
#include "DNA_action_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -94,13 +94,13 @@ extern "C" {
#include "BKE_tracking.h"
#include "BKE_world.h"
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-
#include "RNA_access.h"
#include "RNA_types.h"
} /* extern "C" */
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "intern/builder/deg_builder.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
@@ -160,55 +160,14 @@ DepsgraphNodeBuilder::~DepsgraphNodeBuilder()
{
}
-RootDepsNode *DepsgraphNodeBuilder::add_root_node()
-{
- return m_graph->add_root_node();
-}
-
IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
{
return m_graph->add_id_node(id, id->name);
}
-TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id)
+TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source()
{
- /* determine which node to attach timesource to */
- if (id) {
-#if 0 /* XXX TODO */
- /* get ID node */
- IDDepsNode id_node = m_graph->find_id_node(id);
-
- /* depends on what this is... */
- switch (GS(id->name)) {
- case ID_SCE: /* Scene - Usually sequencer strip causing time remapping... */
- {
- // TODO...
- }
- break;
-
- case ID_GR: /* Group */
- {
- // TODO...
- }
- break;
-
- // XXX: time source...
-
- default: /* Unhandled */
- printf("%s(): Unhandled ID - %s \n", __func__, id->name);
- break;
- }
-#endif
- }
- else {
- /* root-node */
- RootDepsNode *root_node = m_graph->root_node;
- if (root_node) {
- return root_node->add_time_source("Time Source");
- }
- }
-
- return NULL;
+ return m_graph->add_time_source();
}
ComponentDepsNode *DepsgraphNodeBuilder::add_component_node(
@@ -224,8 +183,7 @@ ComponentDepsNode *DepsgraphNodeBuilder::add_component_node(
OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
ComponentDepsNode *comp_node,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
@@ -234,7 +192,7 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
name,
name_tag);
if (op_node == NULL) {
- op_node = comp_node->add_operation(optype, op, opcode, name, name_tag);
+ op_node = comp_node->add_operation(op, opcode, name, name_tag);
m_graph->operations.push_back(op_node);
}
else {
@@ -252,21 +210,19 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
ID *id,
eDepsNode_Type comp_type,
const char *comp_name,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
{
ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name);
- return add_operation_node(comp_node, optype, op, opcode, name, name_tag);
+ return add_operation_node(comp_node, op, opcode, name, name_tag);
}
OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
ID *id,
eDepsNode_Type comp_type,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
@@ -274,7 +230,6 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
return add_operation_node(id,
comp_type,
"",
- optype,
op,
opcode,
name,
@@ -352,41 +307,6 @@ void DepsgraphNodeBuilder::build_group(Scene *scene,
}
}
-SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
-{
- /* sanity checks */
- if (!group)
- return NULL;
-
- /* create new subgraph's data */
- Depsgraph *subgraph = reinterpret_cast<Depsgraph *>(DEG_graph_new());
-
- DepsgraphNodeBuilder subgraph_builder(m_bmain, subgraph);
-
- /* add group objects */
- LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
- /*Object *ob = go->ob;*/
-
- /* Each "group object" is effectively a separate instance of the
- * underlying object data. When the group is evaluated, the transform
- * results and/or some other attributes end up getting overridden by
- * the group.
- */
- }
-
- /* Create a node for representing subgraph. */
- SubgraphDepsNode *subgraph_node = m_graph->add_subgraph_node(&group->id);
- subgraph_node->graph = subgraph;
-
- /* Make a copy of the data this node will need? */
- /* XXX: do we do this now, or later? */
- /* TODO: need API function which queries graph's ID's hash, and duplicates
- * those blocks thoroughly with all outside links removed.
- */
-
- return subgraph_node;
-}
-
void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
{
const bool has_object = (ob->id.tag & LIB_TAG_DOIT);
@@ -400,8 +320,11 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
if (base != NULL) {
id_node->layers |= base->lay;
}
- if (ob == scene->camera) {
- /* Camera should always be updated, it used directly by viewport. */
+ if (ob->type == OB_CAMERA) {
+ /* Camera should always be updated, it used directly by viewport.
+ *
+ * TODO(sergey): Make it only for active scene camera.
+ */
id_node->layers |= (unsigned int)(-1);
}
/* Skip rest of components if the ID node was already there. */
@@ -427,7 +350,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
BuilderWalkUserData data;
data.builder = this;
data.scene = scene;
- modifiers_foreachObjectLink(ob, modifier_walk, &data);
BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
}
@@ -513,15 +435,18 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
{
+ OperationDepsNode *op_node;
+
/* local transforms (from transform channels - loc/rot/scale + deltas) */
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_INIT, function_bind(BKE_object_eval_local_transform, _1, scene, ob),
- DEG_OPCODE_TRANSFORM_LOCAL);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_local_transform, _1, scene, ob),
+ DEG_OPCODE_TRANSFORM_LOCAL);
+ op_node->set_as_entry();
/* object parent */
if (ob->parent) {
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_parent, _1, scene, ob),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_parent, _1, scene, ob),
DEG_OPCODE_TRANSFORM_PARENT);
}
@@ -537,14 +462,15 @@ void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
*
* TODO(sergey): Get rid of this node.
*/
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_uber_transform, _1, scene, ob),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_uber_transform, _1, scene, ob),
DEG_OPCODE_OBJECT_UBEREVAL);
/* object transform is done */
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_POST, function_bind(BKE_object_eval_done, _1, ob),
- DEG_OPCODE_TRANSFORM_FINAL);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_done, _1, ob),
+ DEG_OPCODE_TRANSFORM_FINAL);
+ op_node->set_as_exit();
}
/**
@@ -567,8 +493,8 @@ void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
void DepsgraphNodeBuilder::build_object_constraints(Scene *scene, Object *ob)
{
/* create node for constraint stack */
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_constraints, _1, scene, ob),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_constraints, _1, scene, ob),
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
}
@@ -590,8 +516,8 @@ void DepsgraphNodeBuilder::build_animdata(ID *id)
/* actions and NLA - as a single unit for now, as it gets complicated to schedule otherwise */
if ((adt->action) || (adt->nla_tracks.first)) {
/* create the node */
- add_operation_node(id, DEPSNODE_TYPE_ANIMATION,
- DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_animdata, _1, id),
+ add_operation_node(id, DEG_NODE_TYPE_ANIMATION,
+ function_bind(BKE_animsys_eval_animdata, _1, id),
DEG_OPCODE_ANIMATION, id->name);
// TODO: for each channel affected, we might also want to add some support for running RNA update callbacks on them
@@ -621,15 +547,14 @@ OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
* and use some tagging magic instead.
*/
OperationDepsNode *driver_op = find_operation_node(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
if (driver_op == NULL) {
driver_op = add_operation_node(id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC,
+ DEG_NODE_TYPE_PARAMETERS,
function_bind(BKE_animsys_eval_driver, _1, id, fcu),
DEG_OPCODE_DRIVER,
fcu->rna_path ? fcu->rna_path : "",
@@ -656,9 +581,9 @@ void DepsgraphNodeBuilder::build_world(World *world)
build_animdata(world_id);
/* world itself */
- add_component_node(world_id, DEPSNODE_TYPE_PARAMETERS);
+ add_component_node(world_id, DEG_NODE_TYPE_PARAMETERS);
- add_operation_node(world_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(world_id, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
/* textures */
@@ -694,14 +619,14 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
/* XXX: is this the right component, or do we want to use another one instead? */
/* init/rebuild operation */
- /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_REBUILD, function_bind(BKE_rigidbody_rebuild_sim, _1, scene),
+ /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_rebuild_sim, _1, scene),
DEG_OPCODE_RIGIDBODY_REBUILD);
/* do-sim operation */
// XXX: what happens if we need to split into several groups?
- OperationDepsNode *sim_node = add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_SIM, function_bind(BKE_rigidbody_eval_simulation, _1, scene),
+ OperationDepsNode *sim_node = add_operation_node(&scene->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_eval_simulation, _1, scene),
DEG_OPCODE_RIGIDBODY_SIM);
/* XXX: For now, the sim node is the only one that really matters here. If any other
@@ -721,8 +646,8 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
/* 2) create operation for flushing results */
/* object's transform component - where the rigidbody operation lives */
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_EXEC, function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob),
DEG_OPCODE_TRANSFORM_RIGIDBODY);
}
}
@@ -747,7 +672,14 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
/* component for all particle systems */
ComponentDepsNode *psys_comp =
- add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
+ add_component_node(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
+
+ add_operation_node(psys_comp,
+ function_bind(BKE_particle_system_eval_init,
+ _1,
+ scene,
+ ob),
+ DEG_OPCODE_PSYS_EVAL_INIT);
/* particle systems */
LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
@@ -760,12 +692,7 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
/* this particle system */
// TODO: for now, this will just be a placeholder "ubereval" node
add_operation_node(psys_comp,
- DEPSOP_TYPE_EXEC,
- function_bind(BKE_particle_system_eval,
- _1,
- scene,
- ob,
- psys),
+ NULL,
DEG_OPCODE_PSYS_EVAL,
psys->name);
}
@@ -777,9 +704,8 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
void DepsgraphNodeBuilder::build_cloth(Scene *scene, Object *object)
{
ComponentDepsNode *cache_comp = add_component_node(&object->id,
- DEPSNODE_TYPE_CACHE);
+ DEG_NODE_TYPE_CACHE);
add_operation_node(cache_comp,
- DEPSOP_TYPE_EXEC,
function_bind(BKE_object_eval_cloth,
_1,
scene,
@@ -793,7 +719,7 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key)
{
build_animdata(&key->id);
- add_operation_node(&key->id, DEPSNODE_TYPE_GEOMETRY, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(&key->id, DEG_NODE_TYPE_GEOMETRY, NULL,
DEG_OPCODE_PLACEHOLDER, "Shapekey Eval");
}
@@ -802,18 +728,19 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key)
void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
{
ID *obdata = (ID *)ob->data;
+ OperationDepsNode *op_node;
/* TODO(sergey): This way using this object's properties as driver target
* works fine.
*
* Does this depend on other nodes?
*/
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_POST,
- NULL,
- DEG_OPCODE_PLACEHOLDER,
- "Parameters Eval");
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PLACEHOLDER,
+ "Parameters Eval");
+ op_node->set_as_exit();
/* Temporary uber-update node, which does everything.
* It is for the being we're porting old dependencies into the new system.
@@ -822,33 +749,23 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
*
* TODO(sergey): Get rid of this node.
*/
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_POST,
- function_bind(BKE_object_eval_uber_data, _1, scene, ob),
- DEG_OPCODE_GEOMETRY_UBEREVAL);
-
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- NULL,
- DEG_OPCODE_PLACEHOLDER,
- "Eval Init");
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_object_eval_uber_data, _1, scene, ob),
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+ op_node->set_as_exit();
+
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ NULL,
+ DEG_OPCODE_PLACEHOLDER,
+ "Eval Init");
+ op_node->set_as_entry();
// TODO: "Done" operation
- /* Modifiers */
+ /* Cloyth modifier. */
LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_EXEC,
- function_bind(BKE_object_eval_modifier,
- _1,
- scene,
- ob,
- md),
- DEG_OPCODE_GEOMETRY_MODIFIER,
- md->name);
if (md->type == eModifierType_Cloth) {
build_cloth(scene, ob);
}
@@ -888,14 +805,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
//Mesh *me = (Mesh *)ob->data;
/* evaluation operations */
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_mesh_eval_geometry,
- _1,
- (Mesh *)obdata),
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_mesh_eval_geometry,
+ _1,
+ (Mesh *)obdata),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
break;
}
@@ -907,14 +824,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
if (mom == ob) {
/* metaball evaluation operations */
/* NOTE: only the motherball gets evaluated! */
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_mball_eval_geometry,
- _1,
- (MetaBall *)obdata),
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_mball_eval_geometry,
+ _1,
+ (MetaBall *)obdata),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
}
break;
}
@@ -925,26 +842,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
{
/* Curve/nurms evaluation operations. */
/* - calculate curve geometry (including path) */
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_curve_eval_geometry,
- _1,
- (Curve *)obdata),
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
-
- /* Calculate curve path - this is used by constraints, etc. */
- if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_EXEC,
- function_bind(BKE_curve_eval_path,
- _1,
- (Curve *)obdata),
- DEG_OPCODE_GEOMETRY_PATH,
- "Path");
- }
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_curve_eval_geometry,
+ _1,
+ (Curve *)obdata),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
/* Make sure objects used for bevel.taper are in the graph.
* NOTE: This objects might be not linked to the scene.
@@ -965,24 +870,24 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
case OB_LATTICE:
{
/* Lattice evaluation operations. */
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_lattice_eval_geometry,
- _1,
- (Lattice *)obdata),
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_lattice_eval_geometry,
+ _1,
+ (Lattice *)obdata),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
break;
}
}
- add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_POST, NULL,
- DEG_OPCODE_PLACEHOLDER, "Eval Done");
+ op_node = add_operation_node(obdata, DEG_NODE_TYPE_GEOMETRY, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Eval Done");
+ op_node->set_as_exit();
/* Parameters for driver sources. */
- add_operation_node(obdata, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(obdata, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
}
@@ -998,15 +903,13 @@ void DepsgraphNodeBuilder::build_camera(Object *ob)
build_animdata(&cam->id);
- add_operation_node(camera_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(camera_id, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
if (cam->dof_ob != NULL) {
/* TODO(sergey): For now parametrs are on object level. */
- add_operation_node(&ob->id, DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC, NULL,
- DEG_OPCODE_PLACEHOLDER,
- "Camera DOF");
+ add_operation_node(&ob->id, DEG_NODE_TYPE_PARAMETERS, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Camera DOF");
}
}
@@ -1022,10 +925,10 @@ void DepsgraphNodeBuilder::build_lamp(Object *ob)
build_animdata(&la->id);
/* node for obdata */
- add_component_node(lamp_id, DEPSNODE_TYPE_PARAMETERS);
+ add_component_node(lamp_id, DEG_NODE_TYPE_PARAMETERS);
/* TODO(sergey): Is it really how we're supposed to work with drivers? */
- add_operation_node(lamp_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(lamp_id, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
/* lamp's nodetree */
@@ -1044,18 +947,20 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
/* nodetree itself */
ID *ntree_id = &ntree->id;
+ OperationDepsNode *op_node;
build_animdata(ntree_id);
/* Parameters for drivers. */
- add_operation_node(ntree_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_POST, NULL,
- DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+ op_node = add_operation_node(ntree_id, DEG_NODE_TYPE_PARAMETERS, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+ op_node->set_as_exit();
/* nodetree's nodes... */
LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
ID *id = bnode->id;
if (id != NULL) {
- short id_type = GS(id->name);
+ ID_Type id_type = GS(id->name);
if (id_type == ID_MA) {
build_material((Material *)id);
}
@@ -1088,8 +993,7 @@ void DepsgraphNodeBuilder::build_material(Material *ma)
/* material itself */
add_id_node(ma_id);
- add_operation_node(ma_id, DEPSNODE_TYPE_SHADING,
- DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(ma_id, DEG_NODE_TYPE_SHADING, NULL,
DEG_OPCODE_PLACEHOLDER, "Material Update");
/* material animation */
@@ -1145,8 +1049,7 @@ void DepsgraphNodeBuilder::build_image(Image *image) {
add_id_node(image_id);
/* Placeholder so we can add relations and tag ID node for update. */
add_operation_node(image_id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC,
+ DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,
"Image Eval");
@@ -1157,10 +1060,10 @@ void DepsgraphNodeBuilder::build_compositor(Scene *scene)
/* For now, just a plain wrapper? */
// TODO: create compositing component?
// XXX: component type undefined!
- //graph->get_node(&scene->id, NULL, DEPSNODE_TYPE_COMPOSITING, NULL);
+ //graph->get_node(&scene->id, NULL, DEG_NODE_TYPE_COMPOSITING, NULL);
/* for now, nodetrees are just parameters; compositing occurs in internals of renderer... */
- add_component_node(&scene->id, DEPSNODE_TYPE_PARAMETERS);
+ add_component_node(&scene->id, DEG_NODE_TYPE_PARAMETERS);
build_nodetree(scene->nodetree);
}
@@ -1182,9 +1085,8 @@ 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,
+ add_component_node(cache_file_id, DEG_NODE_TYPE_CACHE);
+ add_operation_node(cache_file_id, DEG_NODE_TYPE_CACHE, NULL,
DEG_OPCODE_PLACEHOLDER, "Cache File Update");
add_id_node(cache_file_id);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 745f8283328..a54b1c76c77 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -61,8 +61,6 @@ namespace DEG {
struct Depsgraph;
struct DepsNode;
-struct RootDepsNode;
-struct SubgraphDepsNode;
struct IDDepsNode;
struct TimeSourceDepsNode;
struct ComponentDepsNode;
@@ -74,32 +72,28 @@ struct DepsgraphNodeBuilder {
void begin_build(Main *bmain);
- RootDepsNode *add_root_node();
IDDepsNode *add_id_node(ID *id);
- TimeSourceDepsNode *add_time_source(ID *id);
+ TimeSourceDepsNode *add_time_source();
ComponentDepsNode *add_component_node(ID *id,
eDepsNode_Type comp_type,
const char *comp_name = "");
OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name = "",
int name_tag = -1);
OperationDepsNode *add_operation_node(ID *id,
eDepsNode_Type comp_type,
const char *comp_name,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name = "",
int name_tag = -1);
OperationDepsNode *add_operation_node(ID *id,
eDepsNode_Type comp_type,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name = "",
int name_tag = -1);
@@ -125,7 +119,6 @@ struct DepsgraphNodeBuilder {
int name_tag = -1);
void build_scene(Main *bmain, Scene *scene);
- SubgraphDepsNode *build_subgraph(Group *group);
void build_group(Scene *scene, Base *base, Group *group);
void build_object(Scene *scene, Base *base, Object *ob);
void build_object_transform(Scene *scene, Object *ob);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index e307909cb11..fe7ccaa7fc0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -37,11 +37,11 @@
#include "MEM_guardedalloc.h"
-extern "C" {
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
+extern "C" {
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
@@ -49,10 +49,10 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/nodes/deg_node.h"
@@ -67,8 +67,7 @@ namespace DEG {
void DepsgraphNodeBuilder::build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan)
{
/* create node for constraint stack */
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_EXEC,
+ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
function_bind(BKE_pose_constraints_evaluate, _1, scene, ob, pchan),
DEG_OPCODE_BONE_CONSTRAINTS);
}
@@ -81,15 +80,15 @@ void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel
/* Find the chain's root. */
bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
- if (has_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
+ if (has_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
DEG_OPCODE_POSE_IK_SOLVER))
{
return;
}
/* Operation node for evaluating/running IK Solver. */
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
- DEPSOP_TYPE_SIM, function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
+ function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan),
DEG_OPCODE_POSE_IK_SOLVER);
}
@@ -104,8 +103,8 @@ void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseCh
/* Operation node for evaluating/running Spline IK Solver.
* Store the "root bone" of this chain in the solver, so it knows where to start.
*/
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
- DEPSOP_TYPE_SIM, function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
+ function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan),
DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
}
@@ -113,6 +112,7 @@ void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseCh
void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
{
bArmature *arm = (bArmature *)ob->data;
+ OperationDepsNode *op_node;
/* animation and/or drivers linking posebones to base-armature used to define them
* NOTE: AnimData here is really used to control animated deform properties,
@@ -125,8 +125,7 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
/* Make sure pose is up-to-date with armature updates. */
add_operation_node(&arm->id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC,
+ DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,
"Armature Eval");
@@ -175,30 +174,37 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
*/
/* pose eval context */
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_INIT, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT);
-
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_POST, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE);
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose),
+ DEG_OPCODE_POSE_INIT);
+ op_node->set_as_entry();
+
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose),
+ DEG_OPCODE_POSE_DONE);
+ op_node->set_as_exit();
/* bones */
LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
/* node for bone eval */
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_INIT, NULL, // XXX: BKE_pose_eval_bone_local
- DEG_OPCODE_BONE_LOCAL);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL,
+ DEG_OPCODE_BONE_LOCAL);
+ op_node->set_as_entry();
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_EXEC, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), // XXX: BKE_pose_eval_bone_pose
+ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan),
DEG_OPCODE_BONE_POSE_PARENT);
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_OUT, NULL, /* NOTE: dedicated noop for easier relationship construction */
+ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ NULL, /* NOTE: dedicated noop for easier relationship construction */
DEG_OPCODE_BONE_READY);
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_POST, function_bind(BKE_pose_bone_done, _1, pchan),
- DEG_OPCODE_BONE_DONE);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ function_bind(BKE_pose_bone_done, _1, pchan),
+ DEG_OPCODE_BONE_DONE);
+ op_node->set_as_exit();
/* constraints */
if (pchan->constraints.first != NULL) {
@@ -236,6 +242,8 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
void DepsgraphNodeBuilder::build_proxy_rig(Object *ob)
{
ID *obdata = (ID *)ob->data;
+ OperationDepsNode *op_node;
+
build_animdata(obdata);
BLI_assert(ob->pose != NULL);
@@ -246,31 +254,28 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *ob)
BKE_pose_update_constraint_flags(ob->pose);
}
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_pose_eval_proxy_copy, _1, ob),
- DEG_OPCODE_POSE_INIT);
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ function_bind(BKE_pose_eval_proxy_copy, _1, ob),
+ DEG_OPCODE_POSE_INIT);
+ op_node->set_as_entry();
LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_INIT, NULL,
- DEG_OPCODE_BONE_LOCAL);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ NULL, DEG_OPCODE_BONE_LOCAL);
+ op_node->set_as_entry();
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_EXEC, NULL,
- DEG_OPCODE_BONE_READY);
+ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ NULL, DEG_OPCODE_BONE_READY);
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_POST, NULL,
- DEG_OPCODE_BONE_DONE);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ NULL, DEG_OPCODE_BONE_DONE);
+ op_node->set_as_exit();
}
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_POST,
- NULL,
- DEG_OPCODE_POSE_DONE);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE,
+ NULL, DEG_OPCODE_POSE_DONE);
+ op_node->set_as_exit();
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
index 7dd694cb570..3249867e416 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
@@ -37,21 +37,21 @@
#include "MEM_guardedalloc.h"
-extern "C" {
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
+extern "C" {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_main.h"
#include "BKE_node.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/nodes/deg_node.h"
@@ -69,7 +69,7 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
add_id_node(&scene->id);
/* timesource */
- add_time_source(NULL);
+ add_time_source();
/* build subgraph for set, and link this in... */
// XXX: depending on how this goes, that scene itself could probably store its
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
index f870a33fb68..59eb7ed8cf1 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
@@ -33,10 +33,8 @@
#include <stdio.h>
#include <string.h>
-extern "C" {
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-}
namespace DEG {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index ce238de4be9..ce5ecf79948 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -38,10 +38,10 @@
#include "MEM_guardedalloc.h"
-extern "C" {
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+extern "C" {
#include "DNA_action_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -92,13 +92,13 @@ extern "C" {
#include "BKE_tracking.h"
#include "BKE_world.h"
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-
#include "RNA_access.h"
#include "RNA_types.h"
} /* extern "C" */
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "intern/builder/deg_builder.h"
#include "intern/builder/deg_builder_pchanmap.h"
@@ -113,6 +113,41 @@ extern "C" {
namespace DEG {
+namespace {
+
+struct BuilderWalkUserData {
+ DepsgraphRelationBuilder *builder;
+ Main *bmain;
+ Scene *scene;
+};
+
+static void modifier_walk(void *user_data,
+ struct Object * /*ob*/,
+ struct Object **obpoin,
+ int /*cb_flag*/)
+{
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ if (*obpoin) {
+ data->builder->build_object(data->bmain, data->scene, *obpoin);
+ }
+}
+
+void constraint_walk(bConstraint * /*con*/,
+ ID **idpoin,
+ bool /*is_reference*/,
+ void *user_data)
+{
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ if (*idpoin) {
+ ID *id = *idpoin;
+ if (GS(id->name) == ID_OB) {
+ data->builder->build_object(data->bmain, data->scene, (Object *)id);
+ }
+ }
+}
+
+} /* namespace */
+
/* ***************** */
/* Relations Builder */
@@ -163,13 +198,6 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Depsgraph *graph) :
{
}
-RootDepsNode *DepsgraphRelationBuilder::find_node(const RootKey &key) const
-{
- (void)key;
- BLI_assert(!"Doesn't seem to be correct");
- return m_graph->root_node;
-}
-
TimeSourceDepsNode *DepsgraphRelationBuilder::find_node(
const TimeSourceKey &key) const
{
@@ -178,7 +206,7 @@ TimeSourceDepsNode *DepsgraphRelationBuilder::find_node(
return NULL;
}
else {
- return m_graph->root_node->time_source;
+ return m_graph->time_source;
}
}
@@ -247,7 +275,7 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
const char *description)
{
if (timesrc && node_to) {
- m_graph->add_new_relation(timesrc, node_to, DEPSREL_TYPE_TIME, description);
+ m_graph->add_new_relation(timesrc, node_to, description);
}
else {
DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n",
@@ -260,17 +288,16 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
void DepsgraphRelationBuilder::add_operation_relation(
OperationDepsNode *node_from,
OperationDepsNode *node_to,
- eDepsRelation_Type type,
const char *description)
{
if (node_from && node_to) {
- m_graph->add_new_relation(node_from, node_to, type, description);
+ m_graph->add_new_relation(node_from, node_to, description);
}
else {
- DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %d, %s) Failed\n",
+ DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
node_from, (node_from) ? node_from->identifier().c_str() : "<None>",
node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
- type, description);
+ description);
}
}
@@ -283,11 +310,11 @@ void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key,
{
Object *ob1 = collobjs[i];
- ComponentKey trf_key(&ob1->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, name);
+ ComponentKey trf_key(&ob1->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(trf_key, key, name);
- ComponentKey coll_key(&ob1->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(coll_key, key, DEPSREL_TYPE_STANDARD, name);
+ ComponentKey coll_key(&ob1->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(coll_key, key, name);
}
if (collobjs)
@@ -301,31 +328,31 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key,
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);
+ ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(eff_key, key, 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);
+ ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
+ add_relation(eff_key, key, 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);
+ ComponentKey mod_key(&eff->ob->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(mod_key, key, 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);
+ OperationKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, eff->psys->name);
+ add_relation(eff_key, key, 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 trf_key(&eff->pd->f_source->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(trf_key, key, "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");
+ ComponentKey eff_key(&eff->pd->f_source->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(eff_key, key, "Smoke Force Domain");
}
if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
@@ -337,6 +364,11 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key,
pdEndEffectors(&effectors);
}
+Depsgraph *DepsgraphRelationBuilder::getGraph()
+{
+ return m_graph;
+}
+
/* **** Functions to build relations between entities **** */
void DepsgraphRelationBuilder::begin_build(Main *bmain)
@@ -363,17 +395,14 @@ void DepsgraphRelationBuilder::build_group(Main *bmain,
ID *group_id = &group->id;
bool group_done = (group_id->tag & LIB_TAG_DOIT) != 0;
OperationKey object_local_transform_key(&object->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_LOCAL);
LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
if (!group_done) {
build_object(bmain, scene, go->ob);
}
- ComponentKey dupli_transform_key(&go->ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dupli_transform_key,
- object_local_transform_key,
- DEPSREL_TYPE_TRANSFORM,
- "Dupligroup");
+ ComponentKey dupli_transform_key(&go->ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
}
group_id->tag |= LIB_TAG_DOIT;
}
@@ -387,13 +416,13 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
/* Object Transforms */
eDepsOperation_Code base_op = (ob->parent) ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
- OperationKey base_op_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, base_op);
+ OperationKey base_op_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, base_op);
- OperationKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
- OperationKey parent_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
- OperationKey final_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ OperationKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
+ OperationKey parent_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
+ OperationKey final_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
- OperationKey ob_ubereval_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL);
+ OperationKey ob_ubereval_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL);
/* parenting */
if (ob->parent != NULL) {
@@ -401,16 +430,28 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
build_object_parent(ob);
/* local -> parent */
- add_relation(local_transform_key,
- parent_transform_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "[ObLocal -> ObParent]");
+ add_relation(local_transform_key, parent_transform_key, "[ObLocal -> ObParent]");
+ }
+
+ if (ob->modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.bmain = bmain;
+ data.scene = scene;
+ modifiers_foreachObjectLink(ob, modifier_walk, &data);
+ }
+ if (ob->constraints.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.bmain = bmain;
+ data.scene = scene;
+ BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
}
/* object constraints */
if (ob->constraints.first != NULL) {
OperationKey constraint_key(&ob->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
/* constraint relations */
@@ -418,30 +459,18 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
// XXX: this is broken
build_constraints(scene,
&ob->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
"",
&ob->constraints,
NULL);
/* operation order */
- add_relation(base_op_key,
- constraint_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "[ObBase-> Constraint Stack]");
- add_relation(constraint_key,
- final_transform_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "[ObConstraints -> Done]");
+ add_relation(base_op_key, constraint_key, "[ObBase-> Constraint Stack]");
+ add_relation(constraint_key, final_transform_key, "[ObConstraints -> Done]");
// XXX
- add_relation(constraint_key,
- ob_ubereval_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "Temp Ubereval");
- add_relation(ob_ubereval_key,
- final_transform_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "Temp Ubereval");
+ add_relation(constraint_key, ob_ubereval_key, "Temp Ubereval");
+ add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval");
}
else {
/* NOTE: Keep an eye here, we skip some relations here to "streamline"
@@ -452,31 +481,20 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
/* Rigid body will hook up another node inbetween, so skip
* relation here to avoid transitive relation.
*/
- add_relation(base_op_key,
- ob_ubereval_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "Temp Ubereval");
+ add_relation(base_op_key, ob_ubereval_key, "Temp Ubereval");
}
- add_relation(ob_ubereval_key,
- final_transform_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "Temp Ubereval");
+ add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval");
}
-
/* AnimData */
build_animdata(&ob->id);
// XXX: This should be hooked up by the build_animdata code
if (needs_animdata_node(&ob->id)) {
- ComponentKey adt_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(adt_key,
- local_transform_key,
- DEPSREL_TYPE_OPERATION,
- "Object Animation");
+ ComponentKey adt_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(adt_key, local_transform_key, "Object Animation");
}
-
/* object data */
if (ob->data) {
ID *obdata_id = (ID *)ob->data;
@@ -517,12 +535,9 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
Key *key = BKE_key_from_object(ob);
if (key != NULL) {
- ComponentKey geometry_key((ID *)ob->data, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(key_key,
- geometry_key,
- DEPSREL_TYPE_GEOMETRY_EVAL,
- "Shapekeys");
+ ComponentKey geometry_key((ID *)ob->data, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(key_key, geometry_key, "Shapekeys");
}
}
@@ -543,9 +558,9 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
/* TODO(sergey): This is an inverted relation, matches old depsgraph
* behavior and need to be investigated if it still need to be inverted.
*/
- ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE);
- add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy");
+ ComponentKey ob_pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey proxy_pose_key(&ob->proxy->id, DEG_NODE_TYPE_EVAL_POSE);
+ add_relation(ob_pose_key, proxy_pose_key, "Proxy");
}
/* Object dupligroup. */
@@ -561,23 +576,23 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
*/
// XXX: @sergey - it would be good if we got that backwards flushing working
// when tagging for updates.
- //OperationKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
- ComponentKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
+ //OperationKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
+ ComponentKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
/* type-specific links */
switch (ob->partype) {
case PARSKEL: /* Armature Deform (Virtual Modifier) */
{
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Armature Deform Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, "Armature Deform Parent");
break;
}
case PARVERT1: /* Vertex Parent */
case PARVERT3:
{
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Vertex Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(parent_key, ob_key, "Vertex Parent");
/* XXX not sure what this is for or how you could be done properly - lukas */
OperationDepsNode *parent_node = find_operation_node(parent_key);
@@ -585,27 +600,21 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
parent_node->customdata_mask |= CD_MASK_ORIGINDEX;
}
- ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Vertex Parent TFM");
+ ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(transform_key, ob_key, "Vertex Parent TFM");
break;
}
case PARBONE: /* Bone Parent */
{
ComponentKey parent_bone_key(&ob->parent->id,
- DEPSNODE_TYPE_BONE,
+ DEG_NODE_TYPE_BONE,
ob->parsubstr);
OperationKey parent_transform_key(&ob->parent->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_FINAL);
- add_relation(parent_bone_key,
- ob_key,
- DEPSREL_TYPE_TRANSFORM,
- "Bone Parent");
- add_relation(parent_transform_key,
- ob_key,
- DEPSREL_TYPE_TRANSFORM,
- "Armature Parent");
+ add_relation(parent_bone_key, ob_key, "Bone Parent");
+ add_relation(parent_transform_key, ob_key, "Armature Parent");
break;
}
@@ -614,33 +623,33 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
if (ob->parent->type == OB_LATTICE) {
/* Lattice Deform Parent - Virtual Modifier */
// XXX: no virtual modifiers should be left!
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- ComponentKey geom_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey geom_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent");
- add_relation(geom_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent Geom");
+ add_relation(parent_key, ob_key, "Lattice Deform Parent");
+ add_relation(geom_key, ob_key, "Lattice Deform Parent Geom");
}
else if (ob->parent->type == OB_CURVE) {
Curve *cu = (Curve *)ob->parent->data;
if (cu->flag & CU_PATH) {
/* Follow Path */
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(parent_key, ob_key, "Curve Follow Parent");
- ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow TFM");
+ ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(transform_key, ob_key, "Curve Follow TFM");
}
else {
/* Standard Parent */
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, "Curve Parent");
}
}
else {
/* Standard Parent */
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, "Parent");
}
break;
}
@@ -652,112 +661,145 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
}
}
-void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode_Type component_type, const char *component_subdata,
- ListBase *constraints, RootPChanMap *root_map)
+void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id,
+ eDepsNode_Type component_type,
+ const char *component_subdata,
+ ListBase *constraints,
+ RootPChanMap *root_map)
{
- OperationKey constraint_op_key(id, component_type, component_subdata,
- (component_type == DEPSNODE_TYPE_BONE) ? DEG_OPCODE_BONE_CONSTRAINTS : DEG_OPCODE_TRANSFORM_CONSTRAINTS);
-
- /* add dependencies for each constraint in turn */
+ OperationKey constraint_op_key(
+ id,
+ component_type,
+ component_subdata,
+ (component_type == DEG_NODE_TYPE_BONE)
+ ? DEG_OPCODE_BONE_CONSTRAINTS
+ : DEG_OPCODE_TRANSFORM_CONSTRAINTS);
+ /* Add dependencies for each constraint in turn. */
for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
-
- /* invalid constraint type... */
- if (cti == NULL)
+ /* Invalid constraint type. */
+ if (cti == NULL) {
continue;
-
- /* special case for camera tracking -- it doesn't use targets to define relations */
- // TODO: we can now represent dependencies in a much richer manner, so review how this is done...
- if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ }
+ /* Special case for camera tracking -- it doesn't use targets to
+ * define relations.
+ */
+ /* TODO: we can now represent dependencies in a much richer manner,
+ * so review how this is done.
+ */
+ if (ELEM(cti->type,
+ CONSTRAINT_TYPE_FOLLOWTRACK,
+ CONSTRAINT_TYPE_CAMERASOLVER,
+ CONSTRAINT_TYPE_OBJECTSOLVER))
+ {
bool depends_on_camera = false;
-
if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
-
- if (((data->clip) || (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0])
+ if (((data->clip) ||
+ (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0])
+ {
depends_on_camera = true;
-
+ }
if (data->depth_ob) {
- // DAG_RL_DATA_OB | DAG_RL_OB_OB
- ComponentKey depth_key(&data->depth_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(depth_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey depth_key(&data->depth_ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(depth_key, constraint_op_key, cti->name);
}
}
else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
depends_on_camera = true;
}
-
if (depends_on_camera && scene->camera) {
- // DAG_RL_DATA_OB | DAG_RL_OB_OB
- ComponentKey camera_key(&scene->camera->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(camera_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey camera_key(&scene->camera->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(camera_key, constraint_op_key, cti->name);
}
-
- /* TODO(sergey): This is more a TimeSource -> MovieClip -> Constraint dependency chain. */
+ /* TODO(sergey): This is more a TimeSource -> MovieClip ->
+ * Constraint dependency chain.
+ */
TimeSourceKey time_src_key;
- add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
+ add_relation(time_src_key, constraint_op_key, "[TimeSrc -> Animation]");
}
else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint dependency chain. */
+ /* 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]");
-
+ add_relation(time_src_key, constraint_op_key, "[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);
+ ComponentKey cache_key(&data->cache_file->id, DEG_NODE_TYPE_CACHE);
+ add_relation(cache_key, constraint_op_key, cti->name);
}
}
else if (cti->get_constraint_targets) {
ListBase targets = {NULL, NULL};
cti->get_constraint_targets(con, &targets);
-
LINKLIST_FOREACH (bConstraintTarget *, ct, &targets) {
if (ct->tar == NULL) {
continue;
}
-
- if (ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) {
- /* ignore IK constraints - these are handled separately (on pose level) */
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_KINEMATIC,
+ CONSTRAINT_TYPE_SPLINEIK))
+ {
+ /* Ignore IK constraints - these are handled separately
+ * (on pose level).
+ */
}
- else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
- /* these constraints require path geometry data... */
- ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name); // XXX: type = geom_transform
- // TODO: path dependency
+ else if (ELEM(con->type,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_CLAMPTO))
+ {
+ /* These constraints require path geometry data. */
+ ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
+ ComponentKey target_transform_key(&ct->tar->id,
+ DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
}
else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
/* bone */
if (&ct->tar->id == id) {
/* same armature */
eDepsOperation_Code target_key_opcode;
-
- /* Using "done" here breaks in-chain deps, while using "ready" here breaks most production rigs instead...
- * So, we do a compromise here, and only do this when an IK chain conflict may occur
+ /* Using "done" here breaks in-chain deps, while using
+ * "ready" here breaks most production rigs instead.
+ * So, we do a compromise here, and only do this when an
+ * IK chain conflict may occur.
*/
- if (root_map->has_common_root(component_subdata, ct->subtarget)) {
+ if (root_map->has_common_root(component_subdata,
+ ct->subtarget))
+ {
target_key_opcode = DEG_OPCODE_BONE_READY;
}
else {
target_key_opcode = DEG_OPCODE_BONE_DONE;
}
-
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, target_key_opcode);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ OperationKey target_key(&ct->tar->id,
+ DEG_NODE_TYPE_BONE,
+ ct->subtarget,
+ target_key_opcode);
+ add_relation(target_key, constraint_op_key, cti->name);
}
else {
- /* different armature - we can safely use the result of that */
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, DEG_OPCODE_BONE_DONE);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ /* Different armature - we can safely use the result
+ * of that.
+ */
+ OperationKey target_key(&ct->tar->id,
+ DEG_NODE_TYPE_BONE,
+ ct->subtarget,
+ DEG_OPCODE_BONE_DONE);
+ add_relation(target_key, constraint_op_key, cti->name);
}
}
- else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
- /* vertex group */
- /* NOTE: for now, we don't need to represent vertex groups separately... */
- ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name);
-
+ else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) &&
+ (ct->subtarget[0]))
+ {
+ /* Vertex group. */
+ /* NOTE: for now, we don't need to represent vertex groups
+ * separately.
+ */
+ ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
if (ct->tar->type == OB_MESH) {
OperationDepsNode *node2 = find_operation_node(target_key);
if (node2 != NULL) {
@@ -767,39 +809,50 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
}
else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
/* Constraints which requires the target object surface. */
- ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
-
- /* NOTE: obdata eval now doesn't necessarily depend on the object's transform... */
- ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
+ /* NOTE: obdata eval now doesn't necessarily depend on the
+ * object's transform.
+ */
+ ComponentKey target_transform_key(&ct->tar->id,
+ DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
}
else {
- /* standard object relation */
+ /* Standard object relation. */
// TODO: loc vs rot vs scale?
if (&ct->tar->id == id) {
/* Constraint targetting own object:
- * - This case is fine IFF we're dealing with a bone constraint pointing to
- * its own armature. In that case, it's just transform -> bone.
- * - If however it is a real self targetting case, just make it depend on the
- * previous constraint (or the pre-constraint state)...
+ * - This case is fine IFF we're dealing with a bone
+ * constraint pointing to its own armature. In that
+ * case, it's just transform -> bone.
+ * - If however it is a real self targetting case, just
+ * make it depend on the previous constraint (or the
+ * pre-constraint state).
*/
- if ((ct->tar->type == OB_ARMATURE) && (component_type == DEPSNODE_TYPE_BONE)) {
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ if ((ct->tar->type == OB_ARMATURE) &&
+ (component_type == DEG_NODE_TYPE_BONE))
+ {
+ OperationKey target_key(&ct->tar->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, cti->name);
}
else {
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ OperationKey target_key(&ct->tar->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_LOCAL);
+ add_relation(target_key, constraint_op_key, cti->name);
}
}
else {
- /* normal object dependency */
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ /* Normal object dependency. */
+ OperationKey target_key(&ct->tar->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, cti->name);
}
}
-
/* Constraints which needs world's matrix for transform.
* TODO(sergey): More constraints here?
*/
@@ -810,14 +863,14 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
CONSTRAINT_TYPE_TRANSLIKE))
{
/* TODO(sergey): Add used space check. */
- ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey target_transform_key(&ct->tar->id,
+ DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
}
-
}
-
- if (cti->flush_constraint_targets)
+ if (cti->flush_constraint_targets) {
cti->flush_constraint_targets(con, &targets, 1);
+ }
}
}
}
@@ -829,13 +882,13 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
if (adt == NULL)
return;
- ComponentKey adt_key(id, DEPSNODE_TYPE_ANIMATION);
+ ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
/* animation */
if (adt->action || adt->nla_tracks.first) {
/* wire up dependency to time source */
TimeSourceKey time_src_key;
- add_relation(time_src_key, adt_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
+ add_relation(time_src_key, adt_key, "[TimeSrc -> Animation]");
// XXX: Hook up specific update callbacks for special properties which may need it...
@@ -845,7 +898,7 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
/* drivers */
LINKLIST_FOREACH (FCurve *, fcu, &adt->drivers) {
OperationKey driver_key(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
@@ -886,26 +939,22 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
}
if (fcu_prev != NULL) {
OperationKey prev_driver_key(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu_prev->rna_path ? fcu_prev->rna_path : "",
fcu_prev->array_index);
OperationKey driver_key(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
- add_relation(prev_driver_key,
- driver_key,
- DEPSREL_TYPE_OPERATION,
- "[Driver Order]");
+ add_relation(prev_driver_key, driver_key, "[Driver Order]");
}
}
/* prevent driver from occurring before own animation... */
if (adt->action || adt->nla_tracks.first) {
- add_relation(adt_key, driver_key, DEPSREL_TYPE_OPERATION,
- "[AnimData Before Drivers]");
+ add_relation(adt_key, driver_key, "[AnimData Before Drivers]");
}
}
}
@@ -914,7 +963,7 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
{
ChannelDriver *driver = fcu->driver;
OperationKey driver_key(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
@@ -922,16 +971,20 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
- /* create dependency between driver and data affected by it */
+ /* Create dependency between driver and data affected by it. */
/* - direct property relationship... */
//RNAPathKey affected_key(id, fcu->rna_path);
- //add_relation(driver_key, affected_key, DEPSREL_TYPE_DRIVER, "[Driver -> Data] DepsRel");
+ //add_relation(driver_key, affected_key, "[Driver -> Data] DepsRel");
- /* driver -> data components (for interleaved evaluation - bones/constraints/modifiers) */
- // XXX: this probably should probably be moved out into a separate function
+ /* Driver -> data components (for interleaved evaluation
+ * bones/constraints/modifiers).
+ */
+ // XXX: this probably should probably be moved out into a separate function.
if (strstr(rna_path, "pose.bones[") != NULL) {
/* interleaved drivers during bone eval */
- // TODO: ideally, if this is for a constraint, it goes to said constraint
+ /* TODO: ideally, if this is for a constraint, it goes to said
+ * constraint.
+ */
Object *ob = (Object *)id;
char *bone_name;
@@ -944,8 +997,11 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
}
if (pchan) {
- OperationKey bone_key(id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Driver -> Bone]");
+ OperationKey bone_key(id,
+ DEG_NODE_TYPE_BONE,
+ pchan->name,
+ DEG_OPCODE_BONE_LOCAL);
+ add_relation(driver_key, bone_key, "[Driver -> Bone]");
}
else {
fprintf(stderr,
@@ -954,30 +1010,36 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
}
}
else if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
- /* drivers on armature-level bone settings (i.e. bbone stuff),
- * which will affect the evaluation of corresponding pose bones
+ /* Drivers on armature-level bone settings (i.e. bbone stuff),
+ * which will affect the evaluation of corresponding pose bones.
*/
IDDepsNode *arm_node = m_graph->find_id_node(id);
char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
if (arm_node && bone_name) {
- /* find objects which use this, and make their eval callbacks depend on this */
+ /* Find objects which use this, and make their eval callbacks
+ * depend on this.
+ */
foreach (DepsRelation *rel, arm_node->outlinks) {
IDDepsNode *to_node = (IDDepsNode *)rel->to;
-
- /* we only care about objects with pose data which use this... */
+ /* We only care about objects with pose data which use this. */
if (GS(to_node->id->name) == ID_OB) {
Object *ob = (Object *)to_node->id;
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); // NOTE: ob->pose may be NULL
-
- if (pchan) {
- OperationKey bone_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Arm Bone -> Driver -> Bone]");
+ /* NOTE: ob->pose may be NULL. */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(
+ ob->pose, bone_name);
+ if (pchan != NULL) {
+ OperationKey bone_key(&ob->id,
+ DEG_NODE_TYPE_BONE,
+ pchan->name,
+ DEG_OPCODE_BONE_LOCAL);
+ add_relation(driver_key,
+ bone_key,
+ "[Arm Bone -> Driver -> Bone]");
}
}
}
-
- /* free temp data */
+ /* Free temp data. */
MEM_freeN(bone_name);
bone_name = NULL;
}
@@ -988,65 +1050,69 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
}
}
else if (GS(id->name) == ID_OB && strstr(rna_path, "modifiers[")) {
- /* modifier driver - connect directly to the modifier */
- char *modifier_name = BLI_str_quoted_substrN(rna_path, "modifiers[");
- if (modifier_name) {
- OperationKey modifier_key(id,
- DEPSNODE_TYPE_GEOMETRY,
- DEG_OPCODE_GEOMETRY_MODIFIER,
- modifier_name);
- if (has_node(modifier_key)) {
- add_relation(driver_key, modifier_key, DEPSREL_TYPE_DRIVER, "[Driver -> Modifier]");
- }
- else {
- printf("Unexisting driver RNA path: %s\n", rna_path);
- }
-
- MEM_freeN(modifier_name);
+ OperationKey modifier_key(id,
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+ if (has_node(modifier_key)) {
+ add_relation(driver_key, modifier_key, "[Driver -> Modifier]");
+ }
+ else {
+ printf("Unexisting driver RNA path: %s\n", rna_path);
}
}
else if (GS(id->name) == ID_KE && strstr(rna_path, "key_blocks[")) {
- /* shape key driver - hook into the base geometry operation */
+ /* Shape key driver - hook into the base geometry operation. */
// XXX: double check where this points
Key *shape_key = (Key *)id;
- ComponentKey geometry_key(shape_key->from, DEPSNODE_TYPE_GEOMETRY);
- add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]");
+ ComponentKey geometry_key(shape_key->from, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, "[Driver -> ShapeKey Geom]");
}
else if (strstr(rna_path, "key_blocks[")) {
- ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]");
+ ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, "[Driver -> ShapeKey Geom]");
}
else {
if (GS(id->name) == ID_OB) {
/* assume that driver affects a transform... */
- OperationKey local_transform_key(id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
- add_relation(driver_key, local_transform_key, DEPSREL_TYPE_OPERATION, "[Driver -> Transform]");
+ OperationKey local_transform_key(id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_LOCAL);
+ add_relation(driver_key,
+ local_transform_key,
+ "[Driver -> Transform]");
}
else if (GS(id->name) == ID_KE) {
- ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(driver_key, geometry_key, DEPSREL_TYPE_GEOMETRY_EVAL, "[Driver -> Shapekey Geometry]");
+ ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(driver_key,
+ geometry_key,
+ "[Driver -> Shapekey Geometry]");
}
}
-
- /* ensure that affected prop's update callbacks will be triggered once done */
- // TODO: implement this once the functionality to add these links exists in RNA
- // XXX: the data itself could also set this, if it were to be truly initialised later?
-
- /* loop over variables to get the target relationships */
+ /* Ensure that affected prop's update callbacks will be triggered once
+ * done.
+ */
+ /* TODO: Implement this once the functionality to add these links exists
+ * RNA.
+ */
+ /* XXX: the data itself could also set this, if it were to be truly
+ * initialised later?
+ */
+ /* Loop over variables to get the target relationships. */
LINKLIST_FOREACH (DriverVar *, dvar, &driver->variables) {
- /* only used targets */
+ /* Only used targets. */
DRIVER_TARGETS_USED_LOOPER(dvar)
{
- if (dtar->id == NULL)
+ if (dtar->id == NULL) {
continue;
-
- /* special handling for directly-named bones */
+ }
+ /* Special handling for directly-named bones. */
if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) {
Object *ob = (Object *)dtar->id;
- bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
+ bPoseChannel *target_pchan =
+ BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
if (target_pchan != NULL) {
- /* get node associated with bone */
+ /* Get node associated with bone. */
// XXX: watch the space!
/* Some cases can't use final bone transform, for example:
* - Driving the bone with itself (addressed here)
@@ -1058,61 +1124,81 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
{
continue;
}
- OperationKey target_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Bone Target -> Driver]");
+ OperationKey target_key(dtar->id,
+ DEG_NODE_TYPE_BONE,
+ target_pchan->name,
+ DEG_OPCODE_BONE_DONE);
+ add_relation(target_key,
+ driver_key,
+ "[Bone Target -> Driver]");
}
}
else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
- /* get node associated with the object's transforms */
- OperationKey target_key(dtar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
- add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Target -> Driver]");
+ /* Get node associated with the object's transforms. */
+ if (dtar->id == id) {
+ /* Ignore input dependency if we're driving properties of
+ * the same ID, otherwise we'll be ending up in a cyclic
+ * dependency here.
+ */
+ continue;
+ }
+ OperationKey target_key(dtar->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, driver_key, "[Target -> Driver]");
}
else if (dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) {
- /* workaround for ensuring that local bone transforms don't end up
- * having to wait for pose eval to finish (to prevent cycles)
+ /* Workaround for ensuring that local bone transforms don't end
+ * up having to wait for pose eval to finish (to prevent cycles).
*/
Object *ob = (Object *)dtar->id;
- char *bone_name = BLI_str_quoted_substrN(dtar->rna_path, "pose.bones[");
- bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
- if (bone_name) {
+ char *bone_name = BLI_str_quoted_substrN(dtar->rna_path,
+ "pose.bones[");
+ bPoseChannel *target_pchan =
+ BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (bone_name != NULL) {
MEM_freeN(bone_name);
bone_name = NULL;
}
- if (target_pchan) {
+ if (target_pchan != NULL) {
if (dtar->id == id &&
pchan != NULL &&
STREQ(pchan->name, target_pchan->name))
{
continue;
}
- OperationKey bone_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(bone_key, driver_key, DEPSREL_TYPE_DRIVER, "[RNA Bone -> Driver]");
+ OperationKey bone_key(dtar->id,
+ DEG_NODE_TYPE_BONE,
+ target_pchan->name,
+ DEG_OPCODE_BONE_LOCAL);
+ add_relation(bone_key, driver_key, "[RNA Bone -> Driver]");
}
}
else {
if (dtar->id == id) {
- /* Ignore input dependency if we're driving properties of the same ID,
- * otherwise we'll be ending up in a cyclic dependency here.
+ /* Ignore input dependency if we're driving properties of
+ * the same ID, otherwise we'll be ending up in a cyclic
+ * dependency here.
*/
continue;
}
- /* resolve path to get node */
- RNAPathKey target_key(dtar->id, dtar->rna_path ? dtar->rna_path : "");
- add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[RNA Target -> Driver]");
+ /* Resolve path to get node. */
+ RNAPathKey target_key(dtar->id,
+ dtar->rna_path ? dtar->rna_path : "");
+ add_relation(target_key, driver_key, "[RNA Target -> Driver]");
}
}
DRIVER_TARGETS_LOOPER_END
}
-
- /* It's quite tricky to detect if the driver actually depends on time or not,
- * so for now we'll be quite conservative here about optimization and consider
- * all python drivers to be depending on time.
+ /* It's quite tricky to detect if the driver actually depends on time or
+ * not, so for now we'll be quite conservative here about optimization and
+ * consider all python drivers to be depending on time.
*/
if ((driver->type == DRIVER_TYPE_PYTHON) &&
python_driver_depends_on_time(driver))
{
TimeSourceKey time_src_key;
- add_relation(time_src_key, driver_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Driver]");
+ add_relation(time_src_key, driver_key, "[TimeSrc -> Driver]");
}
}
@@ -1134,10 +1220,9 @@ void DepsgraphRelationBuilder::build_world(World *world)
/* world's nodetree */
if (world->nodetree != NULL) {
build_nodetree(world->nodetree);
- ComponentKey ntree_key(&world->nodetree->id, DEPSNODE_TYPE_PARAMETERS);
- ComponentKey world_key(world_id, DEPSNODE_TYPE_PARAMETERS);
- add_relation(ntree_key, world_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "NTree->World Parameters");
+ ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey world_key(world_id, DEG_NODE_TYPE_PARAMETERS);
+ add_relation(ntree_key, world_key, "NTree->World Parameters");
}
}
@@ -1145,20 +1230,17 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
- OperationKey init_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_REBUILD);
- OperationKey sim_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_SIM);
+ OperationKey init_key(&scene->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_REBUILD);
+ OperationKey sim_key(&scene->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_SIM);
/* rel between the two sim-nodes */
- add_relation(init_key, sim_key, DEPSREL_TYPE_OPERATION, "Rigidbody [Init -> SimStep]");
+ add_relation(init_key, sim_key, "Rigidbody [Init -> SimStep]");
/* set up dependencies between these operations and other builtin nodes --------------- */
/* time dependency */
TimeSourceKey time_src_key;
- add_relation(time_src_key,
- init_key,
- DEPSREL_TYPE_TIME,
- "TimeSrc -> Rigidbody Reset/Rebuild (Optional)");
+ add_relation(time_src_key, init_key, "TimeSrc -> Rigidbody Reset/Rebuild (Optional)");
/* objects - simulation participants */
if (rbw->group) {
@@ -1176,12 +1258,12 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
* XXX: there's probably a difference between passive and active
* - passive don't change, so may need to know full transform...
*/
- OperationKey rbo_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+ OperationKey rbo_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
eDepsOperation_Code trans_opcode = ob->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
- OperationKey trans_op(&ob->id, DEPSNODE_TYPE_TRANSFORM, trans_opcode);
+ OperationKey trans_op(&ob->id, DEG_NODE_TYPE_TRANSFORM, trans_opcode);
- add_relation(sim_key, rbo_key, DEPSREL_TYPE_COMPONENT_ORDER, "Rigidbody Sim Eval -> RBO Sync");
+ add_relation(sim_key, rbo_key, "Rigidbody Sim Eval -> RBO Sync");
/* if constraints exist, those depend on the result of the rigidbody sim
* - This allows constraints to modify the result of the sim (i.e. clamping)
@@ -1193,12 +1275,9 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
*/
if (ob->constraints.first) {
OperationKey constraint_key(&ob->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
- add_relation(rbo_key,
- constraint_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "RBO Sync -> Ob Constraints");
+ add_relation(rbo_key, constraint_key, "RBO Sync -> Ob Constraints");
}
else {
/* Final object transform depends on rigidbody.
@@ -1207,19 +1286,13 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
* If it is gone we'll need to reconsider relation here.
*/
OperationKey uber_key(&ob->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_OBJECT_UBEREVAL);
- add_relation(rbo_key,
- uber_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "RBO Sync -> Uber (Temp)");
+ add_relation(rbo_key, uber_key, "RBO Sync -> Uber (Temp)");
}
/* Needed to get correct base values. */
- add_relation(trans_op,
- sim_key,
- DEPSREL_TYPE_OPERATION,
- "Base Ob Transform -> Rigidbody Sim Eval");
+ add_relation(trans_op, sim_key, "Base Ob Transform -> Rigidbody Sim Eval");
}
}
@@ -1236,16 +1309,16 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* final result of the constraint object's transform controls how the
* constraint affects the physics sim for these objects
*/
- ComponentKey trans_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- OperationKey ob1_key(&rbc->ob1->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
- OperationKey ob2_key(&rbc->ob2->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+ ComponentKey trans_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ OperationKey ob1_key(&rbc->ob1->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+ OperationKey ob2_key(&rbc->ob2->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
/* - constrained-objects sync depends on the constraint-holder */
- add_relation(trans_key, ob1_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_1");
- add_relation(trans_key, ob2_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_2");
+ add_relation(trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1");
+ add_relation(trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2");
/* - ensure that sim depends on this constraint's transform */
- add_relation(trans_key, sim_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint Transform -> RB Simulation");
+ add_relation(trans_key, sim_key, "RigidBodyConstraint Transform -> RB Simulation");
}
}
}
@@ -1254,8 +1327,15 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
{
TimeSourceKey time_src_key;
OperationKey obdata_ubereval_key(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
+ DEG_NODE_TYPE_GEOMETRY,
DEG_OPCODE_GEOMETRY_UBEREVAL);
+ OperationKey eval_init_key(&ob->id,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
+ DEG_OPCODE_PSYS_EVAL_INIT);
+ /* TODO(sergey): Are all particle systems depends on time?
+ * Hair without dynamics i.e.
+ */
+ add_relation(time_src_key, eval_init_key, "TimeSrc -> PSys");
/* particle systems */
LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
@@ -1265,55 +1345,19 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
build_animdata(&part->id);
/* this particle system */
- OperationKey psys_key(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name);
+ OperationKey psys_key(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name);
/* XXX: if particle system is later re-enabled, we must do full rebuild? */
if (!psys_check_enabled(ob, psys, G.is_rendering))
continue;
- /* TODO(sergey): Are all particle systems depends on time?
- * Hair without dynamics i.e.
- */
- add_relation(time_src_key, psys_key,
- DEPSREL_TYPE_TIME,
- "TimeSrc -> PSys");
+ add_relation(eval_init_key, psys_key, "Init -> PSys");
/* TODO(sergey): Currently particle update is just a placeholder,
* hook it to the ubereval node so particle system is getting updated
* on playback.
*/
- add_relation(psys_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_OPERATION,
- "PSys -> UberEval");
-
-#if 0
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- LINKLIST_FOREACH (ParticleTarget *, pt, &psys->targets) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- LINKLIST_FOREACH (GroupObject *, go, &part->dup_group->gobject) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-#endif
+ add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval");
/* collisions */
if (part->type != PART_HAIR) {
@@ -1337,19 +1381,16 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
ruleob = ((BoidRuleFollowLeader *)rule)->ob;
if (ruleob) {
- ComponentKey ruleob_key(&ruleob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(ruleob_key, psys_key, DEPSREL_TYPE_TRANSFORM, "Boid Rule");
+ ComponentKey ruleob_key(&ruleob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(ruleob_key, psys_key, "Boid Rule");
}
}
}
}
if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- ComponentKey dup_ob_key(&part->dup_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dup_ob_key,
- psys_key,
- DEPSREL_TYPE_TRANSFORM,
- "Particle Object Visualization");
+ ComponentKey dup_ob_key(&part->dup_ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
}
}
@@ -1359,11 +1400,8 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
* TODO(sergey): This relation should be altered once real granular update
* is implemented.
*/
- ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_GEOMETRY_EVAL,
- "Partcile Eval");
+ ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
/* pointcache */
// TODO...
@@ -1371,27 +1409,23 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
void DepsgraphRelationBuilder::build_cloth(Scene * /*scene*/,
Object *object,
- ModifierData *md)
+ ModifierData * /*md*/)
{
OperationKey cache_key(&object->id,
- DEPSNODE_TYPE_CACHE,
+ DEG_NODE_TYPE_CACHE,
DEG_OPCODE_PLACEHOLDER,
"Cloth Modifier");
/* Cache component affects on modifier. */
OperationKey modifier_key(&object->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEG_OPCODE_GEOMETRY_MODIFIER,
- md->name);
- add_relation(cache_key,
- modifier_key,
- DEPSREL_TYPE_TIME,
- "Cloth Cache -> Cloth");
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+ add_relation(cache_key, modifier_key, "Cloth Cache -> Cloth");
}
/* Shapekeys */
void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
{
- ComponentKey obdata_key(obdata, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey obdata_key(obdata, DEG_NODE_TYPE_GEOMETRY);
/* attach animdata to geometry */
build_animdata(&key->id);
@@ -1399,8 +1433,8 @@ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
if (key->adt) {
// TODO: this should really be handled in build_animdata, since many of these cases will need it
if (key->adt->action || key->adt->nla_tracks.first) {
- ComponentKey adt_key(&key->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(adt_key, obdata_key, DEPSREL_TYPE_OPERATION, "Animation");
+ ComponentKey adt_key(&key->id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(adt_key, obdata_key, "Animation");
}
/* NOTE: individual shapekey drivers are handled above already */
@@ -1408,8 +1442,8 @@ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
/* attach to geometry */
// XXX: aren't shapekeys now done as a pseudo-modifier on object?
- //ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY); // FIXME: this doesn't exist
- //add_relation(key_key, obdata_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Shapekeys");
+ //ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY); // FIXME: this doesn't exist
+ //add_relation(key_key, obdata_key, "Shapekeys");
}
/**
@@ -1437,34 +1471,26 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
ID *obdata = (ID *)ob->data;
/* Init operation of object-level geometry evaluation. */
- OperationKey geom_init_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init");
+ OperationKey geom_init_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init");
/* get nodes for result of obdata's evaluation, and geometry evaluation on object */
- ComponentKey obdata_geom_key(obdata, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey geom_key(&ob->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey obdata_geom_key(obdata, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey geom_key(&ob->id, DEG_NODE_TYPE_GEOMETRY);
/* link components to each other */
- add_relation(obdata_geom_key, geom_key, DEPSREL_TYPE_DATABLOCK, "Object Geometry Base Data");
+ add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
/* Modifiers */
- if (ob->modifiers.first) {
- OperationKey prev_mod_key;
+ if (ob->modifiers.first != NULL) {
+ OperationKey obdata_ubereval_key(&ob->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
- OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
-
- if (md->prev) {
- /* Stack relation: modifier depends on previous modifier in the stack */
- add_relation(prev_mod_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack");
- }
- else {
- /* Stack relation: first modifier depends on the geometry. */
- add_relation(geom_init_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack");
- }
if (mti->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(mod_key);
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
mti->updateDepsgraph(
md,
bmain,
@@ -1475,7 +1501,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
if (BKE_object_modifier_use_time(ob, md)) {
TimeSourceKey time_src_key;
- add_relation(time_src_key, mod_key, DEPSREL_TYPE_TIME, "Time Source");
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
/* Hacky fix for T45633 (Animated modifiers aren't updated)
*
@@ -1484,16 +1510,14 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
*/
/* XXX: Remove this hack when these links are added as part of build_animdata() instead */
if (modifier_dependsOnTime(md) == false && needs_animdata_node(&ob->id)) {
- ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, mod_key, DEPSREL_TYPE_OPERATION, "Modifier Animation");
+ ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, obdata_ubereval_key, "Modifier Animation");
}
}
if (md->type == eModifierType_Cloth) {
build_cloth(scene, ob, md);
}
-
- prev_mod_key = mod_key;
}
}
@@ -1518,15 +1542,8 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
*/
if (ob->type != OB_ARMATURE) {
/* Armatures does no longer require uber node. */
- OperationKey obdata_ubereval_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
- if (ob->modifiers.last) {
- ModifierData *md = (ModifierData *)ob->modifiers.last;
- OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
- add_relation(mod_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval");
- }
- else {
- add_relation(geom_init_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval");
- }
+ OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
+ add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
}
if (obdata->tag & LIB_TAG_DOIT) {
@@ -1535,13 +1552,26 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
obdata->tag |= LIB_TAG_DOIT;
/* Link object data evaluation node to exit operation. */
- OperationKey obdata_geom_eval_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
- OperationKey obdata_geom_done_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Done");
- add_relation(obdata_geom_eval_key, obdata_geom_done_key, DEPSREL_TYPE_DATABLOCK, "ObData Geom Eval Done");
+ OperationKey obdata_geom_eval_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
+ OperationKey obdata_geom_done_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Done");
+ add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
/* type-specific node/links */
switch (ob->type) {
case OB_MESH:
+ /* NOTE: This is compatibility code to support particle systems
+ *
+ * for viewport being properly rendered in final render mode.
+ * This relation is similar to what dag_object_time_update_flags()
+ * was doing for mesh objects with particle system/
+ *
+ * Ideally we need to get rid of this relation.
+ */
+ if (ob->particlesystem.first != NULL) {
+ TimeSourceKey time_key;
+ OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
+ add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
+ }
break;
case OB_MBALL:
@@ -1551,10 +1581,10 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
/* motherball - mom depends on children! */
if (mom != ob) {
/* non-motherball -> cannot be directly evaluated! */
- ComponentKey mom_key(&mom->id, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(geom_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball");
- add_relation(transform_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball");
+ ComponentKey mom_key(&mom->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(geom_key, mom_key, "Metaball Motherball");
+ add_relation(transform_key, mom_key, "Metaball Motherball");
}
break;
}
@@ -1567,20 +1597,20 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
/* curve's dependencies */
// XXX: these needs geom data, but where is geom stored?
if (cu->bevobj) {
- ComponentKey bevob_key(&cu->bevobj->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey bevob_key(&cu->bevobj->id, DEG_NODE_TYPE_GEOMETRY);
build_object(bmain, scene, cu->bevobj);
- add_relation(bevob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Bevel");
+ add_relation(bevob_key, geom_key, "Curve Bevel");
}
if (cu->taperobj) {
- ComponentKey taperob_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey taperob_key(&cu->taperobj->id, DEG_NODE_TYPE_GEOMETRY);
build_object(bmain, scene, cu->taperobj);
- add_relation(taperob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Taper");
+ add_relation(taperob_key, geom_key, "Curve Taper");
}
if (ob->type == OB_FONT) {
if (cu->textoncurve) {
- ComponentKey textoncurve_key(&cu->textoncurve->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey textoncurve_key(&cu->textoncurve->id, DEG_NODE_TYPE_GEOMETRY);
build_object(bmain, scene, cu->textoncurve);
- add_relation(textoncurve_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Text on Curve");
+ add_relation(textoncurve_key, geom_key, "Text on Curve");
}
}
break;
@@ -1604,14 +1634,13 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
}
if (needs_animdata_node(obdata)) {
- ComponentKey animation_key(obdata, DEPSNODE_TYPE_ANIMATION);
- ComponentKey parameters_key(obdata, DEPSNODE_TYPE_PARAMETERS);
- add_relation(animation_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "Geom Parameters");
+ ComponentKey animation_key(obdata, DEG_NODE_TYPE_ANIMATION);
+ ComponentKey parameters_key(obdata, DEG_NODE_TYPE_PARAMETERS);
+ add_relation(animation_key, parameters_key, "Geom Parameters");
/* Evaluation usually depends on animation.
* TODO(sergey): Need to re-hook it after granular update is implemented..
*/
- add_relation(animation_key, obdata_geom_eval_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Animation");
+ add_relation(animation_key, obdata_geom_eval_key, "Animation");
}
}
@@ -1626,19 +1655,18 @@ void DepsgraphRelationBuilder::build_camera(Object *ob)
}
camera_id->tag |= LIB_TAG_DOIT;
- ComponentKey parameters_key(camera_id, DEPSNODE_TYPE_PARAMETERS);
+ ComponentKey parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS);
if (needs_animdata_node(camera_id)) {
- ComponentKey animation_key(camera_id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "Camera Parameters");
+ ComponentKey animation_key(camera_id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key, "Camera Parameters");
}
/* DOF */
if (cam->dof_ob) {
- ComponentKey ob_param_key(&ob->id, DEPSNODE_TYPE_PARAMETERS);
- ComponentKey dof_ob_key(&cam->dof_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dof_ob_key, ob_param_key, DEPSREL_TYPE_TRANSFORM, "Camera DOF");
+ ComponentKey ob_param_key(&ob->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(dof_ob_key, ob_param_key, "Camera DOF");
}
}
@@ -1652,20 +1680,18 @@ void DepsgraphRelationBuilder::build_lamp(Object *ob)
}
lamp_id->tag |= LIB_TAG_DOIT;
- ComponentKey parameters_key(lamp_id, DEPSNODE_TYPE_PARAMETERS);
+ ComponentKey parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
if (needs_animdata_node(lamp_id)) {
- ComponentKey animation_key(lamp_id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "Lamp Parameters");
+ ComponentKey animation_key(lamp_id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key, "Lamp Parameters");
}
/* lamp's nodetree */
if (la->nodetree) {
build_nodetree(la->nodetree);
- ComponentKey nodetree_key(&la->nodetree->id, DEPSNODE_TYPE_PARAMETERS);
- add_relation(nodetree_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "NTree->Lamp Parameters");
+ ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
+ add_relation(nodetree_key, parameters_key, "NTree->Lamp Parameters");
}
/* textures */
@@ -1682,7 +1708,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
build_animdata(ntree_id);
OperationKey parameters_key(ntree_id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"Parameters Eval");
@@ -1702,19 +1728,17 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
group_ntree->id.tag |= LIB_TAG_DOIT;
}
OperationKey group_parameters_key(&group_ntree->id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"Parameters Eval");
- add_relation(group_parameters_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "Group Node");
+ add_relation(group_parameters_key, parameters_key, "Group Node");
}
}
}
if (needs_animdata_node(ntree_id)) {
- ComponentKey animation_key(ntree_id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "NTree Parameters");
+ ComponentKey animation_key(ntree_id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key, "NTree Parameters");
}
}
@@ -1737,15 +1761,14 @@ void DepsgraphRelationBuilder::build_material(Material *ma)
if (ma->nodetree != NULL) {
build_nodetree(ma->nodetree);
OperationKey ntree_key(&ma->nodetree->id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"Parameters Eval");
OperationKey material_key(&ma->id,
- DEPSNODE_TYPE_SHADING,
+ DEG_NODE_TYPE_SHADING,
DEG_OPCODE_PLACEHOLDER,
"Material Update");
- add_relation(ntree_key, material_key,
- DEPSREL_TYPE_UPDATE, "Material's NTree");
+ add_relation(ntree_key, material_key, "Material's NTree");
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 4ca95bebe3f..02f8fc69070 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -78,17 +78,12 @@ struct Depsgraph;
struct DepsNode;
struct DepsNodeHandle;
struct RootDepsNode;
-struct SubgraphDepsNode;
struct IDDepsNode;
struct TimeSourceDepsNode;
struct ComponentDepsNode;
struct OperationDepsNode;
struct RootPChanMap;
-struct RootKey {
- RootKey();
-};
-
struct TimeSourceKey
{
TimeSourceKey();
@@ -177,19 +172,16 @@ struct DepsgraphRelationBuilder
template <typename KeyFrom, typename KeyTo>
void add_relation(const KeyFrom& key_from,
const KeyTo& key_to,
- eDepsRelation_Type type,
const char *description);
template <typename KeyTo>
void add_relation(const TimeSourceKey& key_from,
const KeyTo& key_to,
- eDepsRelation_Type type,
const char *description);
template <typename KeyType>
void add_node_handle_relation(const KeyType& key_from,
const DepsNodeHandle *handle,
- eDepsRelation_Type type,
const char *description);
void build_scene(Main *bmain, Scene *scene);
@@ -237,8 +229,9 @@ struct DepsgraphRelationBuilder
template <typename KeyType>
OperationDepsNode *find_operation_node(const KeyType &key);
+ Depsgraph *getGraph();
+
protected:
- RootDepsNode *find_node(const RootKey &key) const;
TimeSourceDepsNode *find_node(const TimeSourceKey &key) const;
ComponentDepsNode *find_node(const ComponentKey &key) const;
OperationDepsNode *find_node(const OperationKey &key) const;
@@ -250,7 +243,6 @@ protected:
const char *description);
void add_operation_relation(OperationDepsNode *node_from,
OperationDepsNode *node_to,
- eDepsRelation_Type type,
const char *description);
template <typename KeyType>
@@ -290,7 +282,6 @@ OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType&
template <typename KeyFrom, typename KeyTo>
void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
const KeyTo &key_to,
- eDepsRelation_Type type,
const char *description)
{
DepsNode *node_from = find_node(key_from);
@@ -298,27 +289,27 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
if (op_from && op_to) {
- add_operation_relation(op_from, op_to, type, description);
+ add_operation_relation(op_from, op_to, description);
}
else {
if (!op_from) {
/* XXX TODO handle as error or report if needed */
node_from = find_node(key_from);
- fprintf(stderr, "add_relation(%d, %s) - Could not find op_from (%s)\n",
- type, description, key_from.identifier().c_str());
+ fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n",
+ description, key_from.identifier().c_str());
}
else {
- fprintf(stderr, "add_relation(%d, %s) - Failed, but op_from (%s) was ok\n",
- type, description, key_from.identifier().c_str());
+ fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n",
+ description, key_from.identifier().c_str());
}
if (!op_to) {
/* XXX TODO handle as error or report if needed */
- fprintf(stderr, "add_relation(%d, %s) - Could not find op_to (%s)\n",
- type, description, key_to.identifier().c_str());
+ fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n",
+ description, key_to.identifier().c_str());
}
else {
- fprintf(stderr, "add_relation(%d, %s) - Failed, but op_to (%s) was ok\n",
- type, description, key_to.identifier().c_str());
+ fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n",
+ description, key_to.identifier().c_str());
}
}
}
@@ -326,11 +317,8 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
template <typename KeyTo>
void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
const KeyTo &key_to,
- eDepsRelation_Type type,
const char *description)
{
- (void)type; /* Ignored in release builds. */
- BLI_assert(type == DEPSREL_TYPE_TIME);
TimeSourceDepsNode *time_from = find_node(key_from);
DepsNode *node_to = find_node(key_to);
OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
@@ -345,23 +333,22 @@ template <typename KeyType>
void DepsgraphRelationBuilder::add_node_handle_relation(
const KeyType &key_from,
const DepsNodeHandle *handle,
- eDepsRelation_Type type,
const char *description)
{
DepsNode *node_from = find_node(key_from);
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
OperationDepsNode *op_to = handle->node->get_entry_operation();
if (op_from && op_to) {
- add_operation_relation(op_from, op_to, type, description);
+ add_operation_relation(op_from, op_to, description);
}
else {
if (!op_from) {
- fprintf(stderr, "add_node_handle_relation(%d, %s) - Could not find op_from (%s)\n",
- type, description, key_from.identifier().c_str());
+ fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n",
+ description, key_from.identifier().c_str());
}
if (!op_to) {
- fprintf(stderr, "add_node_handle_relation(%d, %s) - Could not find op_to (%s)\n",
- type, description, key_from.identifier().c_str());
+ fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n",
+ description, key_from.identifier().c_str());
}
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
index feae8bca303..9d6ab3358a7 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
@@ -35,13 +35,6 @@
namespace DEG {
/////////////////////////////////////////
-// Root.
-
-RootKey::RootKey()
-{
-}
-
-/////////////////////////////////////////
// Time source.
TimeSourceKey::TimeSourceKey()
@@ -64,7 +57,7 @@ string TimeSourceKey::identifier() const
ComponentKey::ComponentKey()
: id(NULL),
- type(DEPSNODE_TYPE_UNDEFINED),
+ type(DEG_NODE_TYPE_UNDEFINED),
name("")
{
}
@@ -90,7 +83,7 @@ string ComponentKey::identifier() const
OperationKey::OperationKey()
: id(NULL),
- component_type(DEPSNODE_TYPE_UNDEFINED),
+ component_type(DEG_NODE_TYPE_UNDEFINED),
component_name(""),
opcode(DEG_OPCODE_OPERATION),
name(""),
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index 2b4c000f483..be666165a0b 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -38,10 +38,10 @@
#include "MEM_guardedalloc.h"
-extern "C" {
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+extern "C" {
#include "DNA_action_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -51,10 +51,10 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/builder/deg_builder_pchanmap.h"
@@ -83,7 +83,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
* - see notes on direction of rel below...
*/
bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
- OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
+ OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
/* IK target */
// XXX: this should get handled as part of the constraint code
@@ -96,25 +96,25 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
* testing IK solver.
*/
// FIXME: geometry targets...
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+ ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
/* TODO(sergey): This is only for until granular update stores intermediate result. */
if (data->tar != ob) {
/* different armature - can just read the results */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_BONE, data->subtarget);
+ add_relation(target_key, pose_key, con->name);
}
else {
/* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */
- OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ OperationKey target_key(&data->tar->id, DEG_NODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
+ add_relation(target_key, solver_key, con->name);
}
}
else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) {
/* vertex group target */
/* NOTE: for now, we don't need to represent vertex groups separately... */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
+ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, solver_key, con->name);
if (data->tar->type == OB_MESH) {
OperationDepsNode *node2 = find_operation_node(target_key);
@@ -125,8 +125,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
}
else {
/* Standard Object Target */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_key, pose_key, con->name);
}
if ((data->tar == ob) && (data->subtarget[0])) {
@@ -142,14 +142,14 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
if (data->poletar != NULL) {
if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
// XXX: same armature issues - ready vs done?
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->polesubtarget);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_BONE, data->polesubtarget);
+ add_relation(target_key, solver_key, con->name);
}
else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->polesubtarget[0])) {
/* vertex group target */
/* NOTE: for now, we don't need to represent vertex groups separately... */
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
+ ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, solver_key, con->name);
if (data->poletar->type == OB_MESH) {
OperationDepsNode *node2 = find_operation_node(target_key);
@@ -159,8 +159,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
}
}
else {
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_key, solver_key, con->name);
}
}
@@ -170,19 +170,17 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
bPoseChannel *parchan = pchan;
/* exclude tip from chain? */
if (!(data->flag & CONSTRAINT_IK_TIP)) {
- OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
+ OperationKey tip_transforms_key(&ob->id, DEG_NODE_TYPE_BONE,
parchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(solver_key, tip_transforms_key,
- DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
+ add_relation(solver_key, tip_transforms_key, "IK Solver Result");
parchan = pchan->parent;
}
root_map->add_bone(parchan->name, rootchan->name);
- OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
+ OperationKey parchan_transforms_key(&ob->id, DEG_NODE_TYPE_BONE,
parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parchan_transforms_key, solver_key,
- DEPSREL_TYPE_TRANSFORM, "IK Solver Owner");
+ add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
/* Walk to the chain's root */
//size_t segcount = 0;
@@ -196,15 +194,15 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
* grab the result with IK solver results...
*/
if (parchan != pchan) {
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent");
+ OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+ add_relation(parent_key, solver_key, "IK Chain Parent");
- OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+ OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, done_key, "IK Chain Result");
}
else {
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
+ OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, "IK Solver Result");
}
parchan->flag |= POSE_DONE;
@@ -219,8 +217,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
parchan = parchan->parent;
}
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+ OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ add_relation(solver_key, flush_key, "PoseEval Result-Bone Link");
}
/* Spline IK Eval Steps */
@@ -231,14 +229,14 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
{
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
- OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
+ OperationKey transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
/* attach owner to IK Solver too
* - assume that owner is always part of chain
* - see notes on direction of rel below...
*/
- add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner");
+ add_relation(transforms_key, solver_key, "Spline IK Solver Owner");
/* attach path dependency to solver */
if (data->tar) {
@@ -247,14 +245,14 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
* See IK pose for a bit more information.
*/
// TODO: the bigggest point here is that we need the curve PATH and not just the general geometry...
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel");
+ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
+ add_relation(target_key, pose_key, "[Curve.Path -> Spline IK] DepsRel");
}
pchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result");
+ OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, "Spline IK Result");
root_map->add_bone(pchan->name, rootchan->name);
@@ -270,16 +268,16 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
* grab the result with IK solver results...
*/
if (parchan != pchan) {
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update");
+ OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+ add_relation(parent_key, solver_key, "Spline IK Solver Update");
- OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+ OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, done_key, "IK Chain Result");
}
parchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result");
+ OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, "Spline IK Solver Result");
root_map->add_bone(parchan->name, rootchan->name);
@@ -288,8 +286,8 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
if ((segcount == data->chainlen) || (segcount > 255)) break; /* 255 is weak */
}
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+ OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ add_relation(solver_key, flush_key, "PoseEval Result-Bone Link");
}
/* Pose/Armature Bones Graph */
@@ -301,21 +299,21 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
// TODO: selection status?
/* attach links between pose operations */
- OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ OperationKey init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+ OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]");
+ add_relation(init_key, flush_key, "[Pose Init -> Pose Cleanup]");
/* Make sure pose is up-to-date with armature updates. */
OperationKey armature_key(&arm->id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"Armature Eval");
- add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency");
+ add_relation(armature_key, init_key, "Data dependency");
if (needs_animdata_node(&ob->id)) {
- ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation");
+ ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, init_key, "Rig Animation");
}
/* IK Solvers...
@@ -370,26 +368,25 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
/* TODO(sergey): Once partial updates are possible use relation between
* object transform and solver itself in it's build function.
*/
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms");
+ ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(local_transform_key, pose_key, "Local Transforms");
}
-
/* links between operations for each bone */
LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
- OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_pose_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
+ OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
pchan->flag &= ~POSE_DONE;
/* pose init to bone local */
- add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link");
+ add_relation(init_key, bone_local_key, "PoseEval Source-Bone Link");
/* local to pose parenting operation */
- add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link");
+ add_relation(bone_local_key, bone_pose_key, "Bone Local - PoseSpace Link");
/* parent relation */
if (pchan->parent != NULL) {
@@ -403,26 +400,26 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
parent_key_opcode = DEG_OPCODE_BONE_DONE;
}
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
- add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]");
+ OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
+ add_relation(parent_key, bone_pose_key, "[Parent Bone -> Child Bone]");
}
/* constraints */
if (pchan->constraints.first != NULL) {
/* constraints stack and constraint dependencies */
- build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
+ build_constraints(scene, &ob->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
/* pose -> constraints */
- OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
- add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack");
+ OperationKey constraints_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
+ add_relation(bone_pose_key, constraints_key, "Constraints Stack");
/* constraints -> ready */
// TODO: when constraint stack is exploded, this step should occur before the first IK solver
- add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready");
+ add_relation(constraints_key, bone_ready_key, "Constraints -> Ready");
}
else {
/* pose -> ready */
- add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready");
+ add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready");
}
/* bone ready -> done
@@ -430,25 +427,25 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
* For IK chains however, an additional rel is created from IK to done,
* with transitive reduction removing this one...
*/
- add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
+ add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
/* assume that all bones must be done for the pose to be ready (for deformers) */
- add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+ add_relation(bone_done_key, flush_key, "PoseEval Result-Bone Link");
}
}
void DepsgraphRelationBuilder::build_proxy_rig(Object *ob)
{
- OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ OperationKey pose_init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+ OperationKey pose_done_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local");
- add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready");
- add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
- add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done");
+ OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
+ add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
+ add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
+ add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done");
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
index 3bf435c37e0..6a9568e7e8d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
@@ -38,20 +38,20 @@
#include "MEM_guardedalloc.h"
-extern "C" {
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+extern "C" {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_main.h"
#include "BKE_node.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/builder/deg_builder_pchanmap.h"
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
index da71db09f3d..b12af21fc8d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
@@ -30,9 +30,7 @@
#include "intern/builder/deg_builder_transitive.h"
-extern "C" {
#include "MEM_guardedalloc.h"
-}
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
@@ -105,7 +103,7 @@ void deg_graph_transitive_reduction(Depsgraph *graph)
/* Increment in advance, so we can safely remove the relation. */
++it_rel;
- if (rel->from->type == DEPSNODE_TYPE_TIMESOURCE) {
+ if (rel->from->type == DEG_NODE_TYPE_TIMESOURCE) {
/* HACK: time source nodes don't get "done" flag set/cleared. */
/* TODO: there will be other types in future, so iterators above
* need modifying.
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
index 0d56ce71c7d..51d4ed91419 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
@@ -35,10 +35,10 @@
extern "C" {
#include "DNA_listBase.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
-} /* extern "C" */
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
@@ -77,20 +77,18 @@ static const char *deg_debug_colors_light[] = {
#ifdef COLOR_SCHEME_NODE_TYPE
static const int deg_debug_node_type_color_map[][2] = {
- {DEPSNODE_TYPE_ROOT, 0},
- {DEPSNODE_TYPE_TIMESOURCE, 1},
- {DEPSNODE_TYPE_ID_REF, 2},
- {DEPSNODE_TYPE_SUBGRAPH, 3},
+ {DEG_NODE_TYPE_TIMESOURCE, 0},
+ {DEG_NODE_TYPE_ID_REF, 2},
/* Outer Types */
- {DEPSNODE_TYPE_PARAMETERS, 4},
- {DEPSNODE_TYPE_PROXY, 5},
- {DEPSNODE_TYPE_ANIMATION, 6},
- {DEPSNODE_TYPE_TRANSFORM, 7},
- {DEPSNODE_TYPE_GEOMETRY, 8},
- {DEPSNODE_TYPE_SEQUENCER, 9},
- {DEPSNODE_TYPE_SHADING, 10},
- {DEPSNODE_TYPE_CACHE, 11},
+ {DEG_NODE_TYPE_PARAMETERS, 2},
+ {DEG_NODE_TYPE_PROXY, 3},
+ {DEG_NODE_TYPE_ANIMATION, 4},
+ {DEG_NODE_TYPE_TRANSFORM, 5},
+ {DEG_NODE_TYPE_GEOMETRY, 6},
+ {DEG_NODE_TYPE_SEQUENCER, 7},
+ {DEG_NODE_TYPE_SHADING, 8},
+ {DEG_NODE_TYPE_CACHE, 9},
{-1, 0}
};
#endif
@@ -100,9 +98,9 @@ static int deg_debug_node_color_index(const DepsNode *node)
#ifdef COLOR_SCHEME_NODE_CLASS
/* Some special types. */
switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
+ case DEG_NODE_TYPE_ID_REF:
return 5;
- case DEPSNODE_TYPE_OPERATION:
+ case DEG_NODE_TYPE_OPERATION:
{
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->is_noop())
@@ -115,9 +113,9 @@ static int deg_debug_node_color_index(const DepsNode *node)
}
/* Do others based on class. */
switch (node->tclass) {
- case DEPSNODE_CLASS_OPERATION:
+ case DEG_NODE_CLASS_OPERATION:
return 4;
- case DEPSNODE_CLASS_COMPONENT:
+ case DEG_NODE_CLASS_COMPONENT:
return 1;
default:
return 9;
@@ -201,7 +199,7 @@ static void deg_debug_graphviz_node_color(const DebugContext &ctx,
const char *color_update = "dodgerblue3";
const char *color = color_default;
if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ if (node->tclass == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
color = color_modified;
@@ -222,7 +220,7 @@ static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx,
float penwidth_update = 4.0f;
float penwidth = penwidth_default;
if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ if (node->tclass == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
penwidth = penwidth_modified;
@@ -260,7 +258,7 @@ static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNod
{
const char *base_style = "filled"; /* default style */
if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ if (node->tclass == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) {
base_style = "striped";
@@ -268,13 +266,13 @@ static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNod
}
}
switch (node->tclass) {
- case DEPSNODE_CLASS_GENERIC:
+ case DEG_NODE_CLASS_GENERIC:
deg_debug_fprintf(ctx, "\"%s\"", base_style);
break;
- case DEPSNODE_CLASS_COMPONENT:
+ case DEG_NODE_CLASS_COMPONENT:
deg_debug_fprintf(ctx, "\"%s\"", base_style);
break;
- case DEPSNODE_CLASS_OPERATION:
+ case DEG_NODE_CLASS_OPERATION:
deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style);
break;
}
@@ -286,13 +284,13 @@ static void deg_debug_graphviz_node_single(const DebugContext &ctx,
const char *shape = "box";
string name = node->identifier();
float priority = -1.0f;
- if (node->type == DEPSNODE_TYPE_ID_REF) {
+ if (node->type == DEG_NODE_TYPE_ID_REF) {
IDDepsNode *id_node = (IDDepsNode *)node;
char buf[256];
BLI_snprintf(buf, sizeof(buf), " (Layers: %u)", id_node->layers);
name += buf;
}
- if (ctx.show_eval_priority && node->tclass == DEPSNODE_CLASS_OPERATION) {
+ if (ctx.show_eval_priority && node->tclass == DEG_NODE_CLASS_OPERATION) {
priority = ((OperationDepsNode *)node)->eval_priority;
}
deg_debug_fprintf(ctx, "// %s\n", name.c_str());
@@ -322,7 +320,7 @@ static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
const DepsNode *node)
{
string name = node->identifier();
- if (node->type == DEPSNODE_TYPE_ID_REF) {
+ if (node->type == DEG_NODE_TYPE_ID_REF) {
IDDepsNode *id_node = (IDDepsNode *)node;
char buf[256];
BLI_snprintf(buf, sizeof(buf), " (Layers: %u)", id_node->layers);
@@ -363,7 +361,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
const DepsNode *node)
{
switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
+ case DEG_NODE_TYPE_ID_REF:
{
const IDDepsNode *id_node = (const IDDepsNode *)node;
if (BLI_ghash_size(id_node->components) == 0) {
@@ -380,30 +378,17 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
}
break;
}
- case DEPSNODE_TYPE_SUBGRAPH:
- {
- SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
- if (sub_node->graph) {
- deg_debug_graphviz_node_cluster_begin(ctx, node);
- deg_debug_graphviz_graph_nodes(ctx, sub_node->graph);
- deg_debug_graphviz_node_cluster_end(ctx);
- }
- else {
- deg_debug_graphviz_node_single(ctx, node);
- }
- break;
- }
- case DEPSNODE_TYPE_PARAMETERS:
- case DEPSNODE_TYPE_ANIMATION:
- case DEPSNODE_TYPE_TRANSFORM:
- case DEPSNODE_TYPE_PROXY:
- case DEPSNODE_TYPE_GEOMETRY:
- case DEPSNODE_TYPE_SEQUENCER:
- case DEPSNODE_TYPE_EVAL_POSE:
- case DEPSNODE_TYPE_BONE:
- case DEPSNODE_TYPE_SHADING:
- case DEPSNODE_TYPE_CACHE:
- case DEPSNODE_TYPE_EVAL_PARTICLES:
+ case DEG_NODE_TYPE_PARAMETERS:
+ case DEG_NODE_TYPE_ANIMATION:
+ case DEG_NODE_TYPE_TRANSFORM:
+ case DEG_NODE_TYPE_PROXY:
+ case DEG_NODE_TYPE_GEOMETRY:
+ case DEG_NODE_TYPE_SEQUENCER:
+ case DEG_NODE_TYPE_EVAL_POSE:
+ case DEG_NODE_TYPE_BONE:
+ case DEG_NODE_TYPE_SHADING:
+ case DEG_NODE_TYPE_CACHE:
+ case DEG_NODE_TYPE_EVAL_PARTICLES:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
if (!comp_node->operations.empty()) {
@@ -427,24 +412,19 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
static bool deg_debug_graphviz_is_cluster(const DepsNode *node)
{
switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
+ case DEG_NODE_TYPE_ID_REF:
{
const IDDepsNode *id_node = (const IDDepsNode *)node;
return BLI_ghash_size(id_node->components) > 0;
}
- case DEPSNODE_TYPE_SUBGRAPH:
- {
- SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
- return sub_node->graph != NULL;
- }
- case DEPSNODE_TYPE_PARAMETERS:
- case DEPSNODE_TYPE_ANIMATION:
- case DEPSNODE_TYPE_TRANSFORM:
- case DEPSNODE_TYPE_PROXY:
- case DEPSNODE_TYPE_GEOMETRY:
- case DEPSNODE_TYPE_SEQUENCER:
- case DEPSNODE_TYPE_EVAL_POSE:
- case DEPSNODE_TYPE_BONE:
+ case DEG_NODE_TYPE_PARAMETERS:
+ case DEG_NODE_TYPE_ANIMATION:
+ case DEG_NODE_TYPE_TRANSFORM:
+ case DEG_NODE_TYPE_PROXY:
+ case DEG_NODE_TYPE_GEOMETRY:
+ case DEG_NODE_TYPE_SEQUENCER:
+ case DEG_NODE_TYPE_EVAL_POSE:
+ case DEG_NODE_TYPE_BONE:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
return !comp_node->operations.empty();
@@ -458,14 +438,14 @@ static bool deg_debug_graphviz_is_owner(const DepsNode *node,
const DepsNode *other)
{
switch (node->tclass) {
- case DEPSNODE_CLASS_COMPONENT:
+ case DEG_NODE_CLASS_COMPONENT:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
if (comp_node->owner == other)
return true;
break;
}
- case DEPSNODE_CLASS_OPERATION:
+ case DEG_NODE_CLASS_OPERATION:
{
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->owner == other)
@@ -517,15 +497,12 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
const Depsgraph *graph)
{
- if (graph->root_node) {
- deg_debug_graphviz_node(ctx, graph->root_node);
- }
GHASH_FOREACH_BEGIN (DepsNode *, node, graph->id_hash)
{
deg_debug_graphviz_node(ctx, node);
}
GHASH_FOREACH_END();
- TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ TimeSourceDepsNode *time_source = graph->find_time_source();
if (time_source != NULL) {
deg_debug_graphviz_node(ctx, time_source);
}
@@ -546,7 +523,7 @@ static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
}
GHASH_FOREACH_END();
- TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ TimeSourceDepsNode *time_source = graph->find_time_source();
if (time_source != NULL) {
deg_debug_graphviz_node_relations(ctx, time_source);
}
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 5604044e123..aa21f0995be 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -69,26 +69,22 @@ static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL;
static DEG_EditorUpdateScenePreCb deg_editor_update_scene_pre_cb = NULL;
Depsgraph::Depsgraph()
- : root_node(NULL),
+ : time_source(NULL),
need_update(false),
layers(0)
{
BLI_spin_init(&lock);
id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
- subgraphs = BLI_gset_ptr_new("Depsgraph subgraphs");
entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags");
}
Depsgraph::~Depsgraph()
{
- /* Free root node - it won't have been freed yet... */
clear_id_nodes();
- clear_subgraph_nodes();
BLI_ghash_free(id_hash, NULL, NULL);
- BLI_gset_free(subgraphs, NULL);
BLI_gset_free(entry_tags, NULL);
- if (this->root_node != NULL) {
- OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode);
+ if (time_source != NULL) {
+ OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
}
BLI_spin_end(&lock);
}
@@ -131,7 +127,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
/* Bone - generally, we just want the bone component... */
- *type = DEPSNODE_TYPE_BONE;
+ *type = DEG_NODE_TYPE_BONE;
*subdata = pchan->name;
return true;
@@ -141,7 +137,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
/* armature-level bone, but it ends up going to bone component anyway */
// TODO: the ID in thise case will end up being bArmature, not Object as needed!
- *type = DEPSNODE_TYPE_BONE;
+ *type = DEG_NODE_TYPE_BONE;
*subdata = bone->name;
//*id = ...
@@ -155,7 +151,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
if (BLI_findindex(&ob->constraints, con) != -1) {
/* object transform */
// XXX: for now, we can't address the specific constraint or the constraint stack...
- *type = DEPSNODE_TYPE_TRANSFORM;
+ *type = DEG_NODE_TYPE_TRANSFORM;
return true;
}
else if (ob->pose) {
@@ -163,7 +159,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if (BLI_findindex(&pchan->constraints, con) != -1) {
/* bone transforms */
- *type = DEPSNODE_TYPE_BONE;
+ *type = DEG_NODE_TYPE_BONE;
*subdata = pchan->name;
return true;
}
@@ -178,7 +174,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
* so although we have unique ops for modifiers,
* we can't lump them together
*/
- *type = DEPSNODE_TYPE_BONE;
+ *type = DEG_NODE_TYPE_BONE;
//*subdata = md->name;
return true;
@@ -195,14 +191,14 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
strstr(prop_identifier, "scale") ||
strstr(prop_identifier, "matrix_"))
{
- *type = DEPSNODE_TYPE_TRANSFORM;
+ *type = DEG_NODE_TYPE_TRANSFORM;
return true;
}
else if (strstr(prop_identifier, "data")) {
/* We access object.data, most likely a geometry.
* Might be a bone tho..
*/
- *type = DEPSNODE_TYPE_GEOMETRY;
+ *type = DEG_NODE_TYPE_GEOMETRY;
return true;
}
}
@@ -212,21 +208,21 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
/* ShapeKeys are currently handled as geometry on the geometry that owns it */
*id = key->from; // XXX
- *type = DEPSNODE_TYPE_PARAMETERS;
+ *type = DEG_NODE_TYPE_PARAMETERS;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
Sequence *seq = (Sequence *)ptr->data;
/* Sequencer strip */
- *type = DEPSNODE_TYPE_SEQUENCER;
+ *type = DEG_NODE_TYPE_SEQUENCER;
*subdata = seq->name; // xxx?
return true;
}
if (prop) {
/* All unknown data effectively falls under "parameter evaluation" */
- *type = DEPSNODE_TYPE_PARAMETERS;
+ *type = DEG_NODE_TYPE_PARAMETERS;
return true;
}
@@ -263,72 +259,18 @@ static void id_node_deleter(void *value)
OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
}
-RootDepsNode *Depsgraph::add_root_node()
+TimeSourceDepsNode *Depsgraph::add_time_source()
{
- if (!root_node) {
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_ROOT);
- root_node = (RootDepsNode *)factory->create_node(NULL, "", "Root (Scene)");
+ if (time_source == NULL) {
+ DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_TIMESOURCE);
+ time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", "Time Source");
}
- return root_node;
+ return time_source;
}
-TimeSourceDepsNode *Depsgraph::find_time_source(const ID *id) const
+TimeSourceDepsNode *Depsgraph::find_time_source() const
{
- /* Search for one attached to a particular ID? */
- if (id) {
- /* Check if it was added as a component
- * (as may be done for subgraphs needing timeoffset).
- */
- IDDepsNode *id_node = find_id_node(id);
- if (id_node) {
- // XXX: review this
-// return id_node->find_component(DEPSNODE_TYPE_TIMESOURCE);
- }
- BLI_assert(!"Not implemented yet");
- }
- else {
- /* Use "official" timesource. */
- return root_node->time_source;
- }
- return NULL;
-}
-
-SubgraphDepsNode *Depsgraph::add_subgraph_node(const ID *id)
-{
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_SUBGRAPH);
- SubgraphDepsNode *subgraph_node =
- (SubgraphDepsNode *)factory->create_node(id, "", id->name + 2);
-
- /* Add to subnodes list. */
- BLI_gset_insert(subgraphs, subgraph_node);
-
- /* if there's an ID associated, add to ID-nodes lookup too */
- if (id) {
-#if 0
- /* XXX subgraph node is NOT a true IDDepsNode - what is this supposed to do? */
- // TODO: what to do if subgraph's ID has already been added?
- BLI_assert(!graph->find_id_node(id));
- graph->id_hash[id] = this;
-#endif
- }
-
- return subgraph_node;
-}
-
-void Depsgraph::remove_subgraph_node(SubgraphDepsNode *subgraph_node)
-{
- BLI_gset_remove(subgraphs, subgraph_node, NULL);
- OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode);
-}
-
-void Depsgraph::clear_subgraph_nodes()
-{
- GSET_FOREACH_BEGIN(SubgraphDepsNode *, subgraph_node, subgraphs)
- {
- OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode);
- }
- GSET_FOREACH_END();
- BLI_gset_clear(subgraphs, NULL);
+ return time_source;
}
IDDepsNode *Depsgraph::find_id_node(const ID *id) const
@@ -340,7 +282,7 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name)
{
IDDepsNode *id_node = find_id_node(id);
if (!id_node) {
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_ID_REF);
+ DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_ID_REF);
id_node = (IDDepsNode *)factory->create_node(id, "", name);
id->tag |= LIB_TAG_DOIT;
/* register */
@@ -349,16 +291,6 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name)
return id_node;
}
-void Depsgraph::remove_id_node(const ID *id)
-{
- IDDepsNode *id_node = find_id_node(id);
- if (id_node) {
- /* unregister */
- BLI_ghash_remove(id_hash, id, NULL, NULL);
- OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
- }
-}
-
void Depsgraph::clear_id_nodes()
{
BLI_ghash_clear(id_hash, NULL, id_node_deleter);
@@ -367,15 +299,14 @@ void Depsgraph::clear_id_nodes()
/* Add new relationship between two nodes. */
DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
OperationDepsNode *to,
- eDepsRelation_Type type,
const char *description)
{
/* Create new relation, and add it to the graph. */
- DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description);
+ DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description);
/* TODO(sergey): Find a better place for this. */
#ifdef WITH_OPENSUBDIV
ComponentDepsNode *comp_node = from->owner;
- if (comp_node->type == DEPSNODE_TYPE_GEOMETRY) {
+ if (comp_node->type == DEG_NODE_TYPE_GEOMETRY) {
IDDepsNode *id_to = to->owner->owner;
IDDepsNode *id_from = from->owner->owner;
if (id_to != id_from && (id_to->id->tag & LIB_TAG_ID_RECALC_ALL)) {
@@ -391,11 +322,10 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
/* Add new relation between two nodes */
DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to,
- eDepsRelation_Type type,
const char *description)
{
/* Create new relation, and add it to the graph. */
- DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description);
+ DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description);
return rel;
}
@@ -404,12 +334,10 @@ DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to,
DepsRelation::DepsRelation(DepsNode *from,
DepsNode *to,
- eDepsRelation_Type type,
const char *description)
: from(from),
to(to),
name(description),
- type(type),
flag(0)
{
#ifndef NDEBUG
@@ -472,11 +400,10 @@ void Depsgraph::add_entry_tag(OperationDepsNode *node)
void Depsgraph::clear_all_nodes()
{
clear_id_nodes();
- clear_subgraph_nodes();
BLI_ghash_clear(id_hash, NULL, NULL);
- if (this->root_node) {
- OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode);
- root_node = NULL;
+ if (time_source != NULL) {
+ OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
+ time_source = NULL;
}
}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index e668facd645..f72f8dd9311 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -49,10 +49,8 @@ struct PropertyRNA;
namespace DEG {
struct DepsNode;
-struct RootDepsNode;
struct TimeSourceDepsNode;
struct IDDepsNode;
-struct SubgraphDepsNode;
struct ComponentDepsNode;
struct OperationDepsNode;
@@ -79,12 +77,10 @@ struct DepsRelation {
/* relationship attributes */
const char *name; /* label for debugging */
- eDepsRelation_Type type; /* type */
int flag; /* (eDepsRelation_Flag) */
DepsRelation(DepsNode *from,
DepsNode *to,
- eDepsRelation_Type type,
const char *description);
~DepsRelation();
@@ -111,28 +107,20 @@ struct Depsgraph {
*/
DepsNode *find_node_from_pointer(const PointerRNA *ptr, const PropertyRNA *prop) const;
- RootDepsNode *add_root_node();
-
- TimeSourceDepsNode *find_time_source(const ID *id = NULL) const;
-
- SubgraphDepsNode *add_subgraph_node(const ID *id);
- void remove_subgraph_node(SubgraphDepsNode *subgraph_node);
- void clear_subgraph_nodes();
+ TimeSourceDepsNode *add_time_source();
+ TimeSourceDepsNode *find_time_source() const;
IDDepsNode *find_id_node(const ID *id) const;
IDDepsNode *add_id_node(ID *id, const char *name = "");
- void remove_id_node(const ID *id);
void clear_id_nodes();
/* Add new relationship between two nodes. */
DepsRelation *add_new_relation(OperationDepsNode *from,
OperationDepsNode *to,
- eDepsRelation_Type type,
const char *description);
DepsRelation *add_new_relation(DepsNode *from,
DepsNode *to,
- eDepsRelation_Type type,
const char *description);
/* Tag a specific node as needing updates. */
@@ -147,11 +135,8 @@ struct Depsgraph {
* (for quick lookups). */
GHash *id_hash;
- /* "root" node - the one where all evaluation enters from. */
- RootDepsNode *root_node;
-
- /* Subgraphs referenced in tree. */
- GSet *subgraphs;
+ /* Top-level time source node. */
+ TimeSourceDepsNode *time_source;
/* Indicates whether relations needs to be updated. */
bool need_update;
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 3a69469053c..47bf5e7ecbb 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -34,12 +34,6 @@
// #define DEBUG_TIME
-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"
@@ -48,17 +42,22 @@ extern "C" {
# include "PIL_time_utildefines.h"
#endif
+extern "C" {
+#include "DNA_cachefile_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_force.h"
+
#include "BKE_main.h"
#include "BKE_collision.h"
#include "BKE_effect.h"
#include "BKE_modifier.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
-
#include "builder/deg_builder.h"
#include "builder/deg_builder_cycle.h"
#include "builder/deg_builder_nodes.h"
@@ -81,29 +80,29 @@ static DEG::eDepsNode_Type deg_build_scene_component_type(
eDepsSceneComponentType component)
{
switch (component) {
- case DEG_SCENE_COMP_PARAMETERS: return DEG::DEPSNODE_TYPE_PARAMETERS;
- case DEG_SCENE_COMP_ANIMATION: return DEG::DEPSNODE_TYPE_ANIMATION;
- case DEG_SCENE_COMP_SEQUENCER: return DEG::DEPSNODE_TYPE_SEQUENCER;
+ case DEG_SCENE_COMP_PARAMETERS: return DEG::DEG_NODE_TYPE_PARAMETERS;
+ case DEG_SCENE_COMP_ANIMATION: return DEG::DEG_NODE_TYPE_ANIMATION;
+ case DEG_SCENE_COMP_SEQUENCER: return DEG::DEG_NODE_TYPE_SEQUENCER;
}
- return DEG::DEPSNODE_TYPE_UNDEFINED;
+ return DEG::DEG_NODE_TYPE_UNDEFINED;
}
static DEG::eDepsNode_Type deg_build_object_component_type(
eDepsObjectComponentType component)
{
switch (component) {
- case DEG_OB_COMP_PARAMETERS: return DEG::DEPSNODE_TYPE_PARAMETERS;
- case DEG_OB_COMP_PROXY: return DEG::DEPSNODE_TYPE_PROXY;
- case DEG_OB_COMP_ANIMATION: return DEG::DEPSNODE_TYPE_ANIMATION;
- case DEG_OB_COMP_TRANSFORM: return DEG::DEPSNODE_TYPE_TRANSFORM;
- case DEG_OB_COMP_GEOMETRY: return DEG::DEPSNODE_TYPE_GEOMETRY;
- case DEG_OB_COMP_EVAL_POSE: return DEG::DEPSNODE_TYPE_EVAL_POSE;
- 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;
+ case DEG_OB_COMP_PARAMETERS: return DEG::DEG_NODE_TYPE_PARAMETERS;
+ case DEG_OB_COMP_PROXY: return DEG::DEG_NODE_TYPE_PROXY;
+ case DEG_OB_COMP_ANIMATION: return DEG::DEG_NODE_TYPE_ANIMATION;
+ case DEG_OB_COMP_TRANSFORM: return DEG::DEG_NODE_TYPE_TRANSFORM;
+ case DEG_OB_COMP_GEOMETRY: return DEG::DEG_NODE_TYPE_GEOMETRY;
+ case DEG_OB_COMP_EVAL_POSE: return DEG::DEG_NODE_TYPE_EVAL_POSE;
+ case DEG_OB_COMP_BONE: return DEG::DEG_NODE_TYPE_BONE;
+ case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEG_NODE_TYPE_EVAL_PARTICLES;
+ case DEG_OB_COMP_SHADING: return DEG::DEG_NODE_TYPE_SHADING;
+ case DEG_OB_COMP_CACHE: return DEG::DEG_NODE_TYPE_CACHE;
}
- return DEG::DEPSNODE_TYPE_UNDEFINED;
+ return DEG::DEG_NODE_TYPE_UNDEFINED;
}
static DEG::DepsNodeHandle *get_handle(DepsNodeHandle *handle)
@@ -121,7 +120,6 @@ void DEG_add_scene_relation(DepsNodeHandle *handle,
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
- DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
description);
}
@@ -135,7 +133,6 @@ void DEG_add_object_relation(DepsNodeHandle *handle,
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
- DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
description);
}
@@ -149,7 +146,6 @@ void DEG_add_object_cache_relation(DepsNodeHandle *handle,
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
- DEG::DEPSREL_TYPE_CACHE,
description);
}
@@ -167,10 +163,16 @@ void DEG_add_bone_relation(DepsNodeHandle *handle,
*/
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
- DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
description);
}
+struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *handle)
+{
+ DEG::DepsNodeHandle *deg_handle = get_handle(handle);
+ DEG::DepsgraphRelationBuilder *relation_builder = deg_handle->builder;
+ return reinterpret_cast<Depsgraph *>(relation_builder->getGraph());
+}
+
void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
@@ -205,30 +207,14 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
/* 1) Generate all the nodes in the graph first */
DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
- /* create root node for scene first
- * - this way it should be the first in the graph,
- * reflecting its role as the entrypoint
- */
node_builder.begin_build(bmain);
- node_builder.add_root_node();
node_builder.build_scene(bmain, scene);
/* 2) Hook up relationships between operations - to determine evaluation
* order.
*/
DEG::DepsgraphRelationBuilder relation_builder(deg_graph);
- /* Hook scene up to the root node as entrypoint to graph. */
- /* XXX what does this relation actually mean?
- * it doesnt add any operations anyway and is not clear what part of the
- * scene is to be connected.
- */
relation_builder.begin_build(bmain);
-#if 0
- relation_builder.add_relation(RootKey(),
- IDKey(scene),
- DEPSREL_TYPE_ROOT_TO_ACTIVE,
- "Root to Active Scene");
-#endif
relation_builder.build_scene(bmain, scene);
/* Detect and solve cycles. */
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index d3b48930779..388b692d742 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -35,11 +35,11 @@
extern "C" {
#include "DNA_scene_types.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/eval/deg_eval_debug.h"
#include "intern/depsgraph_intern.h"
@@ -165,7 +165,7 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
return false;
}
foreach (DEG::DepsRelation *rel, node->outlinks) {
- if (rel->to->type == DEG::DEPSNODE_TYPE_OPERATION) {
+ if (rel->to->type == DEG::DEG_NODE_TYPE_OPERATION) {
DEG::OperationDepsNode *to = (DEG::OperationDepsNode *)rel->to;
BLI_assert(to->num_links_pending < to->inlinks.size());
++to->num_links_pending;
@@ -177,7 +177,7 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
foreach (DEG::OperationDepsNode *node, deg_graph->operations) {
int num_links_pending = 0;
foreach (DEG::DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEG::DEPSNODE_TYPE_OPERATION) {
+ if (rel->from->type == DEG::DEG_NODE_TYPE_OPERATION) {
++num_links_pending;
}
}
@@ -232,7 +232,7 @@ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
}
GHASH_FOREACH_END();
- DEG::TimeSourceDepsNode *time_source = deg_graph->find_time_source(NULL);
+ DEG::TimeSourceDepsNode *time_source = deg_graph->find_time_source();
if (time_source != NULL) {
tot_rels += time_source->inlinks.size();
}
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index c41f28b07e8..85a0d336d28 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -32,17 +32,17 @@
#include "MEM_guardedalloc.h"
-extern "C" {
-#include "DNA_scene_types.h"
-
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+extern "C" {
+#include "DNA_scene_types.h"
+
#include "BKE_depsgraph.h"
#include "BKE_scene.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
-} /* extern "C" */
#include "intern/eval/deg_eval.h"
#include "intern/eval/deg_eval_flush.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 7f2f6a65f5e..e58a7a32407 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -35,9 +35,9 @@
extern "C" {
#include "BKE_idcode.h"
#include "BKE_main.h"
+} /* extern "C" */
#include "DEG_depsgraph_query.h"
-} /* extern "C" */
#include "intern/depsgraph_intern.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 8c4c0b8c8a5..f73bb65e5dc 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -34,16 +34,16 @@
#include <cstring> /* required for memset */
#include <queue>
-extern "C" {
#include "BLI_utildefines.h"
+#include "BLI_task.h"
+#include "BLI_listbase.h"
+extern "C" {
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
-#include "BLI_task.h"
-#include "BLI_listbase.h"
#include "BKE_idcode.h"
#include "BKE_library.h"
@@ -53,9 +53,9 @@ extern "C" {
#define new new_
#include "BKE_screen.h"
#undef new
+} /* extern "C" */
#include "DEG_depsgraph.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/eval/deg_eval_flush.h"
@@ -109,7 +109,7 @@ void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
* nodes for update after relations update and after layer
* visibility changes.
*/
- short idtype = GS(id->name);
+ ID_Type idtype = GS(id->name);
if (idtype == ID_OB) {
Object *object = (Object *)id;
object->recalc |= (flag & OB_RECALC_ALL);
@@ -337,7 +337,7 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
{
id_node->tag_update(graph);
DEG::ComponentDepsNode *anim_comp =
- id_node->find_component(DEG::DEPSNODE_TYPE_ANIMATION);
+ id_node->find_component(DEG::DEG_NODE_TYPE_ANIMATION);
if (anim_comp != NULL && object->recalc & OB_RECALC_TIME) {
anim_comp->tag_update(graph);
}
@@ -347,6 +347,12 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
GHASH_FOREACH_END();
}
scene->lay_updated |= graph->layers;
+ /* If graph is tagged for update, we don't need to bother with updates here,
+ * nodes will be re-created.
+ */
+ if (graph->need_update) {
+ return;
+ }
/* Special trick to get local view to work. */
LINKLIST_FOREACH (Base *, base, &scene->base) {
Object *object = base->object;
diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
index 39c189629f2..05a144900f9 100644
--- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc
+++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
@@ -32,12 +32,11 @@
#include <cstdlib> // for BLI_assert()
-extern "C" {
+
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "DEG_depsgraph.h"
-} /* extern "C" */
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
@@ -98,24 +97,17 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
#define STRINGIFY_OPCODE(name) case DEG_OPCODE_##name: return #name
STRINGIFY_OPCODE(OPERATION);
STRINGIFY_OPCODE(PLACEHOLDER);
- STRINGIFY_OPCODE(NOOP);
STRINGIFY_OPCODE(ANIMATION);
STRINGIFY_OPCODE(DRIVER);
- //STRINGIFY_OPCODE(PROXY);
STRINGIFY_OPCODE(TRANSFORM_LOCAL);
STRINGIFY_OPCODE(TRANSFORM_PARENT);
STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS);
- //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS_INIT);
- //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINT);
- //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS_DONE);
STRINGIFY_OPCODE(RIGIDBODY_REBUILD);
STRINGIFY_OPCODE(RIGIDBODY_SIM);
STRINGIFY_OPCODE(TRANSFORM_RIGIDBODY);
STRINGIFY_OPCODE(TRANSFORM_FINAL);
STRINGIFY_OPCODE(OBJECT_UBEREVAL);
STRINGIFY_OPCODE(GEOMETRY_UBEREVAL);
- STRINGIFY_OPCODE(GEOMETRY_MODIFIER);
- STRINGIFY_OPCODE(GEOMETRY_PATH);
STRINGIFY_OPCODE(POSE_INIT);
STRINGIFY_OPCODE(POSE_DONE);
STRINGIFY_OPCODE(POSE_IK_SOLVER);
@@ -123,12 +115,10 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
STRINGIFY_OPCODE(BONE_LOCAL);
STRINGIFY_OPCODE(BONE_POSE_PARENT);
STRINGIFY_OPCODE(BONE_CONSTRAINTS);
- //STRINGIFY_OPCODE(BONE_CONSTRAINTS_INIT);
- //STRINGIFY_OPCODE(BONE_CONSTRAINT);
- //STRINGIFY_OPCODE(BONE_CONSTRAINTS_DONE);
STRINGIFY_OPCODE(BONE_READY);
STRINGIFY_OPCODE(BONE_DONE);
STRINGIFY_OPCODE(PSYS_EVAL);
+ STRINGIFY_OPCODE(PSYS_EVAL_INIT);
case DEG_NUM_OPCODES: return "SpecialCase";
#undef STRINGIFY_OPCODE
diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h
index c9c4329769d..6c0e3839b39 100644
--- a/source/blender/depsgraph/intern/depsgraph_types.h
+++ b/source/blender/depsgraph/intern/depsgraph_types.h
@@ -67,74 +67,66 @@ typedef enum eDepsNode_Class {
/* Types generally unassociated with user-visible entities,
* but needed for graph functioning.
*/
- DEPSNODE_CLASS_GENERIC = 0,
+ DEG_NODE_CLASS_GENERIC = 0,
/* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring
* certain types of evaluation behavior.
*/
- DEPSNODE_CLASS_COMPONENT = 1,
+ DEG_NODE_CLASS_COMPONENT = 1,
/* [Inner Node] A glorified function-pointer/callback for scheduling up
* evaluation operations for components, subject to relationship
* requirements.
*/
- DEPSNODE_CLASS_OPERATION = 2,
+ DEG_NODE_CLASS_OPERATION = 2,
} eDepsNode_Class;
/* Types of Nodes */
typedef enum eDepsNode_Type {
/* Fallback type for invalid return value */
- DEPSNODE_TYPE_UNDEFINED = -1,
+ DEG_NODE_TYPE_UNDEFINED = -1,
/* Inner Node (Operation) */
- DEPSNODE_TYPE_OPERATION = 0,
+ DEG_NODE_TYPE_OPERATION = 0,
/* **** Generic Types **** */
- /* "Current Scene" - basically whatever kicks off the evaluation process. */
- DEPSNODE_TYPE_ROOT,
/* Time-Source */
- DEPSNODE_TYPE_TIMESOURCE,
+ DEG_NODE_TYPE_TIMESOURCE,
/* ID-Block reference - used as landmarks/collection point for components,
* but not usually part of main graph.
*/
- DEPSNODE_TYPE_ID_REF,
- /* Isolated sub-graph - used for keeping instanced data separate from
- * instances using them.
- */
- DEPSNODE_TYPE_SUBGRAPH,
+ DEG_NODE_TYPE_ID_REF,
/* **** Outer Types **** */
/* Parameters Component - Default when nothing else fits
* (i.e. just SDNA property setting).
*/
- DEPSNODE_TYPE_PARAMETERS,
- /* Generic "Proxy-Inherit" Component
- * XXX: Also for instancing of subgraphs?
- */
- DEPSNODE_TYPE_PROXY,
+ DEG_NODE_TYPE_PARAMETERS,
+ /* Generic "Proxy-Inherit" Component. */
+ DEG_NODE_TYPE_PROXY,
/* Animation Component
*
* XXX: merge in with parameters?
*/
- DEPSNODE_TYPE_ANIMATION,
+ DEG_NODE_TYPE_ANIMATION,
/* Transform Component (Parenting/Constraints) */
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
/* Geometry Component (DerivedMesh/Displist) */
- DEPSNODE_TYPE_GEOMETRY,
+ DEG_NODE_TYPE_GEOMETRY,
/* Sequencer Component (Scene Only) */
- DEPSNODE_TYPE_SEQUENCER,
+ DEG_NODE_TYPE_SEQUENCER,
/* **** Evaluation-Related Outer Types (with Subdata) **** */
/* Pose Component - Owner/Container of Bones Eval */
- DEPSNODE_TYPE_EVAL_POSE,
+ DEG_NODE_TYPE_EVAL_POSE,
/* Bone Component - Child/Subcomponent of Pose */
- DEPSNODE_TYPE_BONE,
+ DEG_NODE_TYPE_BONE,
/* Particle Systems Component */
- DEPSNODE_TYPE_EVAL_PARTICLES,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
/* Material Shading Component */
- DEPSNODE_TYPE_SHADING,
+ DEG_NODE_TYPE_SHADING,
/* Cache Component */
- DEPSNODE_TYPE_CACHE,
+ DEG_NODE_TYPE_CACHE,
} eDepsNode_Type;
/* Identifiers for common operations (as an enum). */
@@ -147,8 +139,6 @@ typedef enum eDepsOperation_Code {
// XXX: Placeholder while porting depsgraph code
DEG_OPCODE_PLACEHOLDER,
- DEG_OPCODE_NOOP,
-
/* Animation, Drivers, etc. ------------------------ */
/* NLA + Action */
@@ -157,9 +147,6 @@ typedef enum eDepsOperation_Code {
/* Driver */
DEG_OPCODE_DRIVER,
- /* Proxy Inherit? */
- //DEG_OPCODE_PROXY,
-
/* Transform --------------------------------------- */
/* Transform entry point - local transforms only */
@@ -170,9 +157,6 @@ typedef enum eDepsOperation_Code {
/* Constraints */
DEG_OPCODE_TRANSFORM_CONSTRAINTS,
- //DEG_OPCODE_TRANSFORM_CONSTRAINTS_INIT,
- //DEG_OPCODE_TRANSFORM_CONSTRAINT,
- //DEG_OPCODE_TRANSFORM_CONSTRAINTS_DONE,
/* Rigidbody Sim - Perform Sim */
DEG_OPCODE_RIGIDBODY_REBUILD,
@@ -192,12 +176,6 @@ typedef enum eDepsOperation_Code {
/* XXX: Placeholder - UberEval */
DEG_OPCODE_GEOMETRY_UBEREVAL,
- /* Modifier */
- DEG_OPCODE_GEOMETRY_MODIFIER,
-
- /* Curve Objects - Path Calculation (used for path-following tools, */
- DEG_OPCODE_GEOMETRY_PATH,
-
/* Pose -------------------------------------------- */
/* Init IK Trees, etc. */
@@ -220,9 +198,6 @@ typedef enum eDepsOperation_Code {
/* Constraints */
DEG_OPCODE_BONE_CONSTRAINTS,
- //DEG_OPCODE_BONE_CONSTRAINTS_INIT,
- //DEG_OPCODE_BONE_CONSTRAINT,
- //DEG_OPCODE_BONE_CONSTRAINTS_DONE,
/* Bone transforms are ready
*
@@ -241,6 +216,7 @@ typedef enum eDepsOperation_Code {
/* Particles --------------------------------------- */
/* XXX: placeholder - Particle System eval */
+ DEG_OPCODE_PSYS_EVAL_INIT,
DEG_OPCODE_PSYS_EVAL,
DEG_NUM_OPCODES,
@@ -258,83 +234,4 @@ protected:
/* String defines for these opcodes, defined in depsgraph_type_defines.cpp */
extern DepsOperationStringifier DEG_OPNAMES;
-/* Type of operation */
-typedef enum eDepsOperation_Type {
- /* **** Primary operation types **** */
-
- /* Initialise evaluation data */
- DEPSOP_TYPE_INIT = 0,
- /* Standard evaluation step */
- DEPSOP_TYPE_EXEC = 1,
- /* Cleanup evaluation data + flush results */
- DEPSOP_TYPE_POST = 2,
-
- /* **** Additional operation types **** */
- /* Indicator for outputting a temporary result that other components
- * can use. // XXX?
- */
- DEPSOP_TYPE_OUT = 3,
- /* Indicator for things like IK Solvers and Rigidbody Sim steps which
- * modify final results of separate entities at once.
- */
- DEPSOP_TYPE_SIM = 4,
- /* Rebuild internal evaluation data - used for Rigidbody Reset and
- * Armature Rebuild-On-Load.
- */
- DEPSOP_TYPE_REBUILD = 5,
-} eDepsOperation_Type;
-
-/* Types of relationships between nodes
- *
- * This is used to provide additional hints to use when filtering
- * the graph, so that we can go without doing more extensive
- * data-level checks...
- */
-typedef enum eDepsRelation_Type {
- /* relationship type unknown/irrelevant */
- DEPSREL_TYPE_STANDARD = 0,
-
- /* root -> active scene or entity (screen, image, etc.) */
- DEPSREL_TYPE_ROOT_TO_ACTIVE,
-
- /* general datablock dependency */
- DEPSREL_TYPE_DATABLOCK,
-
- /* time dependency */
- DEPSREL_TYPE_TIME,
-
- /* component depends on results of another */
- DEPSREL_TYPE_COMPONENT_ORDER,
-
- /* relationship is just used to enforce ordering of operations
- * (e.g. "init()" callback done before "exec() and "cleanup()")
- */
- DEPSREL_TYPE_OPERATION,
-
- /* relationship results from a property driver affecting property */
- DEPSREL_TYPE_DRIVER,
-
- /* relationship is something driver depends on */
- DEPSREL_TYPE_DRIVER_TARGET,
-
- /* relationship is used for transform stack
- * (e.g. parenting, user transforms, constraints)
- */
- DEPSREL_TYPE_TRANSFORM,
-
- /* relationship is used for geometry evaluation
- * (e.g. metaball "motherball" or modifiers)
- */
- DEPSREL_TYPE_GEOMETRY_EVAL,
-
- /* relationship is used to trigger a post-change validity updates */
- DEPSREL_TYPE_UPDATE,
-
- /* 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 e739bc9dbb5..98b10718404 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -34,16 +34,16 @@
#include "PIL_time.h"
-extern "C" {
#include "BLI_utildefines.h"
#include "BLI_task.h"
#include "BLI_ghash.h"
+extern "C" {
#include "BKE_depsgraph.h"
#include "BKE_global.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
-} /* extern "C" */
#include "atomic_ops.h"
@@ -126,7 +126,9 @@ static void deg_task_run_func(TaskPool *pool,
#endif
}
+ BLI_task_pool_delayed_push_begin(pool, thread_id);
schedule_children(pool, state->graph, node, state->layers, thread_id);
+ BLI_task_pool_delayed_push_end(pool, thread_id);
}
typedef struct CalculatePengindData {
@@ -150,7 +152,7 @@ static void calculate_pending_func(void *data_v, int i)
(node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
{
foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION &&
+ if (rel->from->type == DEG_NODE_TYPE_OPERATION &&
(rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
{
OperationDepsNode *from = (OperationDepsNode *)rel->from;
@@ -195,7 +197,7 @@ static void calculate_eval_priority(OperationDepsNode *node)
foreach (DepsRelation *rel, node->outlinks) {
OperationDepsNode *to = (OperationDepsNode *)rel->to;
- BLI_assert(to->type == DEPSNODE_TYPE_OPERATION);
+ BLI_assert(to->type == DEG_NODE_TYPE_OPERATION);
calculate_eval_priority(to);
node->eval_priority += to->eval_priority;
}
@@ -263,7 +265,7 @@ static void schedule_children(TaskPool *pool,
{
foreach (DepsRelation *rel, node->outlinks) {
OperationDepsNode *child = (OperationDepsNode *)rel->to;
- BLI_assert(child->type == DEPSNODE_TYPE_OPERATION);
+ BLI_assert(child->type == DEG_NODE_TYPE_OPERATION);
if (child->scheduled) {
/* Happens when having cyclic dependencies. */
continue;
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_debug.cc b/source/blender/depsgraph/intern/eval/deg_eval_debug.cc
index 060544a4407..23f4adbaacd 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_debug.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_debug.cc
@@ -34,16 +34,16 @@
#include <cstring> /* required for STREQ later on. */
-extern "C" {
#include "BLI_listbase.h"
#include "BLI_ghash.h"
-#include "DEG_depsgraph_debug.h"
-
+extern "C" {
#include "WM_api.h"
#include "WM_types.h"
} /* extern "C" */
+#include "DEG_depsgraph_debug.h"
+
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index e10f86f6e95..c230ab4c8fd 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -35,16 +35,16 @@
// TODO(sergey): Use some sort of wrapper.
#include <deque>
-extern "C" {
-#include "DNA_object_types.h"
-
#include "BLI_utildefines.h"
#include "BLI_task.h"
#include "BLI_ghash.h"
-#include "DEG_depsgraph.h"
+extern "C" {
+#include "DNA_object_types.h"
} /* extern "C" */
+#include "DEG_depsgraph.h"
+
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -139,18 +139,18 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
IDDepsNode *id_node = comp_node->owner;
ID *id = id_node->id;
- if(id_node->done == 0) {
+ 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) {
+ if (comp_node->done == 0) {
Object *object = NULL;
if (GS(id->name) == ID_OB) {
object = (Object *)id;
- if(id_node->done == 0) {
+ if (id_node->done == 0) {
++num_flushed_objects;
}
}
@@ -164,14 +164,30 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
* 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;
+ switch (comp_node->type) {
+ case DEG_NODE_TYPE_UNDEFINED:
+ case DEG_NODE_TYPE_OPERATION:
+ case DEG_NODE_TYPE_TIMESOURCE:
+ case DEG_NODE_TYPE_ID_REF:
+ case DEG_NODE_TYPE_PARAMETERS:
+ case DEG_NODE_TYPE_SEQUENCER:
+ /* Ignore, does not translate to object component. */
+ break;
+ case DEG_NODE_TYPE_ANIMATION:
+ object->recalc |= OB_RECALC_TIME;
+ break;
+ case DEG_NODE_TYPE_TRANSFORM:
+ object->recalc |= OB_RECALC_OB;
+ break;
+ case DEG_NODE_TYPE_GEOMETRY:
+ case DEG_NODE_TYPE_EVAL_POSE:
+ case DEG_NODE_TYPE_BONE:
+ case DEG_NODE_TYPE_EVAL_PARTICLES:
+ case DEG_NODE_TYPE_SHADING:
+ case DEG_NODE_TYPE_CACHE:
+ case DEG_NODE_TYPE_PROXY:
+ object->recalc |= OB_RECALC_DATA;
+ break;
}
}
}
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc
index b1d5b538e25..a15317586c1 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node.cc
@@ -41,9 +41,9 @@ extern "C" {
#include "DNA_anim_types.h"
#include "BKE_animsys.h"
+}
#include "DEG_depsgraph.h"
-}
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -60,12 +60,12 @@ namespace DEG {
DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname)
{
this->type = type;
- if (type == DEPSNODE_TYPE_OPERATION)
- this->tclass = DEPSNODE_CLASS_OPERATION;
- else if (type < DEPSNODE_TYPE_PARAMETERS)
- this->tclass = DEPSNODE_CLASS_GENERIC;
+ if (type == DEG_NODE_TYPE_OPERATION)
+ this->tclass = DEG_NODE_CLASS_OPERATION;
+ else if (type < DEG_NODE_TYPE_PARAMETERS)
+ this->tclass = DEG_NODE_CLASS_GENERIC;
else
- this->tclass = DEPSNODE_CLASS_COMPONENT;
+ this->tclass = DEG_NODE_CLASS_COMPONENT;
this->tname = tname;
}
@@ -109,34 +109,9 @@ void TimeSourceDepsNode::tag_update(Depsgraph *graph)
}
}
-
-/* Root Node ============================================== */
-
-RootDepsNode::RootDepsNode() : scene(NULL), time_source(NULL)
-{
-}
-
-RootDepsNode::~RootDepsNode()
-{
- OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
-}
-
-TimeSourceDepsNode *RootDepsNode::add_time_source(const char *name)
-{
- if (!time_source) {
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_TIMESOURCE);
- time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", name);
- /*time_source->owner = this;*/ // XXX
- }
- return time_source;
-}
-
-DEG_DEPSNODE_DEFINE(RootDepsNode, DEPSNODE_TYPE_ROOT, "Root DepsNode");
-static DepsNodeFactoryImpl<RootDepsNode> DNTI_ROOT;
-
/* Time Source Node ======================================= */
-DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEPSNODE_TYPE_TIMESOURCE, "Time Source");
+DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEG_NODE_TYPE_TIMESOURCE, "Time Source");
static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
/* ID Node ================================================ */
@@ -210,8 +185,9 @@ void IDDepsNode::init(const ID *id, const char *UNUSED(subdata))
/* Free 'id' node. */
IDDepsNode::~IDDepsNode()
{
- clear_components();
- BLI_ghash_free(components, id_deps_node_hash_key_free, NULL);
+ BLI_ghash_free(components,
+ id_deps_node_hash_key_free,
+ id_deps_node_hash_value_free);
}
ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
@@ -237,33 +213,13 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
return comp_node;
}
-void IDDepsNode::remove_component(eDepsNode_Type type, const char *name)
-{
- ComponentDepsNode *comp_node = find_component(type, name);
- if (comp_node) {
- /* Unregister. */
- ComponentIDKey key(type, name);
- BLI_ghash_remove(components,
- &key,
- id_deps_node_hash_key_free,
- id_deps_node_hash_value_free);
- }
-}
-
-void IDDepsNode::clear_components()
-{
- BLI_ghash_clear(components,
- id_deps_node_hash_key_free,
- id_deps_node_hash_value_free);
-}
-
void IDDepsNode::tag_update(Depsgraph *graph)
{
GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
{
/* TODO(sergey): What about drievrs? */
- bool do_component_tag = comp_node->type != DEPSNODE_TYPE_ANIMATION;
- if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
+ bool do_component_tag = comp_node->type != DEG_NODE_TYPE_ANIMATION;
+ if (comp_node->type == DEG_NODE_TYPE_ANIMATION) {
AnimData *adt = BKE_animdata_from_id(id);
/* Animation data might be null if relations are tagged for update. */
if (adt != NULL && (adt->recalc & ADT_RECALC_ANIM)) {
@@ -286,46 +242,13 @@ void IDDepsNode::finalize_build()
GHASH_FOREACH_END();
}
-DEG_DEPSNODE_DEFINE(IDDepsNode, DEPSNODE_TYPE_ID_REF, "ID Node");
+DEG_DEPSNODE_DEFINE(IDDepsNode, DEG_NODE_TYPE_ID_REF, "ID Node");
static DepsNodeFactoryImpl<IDDepsNode> DNTI_ID_REF;
-/* Subgraph Node ========================================== */
-
-/* Initialize 'subgraph' node - from pointer data given. */
-void SubgraphDepsNode::init(const ID *id, const char *UNUSED(subdata))
-{
- /* Store ID-ref if provided. */
- this->root_id = (ID *)id;
-
- /* NOTE: graph will need to be added manually,
- * as we don't have any way of passing this down.
- */
-}
-
-/* Free 'subgraph' node */
-SubgraphDepsNode::~SubgraphDepsNode()
-{
- /* Only free if graph not shared, of if this node is the first
- * reference to it...
- */
- // XXX: prune these flags a bit...
- if ((this->flag & SUBGRAPH_FLAG_FIRSTREF) || !(this->flag & SUBGRAPH_FLAG_SHARED)) {
- /* Free the referenced graph. */
- DEG_graph_free(reinterpret_cast< ::Depsgraph* >(graph));
- graph = NULL;
- }
-}
-
-DEG_DEPSNODE_DEFINE(SubgraphDepsNode, DEPSNODE_TYPE_SUBGRAPH, "Subgraph Node");
-static DepsNodeFactoryImpl<SubgraphDepsNode> DNTI_SUBGRAPH;
-
void deg_register_base_depsnodes()
{
- deg_register_node_typeinfo(&DNTI_ROOT);
deg_register_node_typeinfo(&DNTI_TIMESOURCE);
-
deg_register_node_typeinfo(&DNTI_ID_REF);
- deg_register_node_typeinfo(&DNTI_SUBGRAPH);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.h b/source/blender/depsgraph/intern/nodes/deg_node.h
index 7c2f53840b6..9f1b61faf24 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node.h
@@ -127,22 +127,6 @@ struct TimeSourceDepsNode : public DepsNode {
DEG_DEPSNODE_DECLARE;
};
-/* Root Node. */
-struct RootDepsNode : public DepsNode {
- RootDepsNode();
- ~RootDepsNode();
-
- TimeSourceDepsNode *add_time_source(const char *name = "");
-
- /* scene that this corresponds to */
- Scene *scene;
-
- /* Entrypoint node for time-changed. */
- TimeSourceDepsNode *time_source;
-
- DEG_DEPSNODE_DECLARE;
-};
-
/* ID-Block Reference */
struct IDDepsNode : public DepsNode {
struct ComponentIDKey {
@@ -160,8 +144,6 @@ struct IDDepsNode : public DepsNode {
const char *name = "") const;
ComponentDepsNode *add_component(eDepsNode_Type type,
const char *name = "");
- void remove_component(eDepsNode_Type type, const char *name = "");
- void clear_components();
void tag_update(Depsgraph *graph);
@@ -185,41 +167,6 @@ struct IDDepsNode : public DepsNode {
DEG_DEPSNODE_DECLARE;
};
-/* Subgraph Reference. */
-struct SubgraphDepsNode : public DepsNode {
- void init(const ID *id, const char *subdata);
- ~SubgraphDepsNode();
-
- /* Instanced graph. */
- Depsgraph *graph;
-
- /* ID-block at root of subgraph (if applicable). */
- ID *root_id;
-
- /* Number of nodes which use/reference this subgraph - if just 1, it may be
- * possible to merge into main,
- */
- size_t num_users;
-
- /* (eSubgraphRef_Flag) assorted settings for subgraph node. */
- int flag;
-
- DEG_DEPSNODE_DECLARE;
-};
-
-/* Flags for subgraph node */
-typedef enum eSubgraphRef_Flag {
- /* Subgraph referenced is shared with another reference, so shouldn't
- * free on exit.
- */
- SUBGRAPH_FLAG_SHARED = (1 << 0),
-
- /* Node is first reference to subgraph, so it can be freed when we are
- * removed.
- */
- SUBGRAPH_FLAG_FIRSTREF = (1 << 1),
-} eSubgraphRef_Flag;
-
void deg_register_base_depsnodes();
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index 136c66b9516..e87c87813e3 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -33,10 +33,10 @@
#include <stdio.h>
#include <cstring> /* required for STREQ later on. */
-extern "C" {
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+extern "C" {
#include "DNA_object_types.h"
#include "BKE_action.h"
@@ -198,32 +198,20 @@ OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode,
return has_operation(key);
}
-OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+OperationDepsNode *ComponentDepsNode::add_operation(const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
{
OperationDepsNode *op_node = has_operation(opcode, name, name_tag);
if (!op_node) {
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_OPERATION);
+ DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_OPERATION);
op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
/* register opnode in this component's operation set */
OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
BLI_ghash_insert(operations_map, key, op_node);
- /* set as entry/exit node of component (if appropriate) */
- if (optype == DEPSOP_TYPE_INIT) {
- BLI_assert(this->entry_operation == NULL);
- this->entry_operation = op_node;
- }
- else if (optype == DEPSOP_TYPE_POST) {
- // XXX: review whether DEPSOP_TYPE_OUT is better than DEPSOP_TYPE_POST, or maybe have both?
- BLI_assert(this->exit_operation == NULL);
- this->exit_operation = op_node;
- }
-
/* set backlink */
op_node->owner = this;
}
@@ -235,13 +223,24 @@ OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
/* attach extra data */
op_node->evaluate = op;
- op_node->optype = optype;
op_node->opcode = opcode;
op_node->name = name;
return op_node;
}
+void ComponentDepsNode::set_entry_operation(OperationDepsNode *op_node)
+{
+ BLI_assert(entry_operation == NULL);
+ entry_operation = op_node;
+}
+
+void ComponentDepsNode::set_exit_operation(OperationDepsNode *op_node)
+{
+ BLI_assert(exit_operation == NULL);
+ exit_operation = op_node;
+}
+
void ComponentDepsNode::clear_operations()
{
if (operations_map != NULL) {
@@ -336,37 +335,37 @@ void ComponentDepsNode::finalize_build()
/* Parameter Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEPSNODE_TYPE_PARAMETERS, "Parameters Component");
+DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEG_NODE_TYPE_PARAMETERS, "Parameters Component");
static DepsNodeFactoryImpl<ParametersComponentDepsNode> DNTI_PARAMETERS;
/* Animation Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEPSNODE_TYPE_ANIMATION, "Animation Component");
+DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEG_NODE_TYPE_ANIMATION, "Animation Component");
static DepsNodeFactoryImpl<AnimationComponentDepsNode> DNTI_ANIMATION;
/* Transform Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEPSNODE_TYPE_TRANSFORM, "Transform Component");
+DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEG_NODE_TYPE_TRANSFORM, "Transform Component");
static DepsNodeFactoryImpl<TransformComponentDepsNode> DNTI_TRANSFORM;
/* Proxy Component Defines ================================ */
-DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEPSNODE_TYPE_PROXY, "Proxy Component");
+DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEG_NODE_TYPE_PROXY, "Proxy Component");
static DepsNodeFactoryImpl<ProxyComponentDepsNode> DNTI_PROXY;
/* Geometry Component Defines ============================= */
-DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEPSNODE_TYPE_GEOMETRY, "Geometry Component");
+DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEG_NODE_TYPE_GEOMETRY, "Geometry Component");
static DepsNodeFactoryImpl<GeometryComponentDepsNode> DNTI_GEOMETRY;
/* Sequencer Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEPSNODE_TYPE_SEQUENCER, "Sequencer Component");
+DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEG_NODE_TYPE_SEQUENCER, "Sequencer Component");
static DepsNodeFactoryImpl<SequencerComponentDepsNode> DNTI_SEQUENCER;
/* Pose Component ========================================= */
-DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEPSNODE_TYPE_EVAL_POSE, "Pose Eval Component");
+DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEG_NODE_TYPE_EVAL_POSE, "Pose Eval Component");
static DepsNodeFactoryImpl<PoseComponentDepsNode> DNTI_EVAL_POSE;
/* Bone Component ========================================= */
@@ -388,22 +387,22 @@ void BoneComponentDepsNode::init(const ID *id, const char *subdata)
this->pchan = BKE_pose_channel_find_name(ob->pose, subdata);
}
-DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEPSNODE_TYPE_BONE, "Bone Component");
+DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEG_NODE_TYPE_BONE, "Bone Component");
static DepsNodeFactoryImpl<BoneComponentDepsNode> DNTI_BONE;
/* Particles Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEPSNODE_TYPE_EVAL_PARTICLES, "Particles Component");
+DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEG_NODE_TYPE_EVAL_PARTICLES, "Particles Component");
static DepsNodeFactoryImpl<ParticlesComponentDepsNode> DNTI_EVAL_PARTICLES;
/* Shading Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEPSNODE_TYPE_SHADING, "Shading Component");
+DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEG_NODE_TYPE_SHADING, "Shading Component");
static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING;
/* Cache Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEPSNODE_TYPE_CACHE, "Cache Component");
+DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEG_NODE_TYPE_CACHE, "Cache Component");
static DepsNodeFactoryImpl<CacheComponentDepsNode> DNTI_CACHE;
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h
index 969771a29c9..4ef7dad3ac6 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h
@@ -99,12 +99,18 @@ struct ComponentDepsNode : public DepsNode {
* \param op: The operation to perform
* \param name: Identifier for operation - used to find/locate it again
*/
- OperationDepsNode *add_operation(eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ OperationDepsNode *add_operation(const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag);
+ /* Entry/exit operations management.
+ *
+ * Use those instead of direct set since this will perform sanity checks.
+ */
+ void set_entry_operation(OperationDepsNode *op_node);
+ void set_exit_operation(OperationDepsNode *op_node);
+
void clear_operations();
void tag_update(Depsgraph *graph);
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
index cbf397bc7a9..7467264f612 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
@@ -65,7 +65,7 @@ string OperationDepsNode::identifier() const
string OperationDepsNode::full_identifier() const
{
string owner_str = "";
- if (owner->type == DEPSNODE_TYPE_BONE) {
+ if (owner->type == DEG_NODE_TYPE_BONE) {
owner_str = string(owner->owner->name) + "." + owner->name;
}
else {
@@ -84,7 +84,19 @@ void OperationDepsNode::tag_update(Depsgraph *graph)
graph->add_entry_tag(this);
}
-DEG_DEPSNODE_DEFINE(OperationDepsNode, DEPSNODE_TYPE_OPERATION, "Operation");
+void OperationDepsNode::set_as_entry()
+{
+ BLI_assert(owner != NULL);
+ owner->set_entry_operation(this);
+}
+
+void OperationDepsNode::set_as_exit()
+{
+ BLI_assert(owner != NULL);
+ owner->set_exit_operation(this);
+}
+
+DEG_DEPSNODE_DEFINE(OperationDepsNode, DEG_NODE_TYPE_OPERATION, "Operation");
static DepsNodeFactoryImpl<OperationDepsNode> DNTI_OPERATION;
void deg_register_operation_depsnodes()
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.h b/source/blender/depsgraph/intern/nodes/deg_node_operation.h
index 598393054db..1e5c3832d03 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.h
@@ -44,9 +44,6 @@ typedef enum eDepsOperation_Flag {
DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0),
/* node was directly modified, causing need for update */
- /* XXX: intention is to make it easier to tell when we just need to
- * take subgraphs.
- */
DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1),
/* Operation is evaluated using CPython; has GIL and security
@@ -57,8 +54,6 @@ typedef enum eDepsOperation_Flag {
/* Atomic Operation - Base type for all operations */
struct OperationDepsNode : public DepsNode {
-
-
OperationDepsNode();
~OperationDepsNode();
@@ -72,21 +67,21 @@ struct OperationDepsNode : public DepsNode {
OperationDepsNode *get_entry_operation() { return this; }
OperationDepsNode *get_exit_operation() { return this; }
+ /* Set this operation as compoonent's entry/exit operation. */
+ void set_as_entry();
+ void set_as_exit();
+
/* Component that contains the operation. */
ComponentDepsNode *owner;
/* Callback for operation. */
DepsEvalOperationCb evaluate;
-
/* How many inlinks are we still waiting on before we can be evaluated. */
uint32_t num_links_pending;
float eval_priority;
bool scheduled;
- /* Stage of evaluation */
- eDepsOperation_Type optype;
-
/* Identifier for the operation being performed. */
eDepsOperation_Code opcode;
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 2f73eb6b71c..e18560b95af 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -2247,6 +2247,8 @@ static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin
}
/* TODO: images? */
+ default:
+ break;
}
}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index aafd7ebb1f9..be01f8cbe69 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -895,7 +895,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even
case PADENTER:
case LEFTMOUSE:
case MIDDLEMOUSE:
- if (WM_modal_tweak_exit(event, mm->event_type)) {
+ if (WM_event_is_modal_tweak_exit(event, mm->event_type)) {
ed_marker_move_exit(C, op);
WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 4571df0f077..9d25fc9e1a3 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -452,7 +452,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
ok |= KEYFRAME_OK_H2; \
} \
} (void)0
-
+
/* ------------------------ */
static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt)
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index c1e82583521..071c5fab9d7 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -52,6 +52,7 @@
#include "BKE_deform.h"
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index f2a35bb1553..540886196fe 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1073,10 +1073,11 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
/* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
* is determined by the array index for the F-Curve
*/
- if (ELEM(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
+ PropertySubType prop_subtype = RNA_property_subtype(prop);
+ if (ELEM(prop_subtype, PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
}
- else if (RNA_property_subtype(prop), PROP_QUATERNION) {
+ else if (ELEM(prop_subtype, PROP_QUATERNION)) {
fcu->color_mode = FCURVE_COLOR_AUTO_YRGB;
}
}
@@ -1785,7 +1786,9 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
NlaStrip *strip = (NlaStrip *)ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
- success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
+ if (fcu) {
+ success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
+ }
}
else if (UI_but_flag_is_set(but, UI_BUT_DRIVEN)) {
/* Driven property - Find driver */
@@ -1890,27 +1893,27 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
NlaStrip *strip = (NlaStrip *)ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
- BLI_assert(fcu != NULL); /* NOTE: This should be true, or else we wouldn't be able to get here */
-
- if (BKE_fcurve_is_protected(fcu)) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
- strip->name, BKE_idcode_to_name(GS(id->name)), id->name + 2);
- }
- else {
- /* remove the keyframe directly
- * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
- * and delete_keyframe() expects the FCurve to be part of an action
- */
- bool found = false;
- int i;
-
- /* try to find index of beztriple to get rid of */
- i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
- if (found) {
- /* delete the key at the index (will sanity check + do recalc afterwards) */
- delete_fcurve_key(fcu, i, 1);
- success = true;
+ if (fcu) {
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
+ strip->name, BKE_idcode_to_name(GS(id->name)), id->name + 2);
+ }
+ else {
+ /* remove the keyframe directly
+ * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
+ * and delete_keyframe() expects the FCurve to be part of an action
+ */
+ bool found = false;
+ int i;
+
+ /* try to find index of beztriple to get rid of */
+ i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
+ if (found) {
+ /* delete the key at the index (will sanity check + do recalc afterwards) */
+ delete_fcurve_key(fcu, i, 1);
+ success = true;
+ }
}
}
}
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 4408ec26b3f..0a27fe14de7 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -1052,6 +1052,8 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
}
+ default:
+ break;
}
/* send notifiers for updates (this doesn't require context to work!) */
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 47e73f9b777..51b76563c72 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -66,7 +66,7 @@
/* ************************** Object Tools Exports ******************************* */
/* NOTE: these functions are exported to the Object module to be called from the tools there */
-void ED_armature_apply_transform(Object *ob, float mat[4][4])
+void ED_armature_apply_transform(Object *ob, float mat[4][4], const bool do_props)
{
bArmature *arm = ob->data;
@@ -74,14 +74,14 @@ void ED_armature_apply_transform(Object *ob, float mat[4][4])
ED_armature_to_edit(arm);
/* Transform the bones */
- ED_armature_transform_bones(arm, mat);
+ ED_armature_transform_bones(arm, mat, do_props);
/* Turn the list into an armature */
ED_armature_from_edit(arm);
ED_armature_edit_free(arm);
}
-void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4])
+void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props)
{
EditBone *ebone;
float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */
@@ -106,27 +106,29 @@ void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4])
/* apply the transformed roll back */
mat3_to_vec_roll(tmat, NULL, &ebone->roll);
- ebone->rad_head *= scale;
- ebone->rad_tail *= scale;
- ebone->dist *= scale;
-
- /* we could be smarter and scale by the matrix along the x & z axis */
- ebone->xwidth *= scale;
- ebone->zwidth *= scale;
+ if (do_props) {
+ ebone->rad_head *= scale;
+ ebone->rad_tail *= scale;
+ ebone->dist *= scale;
+
+ /* we could be smarter and scale by the matrix along the x & z axis */
+ ebone->xwidth *= scale;
+ ebone->zwidth *= scale;
+ }
}
}
-void ED_armature_transform(struct bArmature *arm, float mat[4][4])
+void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do_props)
{
if (arm->edbo) {
- ED_armature_transform_bones(arm, mat);
+ ED_armature_transform_bones(arm, mat, do_props);
}
else {
/* Put the armature into editmode */
ED_armature_to_edit(arm);
/* Transform the bones */
- ED_armature_transform_bones(arm, mat);
+ ED_armature_transform_bones(arm, mat, do_props);
/* Go back to object mode*/
ED_armature_from_edit(arm);
@@ -220,7 +222,7 @@ float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const bool
vec_roll_to_mat3_normalized(nor, 0.0f, mat);
/* project the new_up_axis along the normal */
- project_v3_v3v3(vec, align_axis, nor);
+ project_v3_v3v3_normalized(vec, align_axis, nor);
sub_v3_v3v3(align_axis_proj, align_axis, vec);
if (axis_only) {
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index c928508237d..db4b642fe91 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -311,8 +311,8 @@ typedef struct BoneFlipNameData {
* This way if we are flipping related bones (e.g., Bone.L, Bone.R) at the same time
* all the bones are safely renamed, without conflicting with each other.
*
- * \param arm Armature the bones belong to
- * \param bones ListBase of BoneConflict elems, populated via ED_armature_bones_flip_names_add
+ * \param arm: Armature the bones belong to
+ * \param bones_names: List of BoneConflict elems.
*/
void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names)
{
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 1c342657eec..417d7c8ba3b 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -380,7 +380,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
if (base->object->adt) {
if (ob->adt == NULL) {
/* no animdata, so just use a copy of the whole thing */
- ob->adt = BKE_animdata_copy(base->object->adt, false);
+ ob->adt = BKE_animdata_copy(bmain, base->object->adt, false);
}
else {
/* merge in data - we'll fix the drivers manually */
@@ -391,7 +391,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
if (curarm->adt) {
if (arm->adt == NULL) {
/* no animdata, so just use a copy of the whole thing */
- arm->adt = BKE_animdata_copy(curarm->adt, false);
+ arm->adt = BKE_animdata_copy(bmain, curarm->adt, false);
}
else {
/* merge in data - we'll fix the drivers manually */
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index e3c64b523b1..25f1b282f14 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -328,7 +328,7 @@ static int poselib_sanitize_exec(bContext *C, wmOperator *op)
/* add pose to poselib */
marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
- BLI_strncpy(marker->name, "Pose", sizeof(marker->name));
+ BLI_snprintf(marker->name, sizeof(marker->name), "F%d Pose", (int)ak->cfra);
marker->frame = (int)ak->cfra;
marker->flag = -1;
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index a69264cd012..8a366ce6a81 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -4160,7 +4160,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
*/
bp = nu->bp;
- if (bp[nu->pntsu - 1].f1 & SELECT) {
+ if (bp[nu->pntsu - 1].f1 & SELECT) {
if (nu2 == NULL) {
nu2 = nu;
}
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 34e026a3ef4..5c3a694929e 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -70,102 +70,6 @@
/* Distance between start/end points to consider cyclic */
#define STROKE_CYCLIC_DIST_PX 8
-
-/* -------------------------------------------------------------------- */
-
-/** \name Depth Utilities
- * \{ */
-
-
-static float depth_read_zbuf(const ViewContext *vc, int x, int y)
-{
- ViewDepths *vd = vc->rv3d->depths;
-
- if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h)
- return vd->depths[y * vd->w + x];
- else
- return -1.0f;
-}
-
-static bool depth_unproject(
- const ARegion *ar, const bglMats *mats,
- const int mval[2], const double depth,
- float r_location_world[3])
-{
- double p[3];
- if (gluUnProject(
- (double)ar->winrct.xmin + mval[0] + 0.5,
- (double)ar->winrct.ymin + mval[1] + 0.5,
- depth, mats->modelview, mats->projection, (const GLint *)mats->viewport,
- &p[0], &p[1], &p[2]))
- {
- copy_v3fl_v3db(r_location_world, p);
- return true;
- }
- return false;
-}
-
-static bool depth_read_normal(
- const ViewContext *vc, const bglMats *mats, const int mval[2],
- float r_normal[3])
-{
- /* pixels surrounding */
- bool depths_valid[9] = {false};
- float coords[9][3] = {{0}};
-
- ARegion *ar = vc->ar;
- const ViewDepths *depths = vc->rv3d->depths;
-
- for (int x = 0, i = 0; x < 2; x++) {
- for (int y = 0; y < 2; y++) {
- const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
-
- const double depth = (double)depth_read_zbuf(vc, mval_ofs[0], mval_ofs[1]);
- if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (depth_unproject(ar, mats, mval_ofs, depth, coords[i])) {
- depths_valid[i] = true;
- }
- }
- i++;
- }
- }
-
- const int edges[2][6][2] = {
- /* x edges */
- {{0, 1}, {1, 2},
- {3, 4}, {4, 5},
- {6, 7}, {7, 8}},
- /* y edges */
- {{0, 3}, {3, 6},
- {1, 4}, {4, 7},
- {2, 5}, {5, 8}},
- };
-
- float cross[2][3] = {{0.0f}};
-
- for (int i = 0; i < 6; i++) {
- for (int axis = 0; axis < 2; axis++) {
- if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) {
- float delta[3];
- sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]);
- add_v3_v3(cross[axis], delta);
- }
- }
- }
-
- cross_v3_v3v3(r_normal, cross[0], cross[1]);
-
- if (normalize_v3(r_normal) != 0.0f) {
- return true;
- }
- else {
- return false;
- }
-}
-
-/** \} */
-
-
/* -------------------------------------------------------------------- */
/** \name StrokeElem / #RNA_OperatorStrokeElement Conversion Functions
@@ -308,9 +212,9 @@ static bool stroke_elem_project(
((unsigned int)mval_i[0] < depths->w) &&
((unsigned int)mval_i[1] < depths->h))
{
- const double depth = (double)depth_read_zbuf(&cdd->vc, mval_i[0], mval_i[1]);
+ const double depth = (double)ED_view3d_depth_read_cached(&cdd->vc, mval_i);
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (depth_unproject(ar, &cdd->mats, mval_i, depth, r_location_world)) {
+ if (ED_view3d_depth_unproject(ar, &cdd->mats, mval_i, depth, r_location_world)) {
is_location_world_set = true;
if (r_normal_world) {
zero_v3(r_normal_world);
@@ -319,7 +223,7 @@ static bool stroke_elem_project(
if (surface_offset != 0.0f) {
const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
float normal[3];
- if (depth_read_normal(&cdd->vc, &cdd->mats, mval_i, normal)) {
+ if (ED_view3d_depth_read_cached_normal(&cdd->vc, &cdd->mats, mval_i, normal)) {
madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
if (r_normal_world) {
copy_v3_v3(r_normal_world, normal);
@@ -627,7 +531,7 @@ static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event)
CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW,
CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE))
{
- if (depth_read_normal(&cdd->vc, &cdd->mats, event->mval, normal)) {
+ if (ED_view3d_depth_read_cached_normal(&cdd->vc, &cdd->mats, event->mval, normal)) {
if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) {
float cross_a[3], cross_b[3];
cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal);
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index bd4856f1b93..90d44503013 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -252,8 +252,10 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
gpfn = gpf->next;
- if (gpf->flag & GP_FRAME_SELECT)
- changed |= BKE_gpencil_layer_delframe(gpl, gpf);
+ if (gpf->flag & GP_FRAME_SELECT) {
+ BKE_gpencil_layer_delframe(gpl, gpf);
+ changed = true;
+ }
}
return changed;
@@ -314,7 +316,7 @@ void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
*/
/* globals for copy/paste data (like for other copy/paste buffers) */
-ListBase gp_anim_copybuf = {NULL, NULL};
+static ListBase gp_anim_copybuf = {NULL, NULL};
static int gp_anim_copy_firstframe = 999999999;
static int gp_anim_copy_lastframe = -999999999;
static int gp_anim_copy_cfra = 0;
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 8ddf3a22517..e5fb162a96c 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -710,7 +710,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
}
else {
/* ERROR */
- BLI_assert("3D stroke being sculpted in non-3D view");
+ BLI_assert(!"3D stroke being sculpted in non-3D view");
}
}
else {
@@ -773,6 +773,9 @@ typedef struct tGPSB_CloneBrushData {
/* for "stamp" mode, the currently pasted brushes */
bGPDstroke **new_strokes;
+
+ /* mapping from colors referenced per stroke, to the new colours in the "pasted" strokes */
+ GHash *new_colors;
} tGPSB_CloneBrushData;
/* Initialise "clone" brush data */
@@ -816,6 +819,11 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso)
if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) {
data->new_strokes = MEM_callocN(sizeof(bGPDstroke *) * data->totitems, "cloned strokes ptr array");
}
+
+ /* Init colormap for mapping between the pasted stroke's source colour(names)
+ * and the final colours that will be used here instead...
+ */
+ data->new_colors = gp_copybuf_validate_colormap(gso->gpd);
}
/* Free custom data used for "clone" brush */
@@ -829,6 +837,12 @@ static void gp_brush_clone_free(tGP_BrushEditData *gso)
data->new_strokes = NULL;
}
+ /* free copybuf colormap */
+ if (data->new_colors) {
+ BLI_ghash_free(data->new_colors, NULL, NULL);
+ data->new_colors = NULL;
+ }
+
/* free the customdata itself */
MEM_freeN(data);
gso->customdata = NULL;
@@ -869,6 +883,13 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
+ /* Fix color references */
+ BLI_assert(new_stroke->colorname[0] != '\0');
+ new_stroke->palcolor = BLI_ghash_lookup(data->new_colors, new_stroke->colorname);
+
+ BLI_assert(new_stroke->palcolor != NULL);
+ BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
+
/* Adjust all the stroke's points, so that the strokes
* get pasted relative to where the cursor is now
*/
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 2df4b2cae54..55a3fc09f2e 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -38,8 +38,11 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -335,11 +338,27 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot)
/* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */
ListBase gp_strokes_copypastebuf = {NULL, NULL};
+/* Hash for hanging on to all the palette colors used by strokes in the buffer
+ *
+ * This is needed to prevent dangling and unsafe pointers when pasting across datablocks,
+ * or after a color used by a stroke in the buffer gets deleted (via user action or undo).
+ */
+static GHash *gp_strokes_copypastebuf_colors = NULL;
+
/* Free copy/paste buffer data */
void ED_gpencil_strokes_copybuf_free(void)
{
bGPDstroke *gps, *gpsn;
+ /* Free the palettes buffer
+ * NOTE: This is done before the strokes so that the name ptrs (keys) are still safe
+ */
+ if (gp_strokes_copypastebuf_colors) {
+ BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN);
+ gp_strokes_copypastebuf_colors = NULL;
+ }
+
+ /* Free the stroke buffer */
for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) {
gpsn = gps->next;
@@ -352,6 +371,46 @@ void ED_gpencil_strokes_copybuf_free(void)
gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL;
}
+/* Ensure that destination datablock has all the colours the pasted strokes need
+ * Helper function for copy-pasting strokes
+ */
+GHash *gp_copybuf_validate_colormap(bGPdata *gpd)
+{
+ GHash *new_colors = BLI_ghash_str_new("GPencil Paste Dst Colors");
+ GHashIterator gh_iter;
+
+ /* If there's no active palette yet (i.e. new datablock), add one */
+ bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
+ if (palette == NULL) {
+ palette = BKE_gpencil_palette_addnew(gpd, "Pasted Palette", true);
+ }
+
+ /* For each color, figure out what to map to... */
+ GHASH_ITER(gh_iter, gp_strokes_copypastebuf_colors) {
+ bGPDpalettecolor *palcolor;
+ char *name = BLI_ghashIterator_getKey(&gh_iter);
+
+ /* Look for existing color to map to */
+ /* XXX: What to do if same name but different color? Behaviour here should depend on a property? */
+ palcolor = BKE_gpencil_palettecolor_getbyname(palette, name);
+ if (palcolor == NULL) {
+ /* Doesn't Exist - Create new matching color for this palette */
+ /* XXX: This still doesn't fix the pasting across file boundaries problem... */
+ bGPDpalettecolor *src_color = BLI_ghashIterator_getValue(&gh_iter);
+
+ palcolor = MEM_dupallocN(src_color);
+ BLI_addtail(&palette->colors, palcolor);
+
+ BLI_uniquename(&palette->colors, palcolor, DATA_("GP Color"), '.', offsetof(bGPDpalettecolor, info), sizeof(palcolor->info));
+ }
+
+ /* Store this mapping (for use later when pasting) */
+ BLI_ghash_insert(new_colors, name, palcolor);
+ }
+
+ return new_colors;
+}
+
/* --------------------- */
/* Copy selected strokes */
@@ -413,7 +472,26 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- /* done - no updates needed */
+ /* Build up hash of colors used in these strokes, making copies of these to protect against dangling pointers */
+ if (gp_strokes_copypastebuf.first) {
+ gp_strokes_copypastebuf_colors = BLI_ghash_str_new("GPencil CopyBuf Colors");
+
+ for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ if (BLI_ghash_haskey(gp_strokes_copypastebuf_colors, gps->colorname) == false) {
+ bGPDpalettecolor *color = MEM_dupallocN(gps->palcolor);
+
+ BLI_ghash_insert(gp_strokes_copypastebuf_colors, gps->colorname, color);
+ gps->palcolor = color;
+ }
+ }
+ }
+ }
+
+ /* updates (to ensure operator buttons are refreshed, when used via hotkeys) */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); // XXX?
+
+ /* done */
return OPERATOR_FINISHED;
}
@@ -458,6 +536,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
bGPDframe *gpf;
eGP_PasteMode type = RNA_enum_get(op->ptr, "type");
+ GHash *new_colors;
/* check for various error conditions */
if (gpd == NULL) {
@@ -515,6 +594,10 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ /* Ensure that all the necessary colors exist */
+ new_colors = gp_copybuf_validate_colormap(gpd);
+
+ /* Copy over the strokes from the buffer (and adjust the colors) */
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 */
@@ -533,6 +616,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
*/
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
if (gpf) {
+ /* Create new stroke */
bGPDstroke *new_stroke = MEM_dupallocN(gps);
new_stroke->tmp_layerinfo[0] = '\0';
@@ -543,10 +627,22 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
+
+ /* Fix color references */
+ BLI_assert(new_stroke->colorname[0] != '\0');
+ new_stroke->palcolor = BLI_ghash_lookup(new_colors, new_stroke->colorname);
+
+ BLI_assert(new_stroke->palcolor != NULL);
+ BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
+
+ /*new_stroke->flag |= GP_STROKE_RECALC_COLOR; */
}
}
}
+ /* free temp data */
+ BLI_ghash_free(new_colors, NULL, NULL);
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
@@ -750,7 +846,7 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
/* identifiers */
ot->name = "Insert Blank Frame";
ot->idname = "GPENCIL_OT_blank_frame_add";
- ot->description = "Inserts a blank frame on the current frame "
+ ot->description = "Insert a blank frame on the current frame "
"(all subsequently existing frames, if any, are shifted right by one frame)";
/* callbacks */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 5c7c9b84adb..a3734c56c59 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -40,6 +40,8 @@ struct bGPdata;
struct bGPDstroke;
struct bGPDspoint;
+struct GHash;
+
struct ARegion;
struct View2D;
struct wmOperatorType;
@@ -69,75 +71,23 @@ typedef struct GP_SpaceConversion {
float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */
} GP_SpaceConversion;
-
-/**
- * Check whether a given stroke segment is inside a circular brush
- *
- * \param mval The current screen-space coordinates (midpoint) of the brush
- * \param mvalo The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED)
- * \param rad The radius of the brush
- *
- * \param x0, y0 The screen-space x and y coordinates of the start of the stroke segment
- * \param x1, y1 The screen-space x and y coordinates of the end of the stroke segment
- */
bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
int rad, int x0, int y0, int x1, int y1);
-
-/**
- * Init settings for stroke point space conversions
- *
- * \param[out] r_gsc The space conversion settings struct, populated with necessary params
- */
void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc);
-/**
- * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
- *
- * \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(GP_SpaceConversion *settings, struct bGPDstroke *gps, struct bGPDspoint *pt,
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
- * \param diff_mat Matrix with the difference between original parent matrix
- * \param[out] r_pt Pointer to new point after apply matrix
- */
void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt);
-/**
- * Change points position relative to parent object
- */
+
void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps);
-/**
- * Change point position relative to parent object
- */
+
void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt);
-/**
- * Convert a screenspace point to a 3D Grease Pencil coordinate.
- *
- * For use with editing tools where it is easier to perform the operations in 2D,
- * and then later convert the transformed points back to 3D.
- *
- * \param screeN_co The screenspace 2D coordinates to convert to
- * \param[out] r_out The resulting 3D coordinates of the input point
- */
bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, struct Scene *scene, const float screen_co[2], float r_out[3]);
/* Poll Callbacks ------------------------------------ */
@@ -155,48 +105,18 @@ int gp_brush_crt_presets_poll(bContext *C);
extern ListBase gp_strokes_copypastebuf;
+/* Build a map for converting between old colornames and destination-color-refs */
+struct GHash *gp_copybuf_validate_colormap(bGPdata *gpd);
+
/* Stroke Editing ------------------------------------ */
void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke, int tag_flags);
-/**
- * Apply smooth to stroke point
- * \param gps Stroke to smooth
- * \param i Point index
- * \param inf Amount of smoothing to apply
- * \param affect_pressure Apply smoothing to pressure values too?
- */
bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure);
-
-/**
-* Apply smooth for strength to stroke point
-* \param gps Stroke to smooth
-* \param i Point index
-* \param inf Amount of smoothing to apply
-*/
bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf);
-
-/**
-* Apply smooth for thickness to stroke point (use pressure)
-* \param gps Stroke to smooth
-* \param i Point index
-* \param inf Amount of smoothing to apply
-*/
bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf);
-
-/**
- * Subdivide a stroke once, by adding points at the midpoint between each pair of points
- * \param gps Stroke data
- * \param new_totpoints Total number of points (after subdividing)
- */
void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints);
-
-/**
-* Add randomness to stroke
-* \param gps Stroke data
-* \param brush Brush data
-*/
void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush);
/* Layers Enums -------------------------------------- */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 59b5b41f114..83e2a85db49 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -117,8 +117,8 @@ static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_t
/* Interpolate all values */
interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor);
- pt->pressure = interpf(prev->pressure, next->pressure, factor);
- pt->strength = interpf(prev->strength, next->strength, factor);
+ pt->pressure = interpf(prev->pressure, next->pressure, 1.0f - factor);
+ pt->strength = interpf(prev->strength, next->strength, 1.0f - factor);
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
}
@@ -284,7 +284,9 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
new_stroke = MEM_dupallocN(gps_from);
new_stroke->points = MEM_dupallocN(gps_from->points);
new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
-
+ new_stroke->tot_triangles = 0;
+ new_stroke->flag |= GP_STROKE_RECALC_CACHES;
+
if (valid) {
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
@@ -302,6 +304,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
new_stroke->tot_triangles = 0;
new_stroke->triangles = MEM_recallocN(new_stroke->triangles, sizeof(*new_stroke->triangles));
+ new_stroke->flag |= GP_STROKE_RECALC_CACHES;
}
/* add to strokes */
@@ -986,7 +989,9 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
new_stroke = MEM_dupallocN(gps_from);
new_stroke->points = MEM_dupallocN(gps_from->points);
new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
-
+ new_stroke->tot_triangles = 0;
+ new_stroke->flag |= GP_STROKE_RECALC_CACHES;
+
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 78e1a0dda36..3a2169798e5 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -99,8 +99,8 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, DKEY);
/* Pie Menu - For standard tools */
- WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_tool_palette", QKEY, KM_PRESS, 0, DKEY);
- WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_settings_palette", WKEY, KM_PRESS, 0, DKEY);
+ WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_tool_palette", QKEY, KM_PRESS, 0, DKEY);
+ WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_settings_palette", WKEY, KM_PRESS, 0, DKEY);
/* Add Blank Frame */
/* XXX: BKEY or NKEY? BKEY is easier to reach from DKEY, so we'll use that for now */
@@ -135,7 +135,7 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0);
/* Pie Menu - For settings/tools easy access */
- WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_sculpt", EKEY, KM_PRESS, 0, DKEY);
+ WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_sculpt", EKEY, KM_PRESS, 0, DKEY);
/* Brush Settings */
/* NOTE: We cannot expose these in the standard keymap, as they will interfere with regular hotkeys
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 5eacbf6f807..eb49060b629 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -162,6 +162,8 @@ typedef struct tGPsdata {
bGPDbrush *brush; /* current drawing brush */
short straight[2]; /* 1: line horizontal, 2: line vertical, other: not defined, second element position */
int lock_axis; /* lock drawing to one axis */
+
+ short keymodifier; /* key used for invoking the operator */
} tGPsdata;
/* ------ */
@@ -1940,7 +1942,7 @@ static void gpencil_draw_cancel(bContext *C, wmOperator *op)
/* ------------------------------- */
-static int gpencil_draw_init(bContext *C, wmOperator *op)
+static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPsdata *p;
eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
@@ -1959,6 +1961,13 @@ static int gpencil_draw_init(bContext *C, wmOperator *op)
gpencil_draw_exit(C, op);
return 0;
}
+
+ if (event != NULL) {
+ p->keymodifier = event->keymodifier;
+ }
+ else {
+ p->keymodifier = -1;
+ }
/* everything is now setup ok */
return 1;
@@ -2200,7 +2209,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
/* printf("GPencil - Starting Re-Drawing\n"); */
/* try to initialize context data needed while drawing */
- if (!gpencil_draw_init(C, op)) {
+ if (!gpencil_draw_init(C, op, NULL)) {
if (op->customdata) MEM_freeN(op->customdata);
/* printf("\tGP - no valid data\n"); */
return OPERATOR_CANCELLED;
@@ -2275,7 +2284,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
printf("GPencil - Starting Drawing\n");
/* try to initialize context data needed while drawing */
- if (!gpencil_draw_init(C, op)) {
+ if (!gpencil_draw_init(C, op, event)) {
if (op->customdata)
MEM_freeN(op->customdata);
if (G.debug & G_DEBUG)
@@ -2438,7 +2447,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* is essential for ensuring that they can quickly return to that view
*/
}
- else if ((ELEM(event->type, DKEY)) && (event->val == KM_RELEASE)) {
+ else if ((ELEM(event->type, p->keymodifier)) && (event->val == KM_RELEASE)) {
/* enable continuous if release D key in mid drawing */
p->scene->toolsettings->gpencil_flags |= GP_TOOL_FLAG_PAINTSESSIONS_ON;
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 2b662d04f03..ed05b8be9ca 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -391,7 +391,16 @@ EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, PointerRNA
/* ******************************************************** */
/* Brush Tool Core */
-/* Check if part of stroke occurs within last segment drawn by eraser */
+/**
+ * Check whether a given stroke segment is inside a circular brush
+ *
+ * \param mval The current screen-space coordinates (midpoint) of the brush
+ * \param mvalo The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED)
+ * \param rad The radius of the brush
+ *
+ * \param x0, y0 The screen-space x and y coordinates of the start of the stroke segment
+ * \param x1, y1 The screen-space x and y coordinates of the end of the stroke segment
+ */
bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
int rad, int x0, int y0, int x1, int y1)
{
@@ -502,7 +511,11 @@ bGPDpalettecolor *ED_gpencil_stroke_getcolor(bGPdata *gpd, bGPDstroke *gps)
/* ******************************************************** */
/* Space Conversion */
-/* Init handling for space-conversion function (from passed-in parameters) */
+/**
+ * Init settings for stroke point space conversions
+ *
+ * \param r_gsc: [out] The space conversion settings struct, populated with necessary params
+ */
void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
{
ScrArea *sa = CTX_wm_area(C);
@@ -538,7 +551,13 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
}
}
-/* convert point to parent space */
+/**
+ * Convert point to parent space
+ *
+ * \param pt Original point
+ * \param diff_mat Matrix with the difference between original parent matrix
+ * \param[out] r_pt Pointer to new point after apply matrix
+ */
void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt)
{
float fpt[3];
@@ -547,7 +566,9 @@ void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *
copy_v3_v3(&r_pt->x, fpt);
}
-/* Change position relative to parent object */
+/**
+ * Change points position relative to parent object
+ */
void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps)
{
bGPDspoint *pt;
@@ -568,7 +589,9 @@ void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps)
}
}
-/* Change point position relative to parent object */
+/**
+ * Change point position relative to parent object
+ */
void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt)
{
/* undo matrix */
@@ -583,8 +606,13 @@ void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt)
copy_v3_v3(&pt->x, fpt);
}
-/* Convert Grease Pencil points to screen-space values
- * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn
+/**
+ * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
+ *
+ * \param[out] r_x The screen-space x-coordinate of the point
+ * \param[out] r_y The screen-space y-coordinate of the point
+ *
+ * \warning This assumes that the caller has already checked whether the stroke in question can be drawn.
*/
void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
int *r_x, int *r_y)
@@ -628,8 +656,16 @@ 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
+/**
+ * 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 r_x: [out] The screen-space x-coordinate of the point
+ * \param r_y: [out] The screen-space y-coordinate of the point
+ *
+ * \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)
@@ -688,6 +724,12 @@ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
/**
* Project screenspace coordinates to 3D-space
*
+ * For use with editing tools where it is easier to perform the operations in 2D,
+ * and then later convert the transformed points back to 3D.
+ *
+ * \param screen_co: The screenspace 2D coordinates to convert to
+ * \param r_out: The resulting 3D coordinates of the input point
+ *
* \note We include this as a utility function, since the standard method
* involves quite a few steps, which are invariably always the same
* for all GPencil operations. So, it's nicer to just centralize these.
@@ -722,7 +764,7 @@ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen
}
/**
- * Apply smooth to stroke point
+ * Apply smooth to stroke point
* \param gps Stroke to smooth
* \param i Point index
* \param inf Amount of smoothing to apply
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 4a4ab832b28..4668d5d3d50 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -256,7 +256,7 @@ typedef enum eAnimFilter_Flags {
ANIMFILTER_TMP_PEEK = (1 << 30),
/* ignore ONLYSEL flag from filterflag, (internal use only!) */
- ANIMFILTER_TMP_IGNORE_ONLYSEL = (1 << 31)
+ ANIMFILTER_TMP_IGNORE_ONLYSEL = (1u << 31)
} eAnimFilter_Flags;
/* ---------- Flag Checking Macros ------------ */
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 6b8943421bd..9130336228d 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -158,9 +158,9 @@ void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4]);
void transform_armature_mirror_update(struct Object *obedit);
void ED_armature_origin_set(struct Scene *scene, struct Object *ob, float cursor[3], int centermode, int around);
-void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4]);
-void ED_armature_apply_transform(struct Object *ob, float mat[4][4]);
-void ED_armature_transform(struct bArmature *arm, float mat[4][4]);
+void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props);
+void ED_armature_apply_transform(struct Object *ob, float mat[4][4], const bool do_props);
+void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do_props);
#define ARM_GROUPS_NAME 1
#define ARM_GROUPS_ENVELOPE 2
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index ebd2a3dcb7a..9a0a7f8f1bb 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -148,7 +148,8 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_CORRECT_UV (1 << 8)
#define P_NO_DEFAULTS (1 << 10)
#define P_NO_TEXSPACE (1 << 11)
-#define P_GPENCIL_EDIT (1 << 12)
+#define P_CENTER (1 << 12)
+#define P_GPENCIL_EDIT (1 << 13)
void Transform_Properties(struct wmOperatorType *ot, int flags);
@@ -159,12 +160,6 @@ void BIF_draw_manipulator(const struct bContext *C);
/* Snapping */
-typedef enum SnapSelect {
- SNAP_ALL = 0,
- SNAP_NOT_SELECTED = 1,
- SNAP_NOT_ACTIVE = 2,
-} SnapSelect;
-
#define SNAP_MIN_DISTANCE 30
bool peelObjectsTransform(
@@ -187,11 +182,7 @@ bool snapObjectsTransform(
/* return args */
float r_loc[3], float r_no[3]);
bool snapNodesTransform(
- struct TransInfo *t, const int mval[2], SnapSelect snap_select,
- /* return args */
- float r_loc[2], float *r_dist_px, char *r_node_border);
-bool snapNodesContext(
- struct bContext *C, const int mval[2], SnapSelect snap_select,
+ struct TransInfo *t, const int mval[2],
/* return args */
float r_loc[2], float *r_dist_px, char *r_node_border);
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 6eaae49912c..e440e8c8389 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -40,6 +40,12 @@ struct View3D;
/* ED_transform_snap_object_*** API */
+typedef enum SnapSelect {
+ SNAP_ALL = 0,
+ SNAP_NOT_SELECTED = 1,
+ SNAP_NOT_ACTIVE = 2,
+} SnapSelect;
+
/** used for storing multiple hits */
struct SnapObjectHitDepth {
struct SnapObjectHitDepth *next, *prev;
@@ -84,7 +90,6 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
bool ED_transform_snap_object_project_ray_ex(
struct SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3], float *ray_depth,
/* return args */
@@ -98,7 +103,6 @@ bool ED_transform_snap_object_project_ray(
bool ED_transform_snap_object_project_ray_all(
SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3],
float ray_depth, bool sort,
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index d5c301d98d6..85fb0ee4447 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -106,7 +106,14 @@ void ED_view3d_lastview_store(struct RegionView3D *rv3d);
/* Depth buffer */
void ED_view3d_depth_update(struct ARegion *ar);
-float ED_view3d_depth_read_cached(const struct ViewContext *vc, int x, int y);
+float ED_view3d_depth_read_cached(const struct ViewContext *vc, const int mval[2]);
+bool ED_view3d_depth_read_cached_normal(
+ const ViewContext *vc, const struct bglMats *mats, const int mval[2],
+ float r_normal[3]);
+bool ED_view3d_depth_unproject(
+ const struct ARegion *ar, const struct bglMats *mats,
+ const int mval[2], const double depth,
+ float r_location_world[3]);
void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
/* Projection */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 8420591aa3e..0c83038b7a3 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -313,9 +313,9 @@ DEF_ICON(OUTLINER_OB_ARMATURE)
DEF_ICON(OUTLINER_OB_FONT)
DEF_ICON(OUTLINER_OB_SURFACE)
DEF_ICON(OUTLINER_OB_SPEAKER)
+DEF_ICON(OUTLINER_OB_FORCE_FIELD)
+DEF_ICON(OUTLINER_OB_GROUP_INSTANCE)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK120)
- DEF_ICON(BLANK121)
DEF_ICON(BLANK122)
DEF_ICON(BLANK123)
DEF_ICON(BLANK124)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 252c199d46c..9376de8c095 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -212,6 +212,8 @@ enum {
UI_BUT_ALIGN_STITCH_TOP = (1 << 18),
UI_BUT_ALIGN_STITCH_LEFT = (1 << 19),
UI_BUT_ALIGN_ALL = (UI_BUT_ALIGN | UI_BUT_ALIGN_STITCH_TOP | UI_BUT_ALIGN_STITCH_LEFT),
+
+ UI_BUT_BOX_ITEM = (1 << 20), /* This but is "inside" a box item (currently used to change theme colors). */
};
/* scale fixed button widths by this to account for DPI */
@@ -1082,7 +1084,7 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
/* Float precision helpers */
-#define UI_PRECISION_FLOAT_MAX 7
+#define UI_PRECISION_FLOAT_MAX 6
/* For float buttons the 'step' (or a1), is scaled */
#define UI_PRECISION_FLOAT_SCALE 0.01f
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index f8a5f30a596..a0efd586af5 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -303,7 +303,6 @@ enum {
TH_EDGE_BEVEL,
TH_VERTEX_BEVEL
};
-/* XXX WARNING: previous is saved in file, so do not change order! */
/* specific defines per space should have higher define values */
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 4caacb65f5f..4c0493a881c 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -203,6 +203,7 @@ bool UI_view2d_view_to_region_clip(struct View2D *v2d, float x, float y, int *r
void UI_view2d_view_to_region(struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL();
void UI_view2d_view_to_region_fl(struct View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) ATTR_NONNULL();
+void UI_view2d_view_to_region_m4(struct View2D *v2d, float matrix[4][4]) ATTR_NONNULL();
void UI_view2d_view_to_region_rcti(struct View2D *v2d, const struct rctf *rect_src, struct rcti *rect_dst) ATTR_NONNULL();
bool UI_view2d_view_to_region_rcti_clip(struct View2D *v2d, const struct rctf *rect_src, struct rcti *rect_dst) ATTR_NONNULL();
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 7180e18ab92..7ab4e1d9c35 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -684,7 +684,7 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
if (oldbut->active) {
/* flags from the buttons we want to refresh, may want to add more here... */
- const int flag_copy = UI_BUT_REDALERT;
+ const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON;
found_active = true;
@@ -1165,6 +1165,8 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
uiBut *but;
char buf[128];
+ BLI_assert(block->flag & UI_BLOCK_LOOP);
+
/* only do it before bounding */
if (block->rect.xmin != block->rect.xmax)
return;
@@ -1179,6 +1181,9 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
}
else {
for (but = block->buttons.first; but; but = but->next) {
+ if (but->dt != UI_EMBOSS_PULLDOWN) {
+ continue;
+ }
if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
ui_but_add_shortcut(but, buf, false);
@@ -1337,7 +1342,7 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
rctf rectf;
ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
- BLI_rcti_rctf_copy(rect, &rectf);
+ BLI_rcti_rctf_copy_round(rect, &rectf);
BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
}
@@ -2146,9 +2151,14 @@ static float ui_get_but_step_unit(uiBut *but, float step_default)
/**
* \param float_precision For number buttons the precision to use or -1 to fallback to the button default.
+ * \param use_exp_float Use exponent representation of floats when out of reasonable range (outside of 1e3/1e-3).
*/
-void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision)
+void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision, const bool use_exp_float, bool *r_use_exp_float)
{
+ if (r_use_exp_float) {
+ *r_use_exp_float = false;
+ }
+
if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
PropertyType type;
const char *buf = NULL;
@@ -2216,17 +2226,38 @@ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int
ui_get_but_string_unit(but, str, maxlen, value, false, float_precision);
}
else {
- const int prec = (float_precision == -1) ? ui_but_calc_float_precision(but, value) : float_precision;
- BLI_snprintf(str, maxlen, "%.*f", prec, value);
+ int prec = (float_precision == -1) ? ui_but_calc_float_precision(but, value) : float_precision;
+ if (use_exp_float) {
+ const int int_digits_num = integer_digits_f(value);
+ if (int_digits_num < -6 || int_digits_num > 12) {
+ BLI_snprintf(str, maxlen, "%.*g", prec, value);
+ if (r_use_exp_float) {
+ *r_use_exp_float = true;
+ }
+ }
+ else {
+ prec -= int_digits_num;
+ CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
+ BLI_snprintf(str, maxlen, "%.*f", prec, value);
+ }
+ }
+ else {
+#if 0 /* TODO, but will likely break some stuff, so better after 2.79 release. */
+ prec -= int_digits_num;
+ CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
+#endif
+ BLI_snprintf(str, maxlen, "%.*f", prec, value);
+ }
}
}
- else
+ else {
BLI_snprintf(str, maxlen, "%d", (int)value);
+ }
}
}
void ui_but_string_get(uiBut *but, char *str, const size_t maxlen)
{
- ui_but_string_get_ex(but, str, maxlen, -1);
+ ui_but_string_get_ex(but, str, maxlen, -1, false, NULL);
}
/**
@@ -2335,11 +2366,10 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double
#else /* WITH_PYTHON */
- *value = atof(str);
+ *r_value = atof(str);
ok = true;
- (void)C;
- (void)but;
+ UNUSED_VARS(C, but);
#endif /* WITH_PYTHON */
@@ -3168,7 +3198,9 @@ static uiBut *ui_def_but(
}
if (block->flag & UI_BLOCK_RADIAL) {
- but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ if (but->str && but->str[0])
+ but->drawflag |= UI_BUT_ICON_LEFT;
}
else if ((block->flag & UI_BLOCK_LOOP) ||
ELEM(but->type,
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index a3f0e29065d..031011ddaee 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -1440,87 +1440,82 @@ static bool ui_selectcontext_begin(
const bool is_array = RNA_property_array_check(prop);
const int rna_type = RNA_property_type(prop);
- if (!UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path)) {
- goto finally;
- }
-
- selctx_data->elems_len = BLI_listbase_count(&lb);
- if (selctx_data->elems_len == 0) {
- goto finally;
- }
-
- selctx_data->elems = MEM_mallocN(sizeof(uiSelectContextElem) * selctx_data->elems_len, __func__);
+ if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
+ !BLI_listbase_is_empty(&lb))
+ {
+ selctx_data->elems_len = BLI_listbase_count(&lb);
+ selctx_data->elems = MEM_mallocN(sizeof(uiSelectContextElem) * selctx_data->elems_len, __func__);
- for (i = 0, link = lb.first; i < selctx_data->elems_len; i++, link = link->next) {
- uiSelectContextElem *other = &selctx_data->elems[i];
- /* TODO,. de-duplicate copy_to_selected_button */
- if (link->ptr.data != ptr.data) {
- if (use_path_from_id) {
- /* Path relative to ID. */
- lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
- RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
- }
- else if (path) {
- /* Path relative to elements from list. */
- lprop = NULL;
- RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
- }
- else {
- lptr = link->ptr;
- lprop = prop;
- }
+ for (i = 0, link = lb.first; i < selctx_data->elems_len; i++, link = link->next) {
+ uiSelectContextElem *other = &selctx_data->elems[i];
+ /* TODO,. de-duplicate copy_to_selected_button */
+ if (link->ptr.data != ptr.data) {
+ if (use_path_from_id) {
+ /* Path relative to ID. */
+ lprop = NULL;
+ RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
+ }
+ else if (path) {
+ /* Path relative to elements from list. */
+ lprop = NULL;
+ RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
+ }
+ else {
+ lptr = link->ptr;
+ lprop = prop;
+ }
- /* lptr might not be the same as link->ptr! */
- if ((lptr.data != ptr.data) &&
- (lprop == prop) &&
- RNA_property_editable(&lptr, lprop))
- {
- other->ptr = lptr;
- if (is_array) {
- if (rna_type == PROP_FLOAT) {
- other->val_f = RNA_property_float_get_index(&lptr, lprop, index);
- }
- else if (rna_type == PROP_INT) {
- other->val_i = RNA_property_int_get_index(&lptr, lprop, index);
- }
- /* ignored for now */
+ /* lptr might not be the same as link->ptr! */
+ if ((lptr.data != ptr.data) &&
+ (lprop == prop) &&
+ RNA_property_editable(&lptr, lprop))
+ {
+ other->ptr = lptr;
+ if (is_array) {
+ if (rna_type == PROP_FLOAT) {
+ other->val_f = RNA_property_float_get_index(&lptr, lprop, index);
+ }
+ else if (rna_type == PROP_INT) {
+ other->val_i = RNA_property_int_get_index(&lptr, lprop, index);
+ }
+ /* ignored for now */
#if 0
- else if (rna_type == PROP_BOOLEAN) {
- other->val_b = RNA_property_boolean_get_index(&lptr, lprop, index);
- }
+ else if (rna_type == PROP_BOOLEAN) {
+ other->val_b = RNA_property_boolean_get_index(&lptr, lprop, index);
+ }
#endif
- }
- else {
- if (rna_type == PROP_FLOAT) {
- other->val_f = RNA_property_float_get(&lptr, lprop);
}
- else if (rna_type == PROP_INT) {
- other->val_i = RNA_property_int_get(&lptr, lprop);
- }
- /* ignored for now */
+ else {
+ if (rna_type == PROP_FLOAT) {
+ other->val_f = RNA_property_float_get(&lptr, lprop);
+ }
+ else if (rna_type == PROP_INT) {
+ other->val_i = RNA_property_int_get(&lptr, lprop);
+ }
+ /* ignored for now */
#if 0
- else if (rna_type == PROP_BOOLEAN) {
- other->val_b = RNA_property_boolean_get(&lptr, lprop);
- }
- else if (rna_type == PROP_ENUM) {
- other->val_i = RNA_property_enum_get(&lptr, lprop);
- }
+ else if (rna_type == PROP_BOOLEAN) {
+ other->val_b = RNA_property_boolean_get(&lptr, lprop);
+ }
+ else if (rna_type == PROP_ENUM) {
+ other->val_i = RNA_property_enum_get(&lptr, lprop);
+ }
#endif
- }
+ }
- continue;
+ continue;
+ }
}
+
+ selctx_data->elems_len -= 1;
+ i -= 1;
}
- selctx_data->elems_len -= 1;
- i -= 1;
+ success = (selctx_data->elems_len != 0);
}
}
- success = (selctx_data->elems_len != 0);
-
-finally:
if (selctx_data->elems_len == 0) {
MEM_SAFE_FREE(selctx_data->elems);
}
@@ -2319,7 +2314,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
/* Get many decimal places, then strip trailing zeros.
* note: too high values start to give strange results */
char buf_copy[UI_MAX_DRAW_STR];
- ui_but_string_get_ex(but, buf_copy, sizeof(buf_copy), UI_PRECISION_FLOAT_MAX);
+ ui_but_string_get_ex(but, buf_copy, sizeof(buf_copy), UI_PRECISION_FLOAT_MAX, false, NULL);
BLI_str_rstrip_float_zero(buf_copy, '\0');
WM_clipboard_text_set(buf_copy, 0);
@@ -3060,6 +3055,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
wmWindow *win = CTX_wm_window(C);
int len;
const bool is_num_but = ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER);
+ bool no_zero_strip = false;
if (data->str) {
MEM_freeN(data->str);
@@ -3092,14 +3088,16 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
data->maxlen = ui_but_string_get_max_length(but);
if (data->maxlen != 0) {
data->str = MEM_callocN(sizeof(char) * data->maxlen, "textedit str");
- ui_but_string_get(but, data->str, data->maxlen);
+ /* We do not want to truncate precision to default here, it's nice to show value,
+ * not to edit it - way too much precision is lost then. */
+ ui_but_string_get_ex(but, data->str, data->maxlen, UI_PRECISION_FLOAT_MAX, true, &no_zero_strip);
}
else {
data->is_str_dynamic = true;
data->str = ui_but_string_get_dynamic(but, &data->maxlen);
}
- if (ui_but_is_float(but) && !ui_but_is_unit(but) && !ui_but_anim_expression_get(but, NULL, 0)) {
+ if (ui_but_is_float(but) && !ui_but_is_unit(but) && !ui_but_anim_expression_get(but, NULL, 0) && !no_zero_strip) {
BLI_str_rstrip_float_zero(data->str, '\0');
}
@@ -6792,8 +6790,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
/* set the prop and pointer data for python access to the hovered ui element; TODO, index could be supported as well*/
PointerRNA temp_ptr;
RNA_pointer_create(NULL, &RNA_Property, but->rnaprop, &temp_ptr);
- uiLayoutSetContextPointer(layout,"button_prop", &temp_ptr);
- uiLayoutSetContextPointer(layout,"button_pointer", ptr);
+ uiLayoutSetContextPointer(layout, "button_prop", &temp_ptr);
+ uiLayoutSetContextPointer(layout, "button_pointer", ptr);
/* second slower test, saved people finding keyframe items in menus when its not possible */
if (is_anim)
@@ -7012,8 +7010,9 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
/* Set the operator pointer for python access */
- if (but->opptr)
- uiLayoutSetContextPointer(layout,"button_operator", but->opptr);
+ if (but->opptr) {
+ uiLayoutSetContextPointer(layout, "button_operator", but->opptr);
+ }
uiItemS(layout);
}
@@ -7061,7 +7060,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
- mt = WM_menutype_find("WM_MT_button_context", false);
+ mt = WM_menutype_find("WM_MT_button_context", true);
if (mt) {
Menu menu = {NULL};
menu.layout = uiLayoutColumn(layout, false);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 067279777ba..ab760c40451 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -473,7 +473,9 @@ extern void ui_hsvcircle_pos_from_vals(struct uiBut *but, const rcti *rect, floa
extern void ui_hsvcube_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xp, float *yp);
bool ui_but_is_colorpicker_display_space(struct uiBut *but);
-extern void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) ATTR_NONNULL();
+extern void ui_but_string_get_ex(
+ uiBut *but, char *str, const size_t maxlen,
+ const int float_precision, const bool use_exp_float, bool *r_use_exp_float) ATTR_NONNULL(1, 2);
extern void ui_but_string_get(uiBut *but, char *str, const size_t maxlen) ATTR_NONNULL();
extern char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size);
extern void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen) ATTR_NONNULL();
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 30a2094fee7..a95fe59348d 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -128,6 +128,8 @@ typedef struct uiItem {
enum {
UI_ITEM_FIXED = 1 << 0,
UI_ITEM_MIN = 1 << 1,
+
+ UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
};
typedef struct uiButtonItem {
@@ -192,8 +194,9 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_
static int ui_item_fit(int item, int pos, int all, int available, bool is_last, int alignment, float *extra_pixel)
{
/* available == 0 is unlimited */
- if (available == 0)
+ if (ELEM(0, available, all)) {
return item;
+ }
if (all > available) {
/* contents is bigger than available space */
@@ -216,8 +219,9 @@ static int ui_item_fit(int item, int pos, int all, int available, bool is_last,
return (int)width;
}
}
- else
+ else {
return item;
+ }
}
}
@@ -243,7 +247,9 @@ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool
variable = (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X);
if (variable) {
- layout->item.flag |= UI_ITEM_MIN;
+ if (layout->alignment != UI_LAYOUT_ALIGN_EXPAND) {
+ layout->item.flag |= UI_ITEM_MIN;
+ }
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
/* it may seem odd that the icon only adds (UI_UNIT_X / 4)
* but taking margins into account its fine */
@@ -700,7 +706,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
}
else if (flag & UI_ITEM_R_EVENT) {
- uiDefButR_prop(block, UI_BTYPE_KEY_EVENT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_KEY_EVENT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL);
}
else if (flag & UI_ITEM_R_FULL_EVENT) {
if (RNA_struct_is_a(ptr->type, &RNA_KeyMapItem)) {
@@ -2306,6 +2312,10 @@ static void ui_litem_layout_column(uiLayout *litem, bool is_box)
if (item->next && (!is_box || item != litem->items.first))
y -= litem->space;
+
+ if (is_box) {
+ item->flag |= UI_ITEM_BOX_ITEM;
+ }
}
litem->h = litem->y - y;
@@ -2396,8 +2406,10 @@ static void ui_litem_layout_radial(uiLayout *litem)
/* add a little bit more here to include number */
bitem->but->rect.xmax += 1.5f * UI_UNIT_X;
/* enable drawing as pie item if supported by widget */
- if (ui_item_is_radial_drawable(bitem))
+ if (ui_item_is_radial_drawable(bitem)) {
bitem->but->dt = UI_EMBOSS_RADIAL;
+ bitem->but->drawflag |= UI_BUT_ICON_LEFT;
+ }
}
ui_item_size(item, &itemw, &itemh);
@@ -2455,7 +2467,6 @@ static void ui_litem_estimate_box(uiLayout *litem)
uiStyle *style = litem->root->style;
ui_litem_estimate_column(litem, true);
- litem->item.flag &= ~UI_ITEM_MIN;
litem->w += 2 * style->boxspace;
litem->h += 2 * style->boxspace;
}
@@ -3127,8 +3138,11 @@ static void ui_item_estimate(uiItem *item)
for (subitem = litem->items.first; subitem; subitem = subitem->next)
ui_item_estimate(subitem);
- if (BLI_listbase_is_empty(&litem->items))
+ if (BLI_listbase_is_empty(&litem->items)) {
+ litem->w = 0;
+ litem->h = 0;
return;
+ }
if (litem->scale[0] != 0.0f || litem->scale[1] != 0.0f)
ui_item_scale(litem, litem->scale);
@@ -3264,8 +3278,18 @@ static void ui_item_layout(uiItem *item)
break;
}
- for (subitem = litem->items.first; subitem; subitem = subitem->next)
+ for (subitem = litem->items.first; subitem; subitem = subitem->next) {
+ if (item->flag & UI_ITEM_BOX_ITEM) {
+ subitem->flag |= UI_ITEM_BOX_ITEM;
+ }
ui_item_layout(subitem);
+ }
+ }
+ else {
+ if (item->flag & UI_ITEM_BOX_ITEM) {
+ uiButtonItem *bitem = (uiButtonItem *)item;
+ bitem->but->drawflag |= UI_BUT_BOX_ITEM;
+ }
}
}
@@ -3382,8 +3406,9 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
ui_item_size((uiItem *)bitem, &w, &h);
/* XXX uiBut hasn't scaled yet
* we can flag the button as not expandable, depending on its size */
- if (w <= 2 * UI_UNIT_X)
+ if (w <= 2 * UI_UNIT_X && (!but->str || but->str[0] == '\0')) {
bitem->item.flag |= UI_ITEM_MIN;
+ }
BLI_addtail(&layout->items, bitem);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index fb95cdf389b..d0c110d1db5 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -360,6 +360,9 @@ bool UI_context_copy_to_selected_list(
else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
*r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
}
+ else if (RNA_struct_is_a(ptr->type, &RNA_FCurve)) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_fcurves");
+ }
else if (RNA_struct_is_a(ptr->type, &RNA_Node) ||
RNA_struct_is_a(ptr->type, &RNA_NodeSocket))
{
@@ -494,51 +497,51 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
char *path = NULL;
bool use_path_from_id;
CollectionPointerLink *link;
- ListBase lb;
-
- if (!UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path))
- return success;
+ ListBase lb = {NULL};
- for (link = lb.first; link; link = link->next) {
- if (link->ptr.data != ptr.data) {
- if (use_path_from_id) {
- /* Path relative to ID. */
- lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
- RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
- }
- else if (path) {
- /* Path relative to elements from list. */
- lprop = NULL;
- RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
- }
- else {
- lptr = link->ptr;
- lprop = prop;
- }
+ if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
+ !BLI_listbase_is_empty(&lb))
+ {
+ for (link = lb.first; link; link = link->next) {
+ if (link->ptr.data != ptr.data) {
+ if (use_path_from_id) {
+ /* Path relative to ID. */
+ lprop = NULL;
+ RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
+ }
+ else if (path) {
+ /* Path relative to elements from list. */
+ lprop = NULL;
+ RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
+ }
+ else {
+ lptr = link->ptr;
+ lprop = prop;
+ }
- if (lptr.data == ptr.data) {
- /* lptr might not be the same as link->ptr! */
- continue;
- }
+ if (lptr.data == ptr.data) {
+ /* lptr might not be the same as link->ptr! */
+ continue;
+ }
- if (lprop == prop) {
- if (RNA_property_editable(&lptr, lprop)) {
- if (poll) {
- success = true;
- break;
- }
- else {
- if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
- RNA_property_update(C, &lptr, prop);
+ if (lprop == prop) {
+ if (RNA_property_editable(&lptr, lprop)) {
+ if (poll) {
success = true;
+ break;
+ }
+ else {
+ if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
+ RNA_property_update(C, &lptr, prop);
+ success = true;
+ }
}
}
}
}
}
}
-
MEM_SAFE_FREE(path);
BLI_freelistN(&lb);
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 534bd4278ca..7ec4d903f46 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -2099,9 +2099,11 @@ static void ui_update_color_picker_buts_rgb(uiBlock *block, ColorPicker *cpicker
continue;
if (bt->rnaprop) {
-
ui_but_v3_set(bt, rgb);
+ /* original button that created the color picker already does undo
+ * push, so disable it on RNA buttons in the color picker block */
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
}
else if (STREQ(bt->str, "Hex: ")) {
float rgb_gamma[3];
@@ -2438,7 +2440,7 @@ static void ui_block_colorpicker(uiBlock *block, float rgba[4], PointerRNA *ptr,
BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((unsigned int), rgb_gamma_uchar, ));
yco = -3.0f * UI_UNIT_Y;
- bt = uiDefBut(block, UI_BTYPE_TEXT, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y, hexcol, 0, 7, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
+ bt = uiDefBut(block, UI_BTYPE_TEXT, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
UI_but_func_set(bt, ui_colorpicker_hex_rna_cb, bt, hexcol);
bt->custom_data = cpicker;
uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("(Gamma Corrected)"), 0, yco - UI_UNIT_Y, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
@@ -2950,8 +2952,8 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co
pie->block_radial->puphash = ui_popup_menu_hash(title);
pie->block_radial->flag |= UI_BLOCK_RADIAL;
- /* if pie is spawned by a left click, it is always assumed to be click style */
- if (event->type == LEFTMOUSE) {
+ /* if pie is spawned by a left click, release or click event, it is always assumed to be click style */
+ if (event->type == LEFTMOUSE || ELEM(event->val, KM_RELEASE, KM_CLICK)) {
pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
pie->block_radial->pie_data.event = EVENT_NONE;
win->lock_pie_event = EVENT_NONE;
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 636b7e4e9ce..1927d7280f3 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -265,7 +265,7 @@ int UI_icon_from_report_type(int type)
*/
int UI_calc_float_precision(int prec, double value)
{
- static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7};
+ static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6};
static const double max_pow = 10000000.0; /* pow(10, UI_PRECISION_FLOAT_MAX) */
BLI_assert(prec <= UI_PRECISION_FLOAT_MAX);
@@ -380,6 +380,17 @@ uiButStore *UI_butstore_create(uiBlock *block)
void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
{
+ /* Workaround for button store being moved into new block,
+ * which then can't use the previous buttons state ('ui_but_update_from_old_block' fails to find a match),
+ * keeping the active button in the old block holding a reference to the button-state in the new block: see T49034.
+ *
+ * Ideally we would manage moving the 'uiButStore', keeping a correct state.
+ * All things considered this is the most straightforward fix - Campbell.
+ */
+ if (block != bs_handle->block && bs_handle->block != NULL) {
+ block = bs_handle->block;
+ }
+
BLI_freelistN(&bs_handle->items);
BLI_remlink(&block->butstore, bs_handle);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index f7f2b422724..51bf09125ba 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -3655,11 +3655,15 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
switch (but->type) {
case UI_BTYPE_LABEL:
- if (but->block->flag & UI_BLOCK_LOOP)
- widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
- else {
- wt = widget_type(UI_WTYPE_LABEL);
- fstyle = &style->widgetlabel;
+ wt = widget_type(UI_WTYPE_LABEL);
+ fstyle = &style->widgetlabel;
+ if (but->drawflag & UI_BUT_BOX_ITEM) {
+ wt->wcol_theme = &tui->wcol_box;
+ wt->state = widget_state;
+ }
+ else if (but->block->flag & UI_BLOCK_LOOP) {
+ wt->wcol_theme = &tui->wcol_menu_back;
+ wt->state = widget_state;
}
break;
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 539284030c2..4b47d0da13e 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -2758,6 +2758,24 @@ void init_userdef_do_versions(void)
}
}
+ if (!USER_VERSION_ATLEAST(278, 6)) {
+ /* Clear preference flags for re-use. */
+ U.flag &= ~(
+ USER_FLAG_DEPRECATED_1 | USER_FLAG_DEPRECATED_2 | USER_FLAG_DEPRECATED_3 |
+ USER_FLAG_DEPRECATED_6 | USER_FLAG_DEPRECATED_7 |
+ USER_FLAG_DEPRECATED_9 | USER_FLAG_DEPRECATED_10);
+ U.uiflag &= ~(
+ USER_UIFLAG_DEPRECATED_7);
+ U.transopts &= ~(
+ USER_TR_DEPRECATED_2 | USER_TR_DEPRECATED_3 | USER_TR_DEPRECATED_4 |
+ USER_TR_DEPRECATED_6 | USER_TR_DEPRECATED_7);
+ U.gameflags &= ~(
+ USER_GL_RENDER_DEPRECATED_0 | USER_GL_RENDER_DEPRECATED_1 |
+ USER_GL_RENDER_DEPRECATED_3 | USER_GL_RENDER_DEPRECATED_4);
+
+ U.uiflag |= USER_LOCK_CURSOR_ADJUST;
+ }
+
/**
* Include next version bump.
*
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index c78d97ef86f..c704c4ae126 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -2138,6 +2138,14 @@ void UI_view2d_view_to_region_rcti(View2D *v2d, const rctf *rect_src, rcti *rect
clamp_rctf_to_rcti(rect_dst, &rect_tmp);
}
+void UI_view2d_view_to_region_m4(View2D *v2d, float matrix[4][4])
+{
+ rctf mask;
+ unit_m4(matrix);
+ BLI_rctf_rcti_copy(&mask, &v2d->mask);
+ BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &mask, matrix);
+}
+
bool UI_view2d_view_to_region_rcti_clip(View2D *v2d, const rctf *rect_src, rcti *rect_dst)
{
const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index ba8792d12ff..ca4ab30a08d 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -31,6 +31,9 @@
# include "BLI_winstuff.h"
#endif
+#include <string.h>
+#include <errno.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
@@ -383,8 +386,8 @@ void WM_OT_alembic_export(wmOperatorType *ot)
"Enable this to run the import in the background, disable to block Blender while importing");
/* This dummy prop is used to check whether we need to init the start and
- * end frame values to that of the scene's, otherwise they are reset at
- * every change, draw update. */
+ * end frame values to that of the scene's, otherwise they are reset at
+ * every change, draw update. */
RNA_def_boolean(ot->srna, "init_scene_frame_range", false, "", "");
}
@@ -417,9 +420,20 @@ static int get_sequence_len(char *filename, int *ofs)
}
char path[FILE_MAX];
+ BLI_path_abs(filename, G.main->name);
BLI_split_dir_part(filename, path, FILE_MAX);
+ if (path[0] == '\0') {
+ /* The filename had no path, so just use the blend file path. */
+ BLI_split_dir_part(G.main->name, path, FILE_MAX);
+ }
+
DIR *dir = opendir(path);
+ if (dir == NULL) {
+ fprintf(stderr, "Error opening directory '%s': %s\n",
+ path, errno ? strerror(errno) : "unknown error");
+ return -1;
+ }
const char *ext = ".abc";
const char *basename = BLI_path_basename(filename);
@@ -523,6 +537,10 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
if (is_sequence) {
sequence_len = get_sequence_len(filename, &offset);
+ if (sequence_len < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to determine ABC sequence length");
+ return OPERATOR_CANCELLED;
+ }
}
bool ok = ABC_import(C, filename, scale, is_sequence, set_frame_range,
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index af6f55d7a64..975bbddd893 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -93,26 +93,28 @@ static int cachefile_open_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
- CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename));
+ CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename), 0);
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);
+ /* Will be set when running invoke, not exec directly. */
+ if (op->customdata != NULL) {
+ /* 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);
}
- MEM_freeN(op->customdata);
-
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 139c9817437..cead08afd61 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -87,8 +87,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int include_shapekeys;
int deform_bones_only;
- int include_uv_textures;
- int include_material_textures;
+ int export_texture_type;
int use_texture_copies;
int active_uv_only;
@@ -139,8 +138,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
- include_uv_textures = RNA_boolean_get(op->ptr, "include_uv_textures");
- include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures");
+ export_texture_type = RNA_enum_get(op->ptr, "export_texture_type_selection");
use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies");
active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only");
@@ -169,8 +167,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
deform_bones_only,
active_uv_only,
- include_uv_textures,
- include_material_textures,
+ export_texture_type,
use_texture_copies,
triangulate,
@@ -241,10 +238,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_uv_textures", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_material_textures", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "export_texture_type_selection", 0, "", ICON_NONE);
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
@@ -321,9 +315,15 @@ void WM_OT_collada_export(wmOperatorType *ot)
};
static EnumPropertyItem prop_bc_export_transformation_type[] = {
- {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"},
- {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"},
- {0, NULL, 0, NULL, NULL}
+ { BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" },
+ { BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ static EnumPropertyItem prop_bc_export_texture_type[] = {
+ { BC_TEXTURE_TYPE_MAT, "mat", 0, "Materials", "Export Materials" },
+ { BC_TEXTURE_TYPE_UV, "uv", 0, "UV Textures", "Export UV Textures (Face textures) as materials" },
+ { 0, NULL, 0, NULL, NULL }
};
ot->name = "Export COLLADA";
@@ -368,16 +368,9 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only",
"Only export deforming bones with armatures");
-
RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
"Export only the selected UV Map");
- RNA_def_boolean(func, "include_uv_textures", 0, "Include UV Textures",
- "Export textures assigned to the object UV Maps");
-
- RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures",
- "Export textures assigned to the object Materials");
-
RNA_def_boolean(func, "use_texture_copies", 1, "Copy",
"Copy textures to same folder where the .dae file is exported");
@@ -394,11 +387,20 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name",
"Sort exported data by Object name");
+
RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
- "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+ "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
- "Transform", "Transformation type for translation, scale and rotation");
+ "Transform", "Transformation type for translation, scale and rotation");
+
+
+ RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
+ "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
+
+ RNA_def_enum(func, "export_texture_type_selection", prop_bc_export_texture_type, 0,
+ "Texture Type", "Type for exported Textures (UV or MAT)");
+
RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim",
"Compatibility mode for SL, OpenSim and other compatible online worlds");
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 35de390274c..196285cf02a 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -999,7 +999,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (weight) {
sub_v2_v2v2(c, offco, p);
- project_v2_v2v2(vec, c, no);
+ project_v2_v2v2_normalized(vec, c, no);
w = len_v2(vec);
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index a478526dee0..6c6c106b19a 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -797,25 +797,47 @@ void ED_mesh_mirrtopo_init(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTop
qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort);
- /* Since the loop starts at 2, we must define the last index where the hash's differ */
- last = ((totvert >= 2) && (topo_pairs[0].hash == topo_pairs[1].hash)) ? 0 : 1;
+ last = 0;
/* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
* but you cant ever access the last 'a' index of MirrTopoPairs */
- for (a = 2; a <= totvert; a++) {
- /* printf("I %d %ld %d\n", (a-last), MirrTopoPairs[a ].hash, MirrTopoPairs[a ].v_index ); */
- if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
- if (a - last == 2) {
- if (em) {
- index_lookup[topo_pairs[a - 1].v_index] = (intptr_t)BM_vert_at_index(em->bm, topo_pairs[a - 2].v_index);
- index_lookup[topo_pairs[a - 2].v_index] = (intptr_t)BM_vert_at_index(em->bm, topo_pairs[a - 1].v_index);
+ if (em) {
+ BMVert **vtable = em->bm->vtable;
+ for (a = 1; a <= totvert; a++) {
+ /* printf("I %d %ld %d\n", (a - last), MirrTopoPairs[a].hash, MirrTopoPairs[a].v_indexs); */
+ if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
+ const int match_count = a - last;
+ if (match_count == 2) {
+ const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
+ index_lookup[j] = (intptr_t)vtable[k];
+ index_lookup[k] = (intptr_t)vtable[j];
+ }
+ else if (match_count == 1) {
+ /* Center vertex. */
+ const int j = topo_pairs[a - 1].v_index;
+ index_lookup[j] = (intptr_t)vtable[j];
+ }
+ last = a;
+ }
+ }
+ }
+ else {
+ /* same as above, for mesh */
+ for (a = 1; a <= totvert; a++) {
+ if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
+ const int match_count = a - last;
+ if (match_count == 2) {
+ const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
+ index_lookup[j] = k;
+ index_lookup[k] = j;
}
- else {
- index_lookup[topo_pairs[a - 1].v_index] = topo_pairs[a - 2].v_index;
- index_lookup[topo_pairs[a - 2].v_index] = topo_pairs[a - 1].v_index;
+ else if (match_count == 1) {
+ /* Center vertex. */
+ const int j = topo_pairs[a - 1].v_index;
+ index_lookup[j] = j;
}
+ last = a;
}
- last = a;
}
}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 3725590c188..07fedffaf80 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -384,7 +384,7 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
RNA_def_float_distance(ot->srna, "radius1", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 1", "", 0.001, 100.00);
- RNA_def_float_distance(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.001, 100.00);
+ RNA_def_float_distance(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.0, 100.00);
RNA_def_float_distance(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", "");
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index bf59693b856..69e8fa03d72 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1206,6 +1206,7 @@ static bool knife_ray_intersect_face(
for (; tri_i < tottri; tri_i++) {
const float *lv1, *lv2, *lv3;
+ float ray_tri_uv[2];
tri = kcd->em->looptris[tri_i];
if (tri[0]->f != f)
@@ -1217,7 +1218,7 @@ static bool knife_ray_intersect_face(
* tesselation edge and might not hit either tesselation tri with
* an exact test;
* we will exclude hits near real edges by a later test */
- if (isect_ray_tri_epsilon_v3(v1, raydir, lv1, lv2, lv3, &lambda, NULL, KNIFE_FLT_EPS)) {
+ if (isect_ray_tri_epsilon_v3(v1, raydir, lv1, lv2, lv3, &lambda, ray_tri_uv, KNIFE_FLT_EPS)) {
/* check if line coplanar with tri */
normal_tri_v3(tri_norm, lv1, lv2, lv3);
plane_from_point_normal_v3(tri_plane, lv1, tri_norm);
@@ -1226,8 +1227,7 @@ static bool knife_ray_intersect_face(
{
return false;
}
- copy_v3_v3(hit_cageco, v1);
- madd_v3_v3fl(hit_cageco, raydir, lambda);
+ interp_v3_v3v3v3_uv(hit_cageco, lv1, lv2, lv3, ray_tri_uv);
/* Now check that far enough away from verts and edges */
lst = knife_get_face_kedges(kcd, f);
for (ref = lst->first; ref; ref = ref->next) {
@@ -1239,11 +1239,7 @@ static bool knife_ray_intersect_face(
return false;
}
}
-
- transform_point_by_tri_v3(
- hit_co, hit_cageco,
- tri[0]->v->co, tri[1]->v->co, tri[2]->v->co,
- lv1, lv2, lv3);
+ interp_v3_v3v3v3_uv(hit_co, tri[0]->v->co, tri[1]->v->co, tri[2]->v->co, ray_tri_uv);
return true;
}
}
@@ -1472,7 +1468,7 @@ static void clip_to_ortho_planes(float v1[3], float v2[3], const float center[3]
/* could be v1 or v2 */
sub_v3_v3(v1, center);
- project_plane_v3_v3v3(closest, v1, dir);
+ project_plane_normalized_v3_v3v3(closest, v1, dir);
add_v3_v3(closest, center);
madd_v3_v3v3fl(v1, closest, dir, d);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index a6de1b284b7..68bd8ff27b1 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -446,6 +446,9 @@ BMVert *EDBM_vert_find_nearest_ex(
unsigned int index;
BMVert *eve;
+ /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
+ ED_view3d_backbuf_validate(vc);
+
index = ED_view3d_backbuf_sample_rect(
vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
@@ -630,7 +633,8 @@ BMEdge *EDBM_edge_find_nearest_ex(
float dist_test = 0.0f;
unsigned int index;
BMEdge *eed;
-
+
+ /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
ED_view3d_backbuf_validate(vc);
index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 1f90b60a1f5..c513c49aa8e 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -169,7 +169,7 @@ struct EdgeRingOpSubdProps {
};
-static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_default)
+static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_min, const int cuts_default)
{
/* Note, these values must match delete_mesh() event values */
static EnumPropertyItem prop_subd_edgering_types[] = {
@@ -181,7 +181,7 @@ static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_defa
PropertyRNA *prop;
- prop = RNA_def_int(ot->srna, "number_cuts", cuts_default, 0, 1000, "Number of Cuts", "", 0, 64);
+ prop = RNA_def_int(ot->srna, "number_cuts", cuts_default, 0, 1000, "Number of Cuts", "", cuts_min, 64);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_enum(ot->srna, "interpolation", prop_subd_edgering_types, SUBD_RING_INTERP_PATH,
@@ -248,7 +248,7 @@ void MESH_OT_subdivide_edgering(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- mesh_operator_edgering_props(ot, 10);
+ mesh_operator_edgering_props(ot, 1, 10);
}
@@ -5447,7 +5447,7 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
RNA_def_float(ot->srna, "merge_factor", 0.5f, 0.0f, 1.0f, "Merge Factor", "", 0.0f, 1.0f);
RNA_def_int(ot->srna, "twist_offset", 0, -1000, 1000, "Twist", "Twist offset for closed loops", -1000, 1000);
- mesh_operator_edgering_props(ot, 0);
+ mesh_operator_edgering_props(ot, 0, 0);
}
static int edbm_wireframe_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index b278d6e1e87..74da6817185 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1344,89 +1344,87 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
const bool use_hierarchy)
{
Main *bmain = CTX_data_main(C);
- ListBase *lb;
+ ListBase *lb_duplis;
DupliObject *dob;
- GHash *dupli_gh = NULL, *parent_gh = NULL;
- Object *object;
+ GHash *dupli_gh, *parent_gh = NULL;
- if (!(base->object->transflag & OB_DUPLI))
+ if (!(base->object->transflag & OB_DUPLI)) {
return;
+ }
- lb = object_duplilist(bmain->eval_ctx, scene, base->object);
+ lb_duplis = object_duplilist(bmain->eval_ctx, scene, base->object);
- if (use_hierarchy || use_base_parent) {
- dupli_gh = BLI_ghash_ptr_new(__func__);
- if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLIGROUP) {
- parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
- }
- else {
- parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
- }
+ dupli_gh = BLI_ghash_ptr_new(__func__);
+ if (use_hierarchy) {
+ if (base->object->transflag & OB_DUPLIGROUP) {
+ parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
+ }
+ else {
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
}
}
- for (dob = lb->first; dob; dob = dob->next) {
- Base *basen;
- Object *ob = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, dob->ob));
+ for (dob = lb_duplis->first; dob; dob = dob->next) {
+ Object *ob_src = dob->ob;
+ Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src));
+ Base *base_dst;
/* font duplis can have a totcol without material, we get them from parent
* should be implemented better...
*/
- if (ob->mat == NULL) ob->totcol = 0;
+ if (ob_dst->mat == NULL) {
+ ob_dst->totcol = 0;
+ }
- basen = MEM_dupallocN(base);
- basen->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP);
- ob->flag = basen->flag;
- basen->lay = base->lay;
- BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
- basen->object = ob;
+ base_dst = MEM_dupallocN(base);
+ base_dst->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP);
+ ob_dst->flag = base_dst->flag;
+ base_dst->lay = base->lay;
+ BLI_addhead(&scene->base, base_dst); /* addhead: othwise eternal loop */
+ base_dst->object = ob_dst;
/* make sure apply works */
- BKE_animdata_free(&ob->id, true);
- ob->adt = NULL;
+ BKE_animdata_free(&ob_dst->id, true);
+ ob_dst->adt = NULL;
/* Proxies are not to be copied. */
- ob->proxy_from = NULL;
- ob->proxy_group = NULL;
- ob->proxy = NULL;
+ ob_dst->proxy_from = NULL;
+ ob_dst->proxy_group = NULL;
+ ob_dst->proxy = NULL;
- ob->parent = NULL;
- BKE_constraints_free(&ob->constraints);
- ob->curve_cache = NULL;
- ob->transflag &= ~OB_DUPLI;
- ob->lay = base->lay;
+ ob_dst->parent = NULL;
+ BKE_constraints_free(&ob_dst->constraints);
+ ob_dst->curve_cache = NULL;
+ ob_dst->transflag &= ~OB_DUPLI;
+ ob_dst->lay = base->lay;
- copy_m4_m4(ob->obmat, dob->mat);
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ copy_m4_m4(ob_dst->obmat, dob->mat);
+ BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
- if (dupli_gh) {
- BLI_ghash_insert(dupli_gh, dob, ob);
- }
+ BLI_ghash_insert(dupli_gh, dob, ob_dst);
if (parent_gh) {
void **val;
/* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as 'the same',
* this avoids trying to insert same key several time and raise asserts in debug builds... */
if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
- *val = ob;
+ *val = ob_dst;
}
}
+ }
+
+ for (dob = lb_duplis->first; dob; dob = dob->next) {
+ Object *ob_src = dob->ob;
+ Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
/* Remap new object to itself, and clear again newid pointer of orig object. */
- BKE_libblock_relink_to_newid(&ob->id);
- set_sca_new_poins_ob(ob);
- BKE_id_clear_newpoin(&dob->ob->id);
+ BKE_libblock_relink_to_newid(&ob_dst->id);
+ set_sca_new_poins_ob(ob_dst);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
- if (use_hierarchy) {
- for (dob = lb->first; dob; dob = dob->next) {
+ if (use_hierarchy) {
/* original parents */
- Object *ob_src = dob->ob;
Object *ob_src_par = ob_src->parent;
-
- Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
Object *ob_dst_par = NULL;
/* find parent that was also made real */
@@ -1437,8 +1435,8 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
dob_key.ob = ob_src_par;
if (base->object->transflag & OB_DUPLIGROUP) {
memcpy(&dob_key.persistent_id[1],
- &dob->persistent_id[1],
- sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ &dob->persistent_id[1],
+ sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
}
else {
dob_key.persistent_id[0] = dob->persistent_id[0];
@@ -1462,52 +1460,42 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob_dst->parent = base->object;
ob_dst->partype = PAROBJECT;
}
-
- if (ob_dst->parent) {
- invert_m4_m4(ob_dst->parentinv, dob->mat);
-
- /* note, this may be the parent of other objects, but it should
- * still work out ok */
- BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
-
- /* to set ob_dst->orig and in case theres any other discrepicies */
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB);
- }
}
- }
- else if (use_base_parent) {
- /* since we are ignoring the internal hierarchy - parent all to the
- * base object */
- for (dob = lb->first; dob; dob = dob->next) {
- /* original parents */
- Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
-
+ else if (use_base_parent) {
+ /* since we are ignoring the internal hierarchy - parent all to the
+ * base object */
ob_dst->parent = base->object;
ob_dst->partype = PAROBJECT;
+ }
- /* similer to the code above, see comments */
- invert_m4_m4(ob_dst->parentinv, dob->mat);
+ if (ob_dst->parent) {
+ /* note, this may be the parent of other objects, but it should
+ * still work out ok */
BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
+
+ /* to set ob_dst->orig and in case theres any other discrepicies */
DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB);
}
}
if (base->object->transflag & OB_DUPLIGROUP && base->object->dup_group) {
- for (object = bmain->object.first; object; object = object->id.next) {
- if (object->proxy_group == base->object) {
- object->proxy = NULL;
- object->proxy_from = NULL;
- DAG_id_tag_update(&object->id, OB_RECALC_OB);
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->proxy_group == base->object) {
+ ob->proxy = NULL;
+ ob->proxy_from = NULL;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
}
- if (dupli_gh)
- BLI_ghash_free(dupli_gh, NULL, NULL);
- if (parent_gh)
+ BLI_ghash_free(dupli_gh, NULL, NULL);
+ if (parent_gh) {
BLI_ghash_free(parent_gh, NULL, NULL);
+ }
- free_object_duplilist(lb);
+ free_object_duplilist(lb_duplis);
+
+ BKE_main_id_clear_newpoins(bmain);
base->object->transflag &= ~OB_DUPLI;
}
@@ -1640,7 +1628,7 @@ static int convert_exec(bContext *C, wmOperator *op)
MetaBall *mb;
Mesh *me;
const short target = RNA_enum_get(op->ptr, "target");
- const bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
+ bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
int a, mballConverted = 0;
/* don't forget multiple users! */
@@ -1678,6 +1666,19 @@ static int convert_exec(bContext *C, wmOperator *op)
{
for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
Base *base = link->ptr.data;
+ ob = base->object;
+
+ /* The way object type conversion works currently (enforcing conversion of *all* objetcs using converted
+ * obdata, even some un-selected/hidden/inother scene ones, sounds totally bad to me.
+ * However, changing this is more design than bugfix, not to mention convoluted code below,
+ * so that will be for later.
+ * But at the very least, do not do that with linked IDs! */
+ if ((ID_IS_LINKED_DATABLOCK(ob) || (ob->data && ID_IS_LINKED_DATABLOCK(ob->data))) && !keep_original) {
+ keep_original = true;
+ BKE_reportf(op->reports, RPT_INFO,
+ "Converting some linked object/object data, enforcing 'Keep Original' option to True");
+ }
+
DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
@@ -2188,6 +2189,11 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
if (didit) {
Key *key = BKE_key_from_object(obn);
+ Key *oldkey = BKE_key_from_object(ob);
+ if (oldkey != NULL) {
+ ID_NEW_SET(oldkey, key);
+ }
+
if (dupflag & USER_DUP_ACT) {
bActuator *act;
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 14224e9c939..f8ad5865887 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -51,6 +51,7 @@
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_modifier.h"
@@ -411,22 +412,18 @@ static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports)
}
}
else {
- if (ob->mat[i]) {
- BKE_reportf(reports, RPT_ERROR,
- "No active image found in material \"%s\" (%d) for object \"%s\"",
- ob->mat[i]->id.name + 2, i, ob->id.name + 2);
- }
- else if (((Mesh *) ob->data)->mat[i]) {
- BKE_reportf(reports, RPT_ERROR,
+ Material *mat = give_current_material(ob, i);
+ if (mat != NULL) {
+ BKE_reportf(reports, RPT_INFO,
"No active image found in material \"%s\" (%d) for object \"%s\"",
- ((Mesh *) ob->data)->mat[i]->id.name + 2, i, ob->id.name + 2);
+ mat->id.name + 2, i, ob->id.name + 2);
}
else {
- BKE_reportf(reports, RPT_ERROR,
- "No active image found in material (%d) for object \"%s\"",
+ BKE_reportf(reports, RPT_INFO,
+ "No active image found in material slot (%d) for object \"%s\"",
i, ob->id.name + 2);
}
- return false;
+ continue;
}
image->id.tag |= LIB_TAG_DOIT;
@@ -566,7 +563,11 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
Image *image;
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
- if ((image->id.tag & LIB_TAG_DOIT)) {
+ /* Some materials have no image, we just ignore those cases. */
+ if (image == NULL) {
+ bake_images->lookup[i] = -1;
+ }
+ else if (image->id.tag & LIB_TAG_DOIT) {
for (j = 0; j < i; j++) {
if (bake_images->data[j].image == image) {
bake_images->lookup[i] = j;
@@ -1028,7 +1029,7 @@ cage_cleanup:
}
else {
/* if everything else fails, use the material index */
- char tmp[4];
+ char tmp[5];
sprintf(tmp, "%d", i % 1000);
BLI_path_suffix(name, FILE_MAX, tmp, "_");
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index edd7b5dd1be..4a96a2e2200 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -773,9 +773,9 @@ static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
/* now copy it, this also works without logicbricks! */
clear_sca_new_poins_ob(ob);
- copy_sensors(&base->object->sensors, &ob->sensors);
- copy_controllers(&base->object->controllers, &ob->controllers);
- copy_actuators(&base->object->actuators, &ob->actuators);
+ copy_sensors(&base->object->sensors, &ob->sensors, 0);
+ copy_controllers(&base->object->controllers, &ob->controllers, 0);
+ copy_actuators(&base->object->actuators, &ob->actuators, 0);
set_sca_new_poins_ob(base->object);
/* some menu settings */
@@ -934,7 +934,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
base->object->collision_boundtype = ob->collision_boundtype;
}
base->object->margin = ob->margin;
- base->object->bsoft = copy_bulletsoftbody(ob->bsoft);
+ base->object->bsoft = copy_bulletsoftbody(ob->bsoft, 0);
}
else if (event == 17) { /* tex space */
@@ -1042,7 +1042,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
base->object->softflag = ob->softflag;
if (base->object->soft) sbFree(base->object->soft);
- base->object->soft = copy_softbody(ob->soft, false);
+ base->object->soft = copy_softbody(ob->soft, 0);
if (!modifiers_findByType(base->object, eModifierType_Softbody)) {
BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody));
@@ -1158,13 +1158,16 @@ void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object)
/* add/remove modifier as needed */
if (!md) {
- if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) && ELEM(pd->forcefield, PFIELD_GUIDE, PFIELD_TEXTURE) == 0)
- if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE))
+ if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) && !ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
+ if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface);
+ }
+ }
}
else {
- if (!pd || pd->shape != PFIELD_SHAPE_SURFACE || pd->forcefield != PFIELD_FORCE)
+ if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) || ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
ED_object_modifier_remove(NULL, bmain, object, md);
+ }
}
}
@@ -2106,9 +2109,9 @@ static int logicbricks_copy_exec(bContext *C, wmOperator *UNUSED(op))
/* now copy it, this also works without logicbricks! */
clear_sca_new_poins_ob(ob);
- copy_sensors(&ob_iter->sensors, &ob->sensors);
- copy_controllers(&ob_iter->controllers, &ob->controllers);
- copy_actuators(&ob_iter->actuators, &ob->actuators);
+ copy_sensors(&ob_iter->sensors, &ob->sensors, 0);
+ copy_controllers(&ob_iter->controllers, &ob->controllers, 0);
+ copy_actuators(&ob_iter->actuators, &ob->actuators, 0);
set_sca_new_poins_ob(ob_iter);
/* some menu settings */
@@ -2169,7 +2172,7 @@ static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op))
copy_v3_v3(ob_iter->anisotropicFriction, ob->anisotropicFriction);
ob_iter->collision_boundtype = ob->collision_boundtype;
ob_iter->margin = ob->margin;
- ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft);
+ ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft, 0);
if (ob->restrictflag & OB_RESTRICT_RENDER)
ob_iter->restrictflag |= OB_RESTRICT_RENDER;
else
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 0fe43c44d7d..568778c0a86 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -528,8 +528,7 @@ static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
if (!group)
return OPERATOR_CANCELLED;
- BKE_libblock_unlink(bmain, group, false, false);
- BKE_libblock_free(bmain, group);
+ BKE_libblock_delete(bmain, group);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 7ec43b02b38..d5b516257a1 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1581,13 +1581,13 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
break;
case MAKE_LINKS_ANIMDATA:
- BKE_animdata_copy_id((ID *)ob_dst, (ID *)ob_src, false);
+ BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, false);
if (ob_dst->data && ob_src->data) {
if (ID_IS_LINKED_DATABLOCK(obdata_id)) {
is_lib = true;
break;
}
- BKE_animdata_copy_id((ID *)ob_dst->data, (ID *)ob_src->data, false);
+ BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, false);
}
DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
@@ -2137,7 +2137,9 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
IDP_RelinkProperty(scene->gpd->id.properties);
}
- IDP_RelinkProperty(scene->world->id.properties);
+ if (scene->world) {
+ IDP_RelinkProperty(scene->world->id.properties);
+ }
if (scene->clip) {
IDP_RelinkProperty(scene->clip->id.properties);
@@ -2149,24 +2151,6 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
/******************************* Make Local ***********************************/
-/* helper for below, ma was checked to be not NULL */
-static void make_local_makelocalmaterial(Material *ma)
-{
- AnimData *adt;
- int b;
-
- id_make_local(G.main, &ma->id, false, false);
-
- for (b = 0; b < MAX_MTEX; b++)
- if (ma->mtex[b] && ma->mtex[b]->tex)
- id_make_local(G.main, &ma->mtex[b]->tex->id, false, false);
-
- adt = BKE_animdata_from_id(&ma->id);
- if (adt) BKE_animdata_make_local(adt);
-
- /* nodetree? XXX */
-}
-
enum {
MAKE_LOCAL_SELECT_OB = 1,
MAKE_LOCAL_SELECT_OBDATA = 2,
@@ -2252,123 +2236,142 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
return changed;
}
-static int make_local_exec(bContext *C, wmOperator *op)
+static void make_local_animdata_tag_strips(ListBase *strips)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- AnimData *adt;
- ParticleSystem *psys;
- Material *ma, ***matarar;
- Lamp *la;
- ID *id;
- const int mode = RNA_enum_get(op->ptr, "type");
- int a, b;
-
- if (mode == MAKE_LOCAL_ALL) {
- /* de-select so the user can differentiate newly instanced from existing objects */
- BKE_scene_base_deselect_all(scene);
+ NlaStrip *strip;
- if (make_local_all__instance_indirect_unused(bmain, scene)) {
- BKE_report(op->reports, RPT_INFO,
- "Orphan library objects added to the current scene to avoid loss");
+ for (strip = strips->first; strip; strip = strip->next) {
+ if (strip->act) {
+ strip->act->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+ if (strip->remap && strip->remap->target) {
+ strip->remap->target->id.tag &= ~LIB_TAG_PRE_EXISTING;
}
- BKE_library_make_local(bmain, NULL, NULL, false, false); /* NULL is all libs */
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ make_local_animdata_tag_strips(&strip->strips);
}
+}
- tag_localizable_objects(C, mode);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- continue;
+/* Tag all actions used by given animdata to be made local. */
+static void make_local_animdata_tag(AnimData *adt)
+{
+ if (adt) {
+ /* Actions - Active and Temp */
+ if (adt->action) {
+ adt->action->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+ if (adt->tmpact) {
+ adt->tmpact->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+ /* Remaps */
+ if (adt->remap && adt->remap->target) {
+ adt->remap->target->id.tag &= ~LIB_TAG_PRE_EXISTING;
}
- if (ob->id.lib)
- id_make_local(bmain, &ob->id, false, false);
- }
- CTX_DATA_END;
+ /* Drivers */
+ /* TODO: need to handle the ID-targets too? */
- /* maybe object pointers */
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if (ob->id.lib == NULL) {
- ID_NEW_REMAP(ob->parent);
+ /* NLA Data */
+ for (NlaTrack *nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ make_local_animdata_tag_strips(&nlt->strips);
}
}
- CTX_DATA_END;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- continue;
- }
+}
- id = ob->data;
+static void make_local_material_tag(Material *ma)
+{
+ if (ma) {
+ ma->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(&ma->id));
- if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) {
- id_make_local(bmain, id, false, false);
- adt = BKE_animdata_from_id(id);
- if (adt) BKE_animdata_make_local(adt);
+ /* About nodetrees: root one is made local together with material, others we keep linked for now... */
- /* tag indirect data direct */
- matarar = give_matarar(ob);
- if (matarar) {
- for (a = 0; a < ob->totcol; a++) {
- ma = (*matarar)[a];
- if (ma)
- id_lib_extern(&ma->id);
- }
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (ma->mtex[a] && ma->mtex[a]->tex) {
+ ma->mtex[a]->tex->id.tag &= ~LIB_TAG_PRE_EXISTING;
}
}
+ }
+}
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- id_make_local(bmain, &psys->part->id, false, false);
+static int make_local_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ParticleSystem *psys;
+ Material *ma, ***matarar;
+ Lamp *la;
+ const int mode = RNA_enum_get(op->ptr, "type");
+ int a;
+
+ /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
+ if (mode == MAKE_LOCAL_ALL) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
+
+ /* de-select so the user can differentiate newly instanced from existing objects */
+ BKE_scene_base_deselect_all(scene);
- adt = BKE_animdata_from_id(&ob->id);
- if (adt) BKE_animdata_make_local(adt);
+ if (make_local_all__instance_indirect_unused(bmain, scene)) {
+ BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss");
+ }
}
- CTX_DATA_END;
+ else {
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+ tag_localizable_objects(C, mode);
- if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) {
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
continue;
}
- if (ob->type == OB_LAMP) {
- la = ob->data;
-
- for (b = 0; b < MAX_MTEX; b++)
- if (la->mtex[b] && la->mtex[b]->tex)
- id_make_local(bmain, &la->mtex[b]->tex->id, false, false);
+ ob->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(&ob->id));
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ psys->part->id.tag &= ~LIB_TAG_PRE_EXISTING;
}
- else {
+
+ if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) {
for (a = 0; a < ob->totcol; a++) {
ma = ob->mat[a];
- if (ma)
- make_local_makelocalmaterial(ma);
+ if (ma) {
+ make_local_material_tag(ma);
+ }
}
matarar = (Material ***)give_matarar(ob);
if (matarar) {
for (a = 0; a < ob->totcol; a++) {
ma = (*matarar)[a];
- if (ma)
- make_local_makelocalmaterial(ma);
+ if (ma) {
+ make_local_material_tag(ma);
+ }
+ }
+ }
+
+ if (ob->type == OB_LAMP) {
+ BLI_assert(ob->data != NULL);
+ la = ob->data;
+ for (a = 0; a < MAX_MTEX; a++) {
+ if (la->mtex[a] && la->mtex[a]->tex) {
+ la->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
}
}
}
+
+ if (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL) && ob->data != NULL) {
+ ID *ob_data = ob->data;
+ ob_data->tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(ob_data));
+ }
}
CTX_DATA_END;
}
- BKE_main_id_clear_newpoins(bmain);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libs */
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 4d7d7df0d2f..6491da4c23c 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -414,7 +414,10 @@ static void ignore_parent_tx(Main *bmain, Scene *scene, Object *ob)
}
}
-static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_loc, bool apply_rot, bool apply_scale)
+static int apply_objects_internal(
+ bContext *C, ReportList *reports,
+ bool apply_loc, bool apply_rot, bool apply_scale,
+ bool do_props)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -531,7 +534,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
BKE_mesh_calc_normals(me);
}
else if (ob->type == OB_ARMATURE) {
- ED_armature_apply_transform(ob, mat);
+ ED_armature_apply_transform(ob, mat, do_props);
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;
@@ -540,12 +543,12 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
}
else if (ob->type == OB_MBALL) {
MetaBall *mb = ob->data;
- BKE_mball_transform(mb, mat);
+ BKE_mball_transform(mb, mat, do_props);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
scale = mat3_to_scale(rsmat);
- BKE_curve_transform_ex(cu, mat, true, scale);
+ BKE_curve_transform_ex(cu, mat, true, do_props, scale);
}
else if (ob->type == OB_FONT) {
Curve *cu = ob->data;
@@ -561,7 +564,9 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
tb->h *= scale;
}
- cu->fsize *= scale;
+ if (do_props) {
+ cu->fsize *= scale;
+ }
}
else if (ob->type == OB_CAMERA) {
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
@@ -677,9 +682,10 @@ static int object_transform_apply_exec(bContext *C, wmOperator *op)
const bool loc = RNA_boolean_get(op->ptr, "location");
const bool rot = RNA_boolean_get(op->ptr, "rotation");
const bool sca = RNA_boolean_get(op->ptr, "scale");
+ const bool do_props = RNA_boolean_get(op->ptr, "properties");
if (loc || rot || sca) {
- return apply_objects_internal(C, op->reports, loc, rot, sca);
+ return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
}
else {
/* allow for redo */
@@ -704,6 +710,8 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "location", 0, "Location", "");
RNA_def_boolean(ot->srna, "rotation", 0, "Rotation", "");
RNA_def_boolean(ot->srna, "scale", 0, "Scale", "");
+ RNA_def_boolean(ot->srna, "properties", true, "Apply Properties",
+ "Modify properties such as curve vertex radius, font size and bone envelope");
}
/********************* Set Object Center ************************/
@@ -712,7 +720,8 @@ enum {
GEOMETRY_TO_ORIGIN = 0,
ORIGIN_TO_GEOMETRY,
ORIGIN_TO_CURSOR,
- ORIGIN_TO_CENTER_OF_MASS
+ ORIGIN_TO_CENTER_OF_MASS_SURFACE,
+ ORIGIN_TO_CENTER_OF_MASS_VOLUME,
};
static int object_origin_set_exec(bContext *C, wmOperator *op)
@@ -866,10 +875,21 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (obedit == NULL && ob->type == OB_MESH) {
Mesh *me = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (centermode == ORIGIN_TO_CENTER_OF_MASS) { BKE_mesh_center_centroid(me, cent); }
- else if (around == V3D_AROUND_CENTER_MEAN) { BKE_mesh_center_median(me, cent); }
- else { BKE_mesh_center_bounds(me, cent); }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
+ BKE_mesh_center_of_surface(me, cent);
+ }
+ else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) {
+ BKE_mesh_center_of_volume(me, cent);
+ }
+ else if (around == V3D_AROUND_CENTER_MEAN) {
+ BKE_mesh_center_median(me, cent);
+ }
+ else {
+ BKE_mesh_center_bounds(me, cent);
+ }
negate_v3_v3(cent_neg, cent);
BKE_mesh_translate(me, cent_neg, 1);
@@ -923,8 +943,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
cent[2] = 0.0f;
- cu->xof = cu->xof - (cent[0] / cu->fsize);
- cu->yof = cu->yof - (cent[1] / cu->fsize);
+ cu->xof = cu->xof - cent[0];
+ cu->yof = cu->yof - cent[1];
tot_change++;
cu->id.tag |= LIB_TAG_DOIT;
@@ -1077,11 +1097,14 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
static EnumPropertyItem prop_set_center_types[] = {
{GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"},
{ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry",
- "Move object origin to center of object geometry"},
+ "Calculate the center of geometry based on the current pivot point (median, otherwise bounding-box)"},
{ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor",
- "Move object origin to position of the 3D cursor"},
- {ORIGIN_TO_CENTER_OF_MASS, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass",
- "Move object origin to the object center of mass (assuming uniform density)"},
+ "Move object origin to position of the 3D cursor"},
+ /* Intentional naming mismatch since some scripts refer to this. */
+ {ORIGIN_TO_CENTER_OF_MASS_SURFACE, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass (Surface)",
+ "Calculate the center of mass from the surface area"},
+ {ORIGIN_TO_CENTER_OF_MASS_VOLUME, "ORIGIN_CENTER_OF_VOLUME", 0, "Origin to Center of Mass (Volume)",
+ "Calculate the center of mass from the volume (must be manifold geometry with consistent normals)"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 3c406764157..19893c79db4 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -238,6 +238,9 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co
}
return false;
}
+
+ default:
+ break;
}
}
@@ -1712,17 +1715,11 @@ static void vgroup_invert_subset(Object *ob,
}
}
-enum {
- WEIGHT_SMOOTH_ALL = -1,
- WEIGHT_SMOOTH_DESELECT = false,
- WEIGHT_SMOOTH_SELECT = true,
-};
-
static void vgroup_smooth_subset(
Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
const int subset_count,
const float fac, const int repeat,
- const float fac_expand, const int source)
+ const float fac_expand)
{
const float ifac = 1.0f - fac;
MDeformVert **dvert_array = NULL;
@@ -1730,6 +1727,8 @@ static void vgroup_smooth_subset(
int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
+ const bool use_select = vertex_group_use_vert_sel(ob);
+ const bool use_hide = use_select;
const int expand_sign = signum_i(fac_expand);
const float expand = fabsf(fac_expand);
@@ -1773,19 +1772,26 @@ static void vgroup_smooth_subset(
verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__);
STACK_INIT(verts_used, dvert_tot);
+#define IS_BM_VERT_READ(v) \
+ (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true)
+#define IS_BM_VERT_WRITE(v) \
+ (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true)
+
+#define IS_ME_VERT_READ(v) \
+ (use_hide ? (((v)->flag & ME_HIDE) == 0) : true)
+#define IS_ME_VERT_WRITE(v) \
+ (use_select ? (((v)->flag & SELECT) != 0) : true)
/* initialize used verts */
if (bm) {
for (int i = 0; i < dvert_tot; i++) {
BMVert *v = BM_vert_at_index(bm, i);
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ if (IS_BM_VERT_WRITE(v)) {
BMIter eiter;
BMEdge *e;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
BMVert *v_other = BM_edge_other_vert(e, v);
- if ((source == WEIGHT_SMOOTH_ALL) ||
- (source == (BM_elem_flag_test(v_other, BM_ELEM_SELECT) != 0)))
- {
+ if (IS_BM_VERT_READ(v_other)) {
STACK_PUSH(verts_used, i);
break;
}
@@ -1795,13 +1801,12 @@ static void vgroup_smooth_subset(
}
else {
for (int i = 0; i < dvert_tot; i++) {
- MVert *v = &me->mvert[i];
- if (v->flag & SELECT) {
+ const MVert *v = &me->mvert[i];
+ if (IS_ME_VERT_WRITE(v)) {
for (int j = 0; j < emap[i].count; j++) {
- MVert *v_other = &me->mvert[emap[i].indices[j]];
- if ((source == WEIGHT_SMOOTH_ALL) ||
- (source == ((v_other->flag & SELECT) != 0)))
- {
+ const MEdge *e = &me->medge[emap[i].indices[j]];
+ const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1];
+ if (IS_ME_VERT_READ(v_other)) {
STACK_PUSH(verts_used, i);
break;
}
@@ -1854,13 +1859,11 @@ static void vgroup_smooth_subset(
BMEdge *e;
/* checked already */
- BLI_assert(BM_elem_flag_test(v, BM_ELEM_SELECT));
+ BLI_assert(IS_BM_VERT_WRITE(v));
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
BMVert *v_other = BM_edge_other_vert(e, v);
- if ((source == WEIGHT_SMOOTH_ALL) ||
- (source == (BM_elem_flag_test(v_other, BM_ELEM_SELECT) != 0)))
- {
+ if (IS_BM_VERT_READ(v_other)) {
const int i_other = BM_elem_index_get(v_other);
WEIGHT_ACCUMULATE;
@@ -1871,16 +1874,14 @@ static void vgroup_smooth_subset(
int j;
/* checked already */
- BLI_assert(me->mvert[i].flag & SELECT);
+ BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i]));
for (j = 0; j < emap[i].count; j++) {
MEdge *e = &me->medge[emap[i].indices[j]];
const int i_other = (e->v1 == i ? e->v2 : e->v1);
MVert *v_other = &me->mvert[i_other];
- if ((source == WEIGHT_SMOOTH_ALL) ||
- (source == ((v_other->flag & SELECT) != 0)))
- {
+ if (IS_ME_VERT_READ(v_other)) {
WEIGHT_ACCUMULATE;
}
}
@@ -1904,6 +1905,11 @@ static void vgroup_smooth_subset(
ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true);
}
+#undef IS_BM_VERT_READ
+#undef IS_BM_VERT_WRITE
+#undef IS_ME_VERT_READ
+#undef IS_ME_VERT_WRITE
+
MEM_freeN(weight_accum_curr);
MEM_freeN(weight_accum_prev);
MEM_freeN(verts_used);
@@ -2497,7 +2503,7 @@ static int UNUSED_FUNCTION(vertex_group_poll_edit) (bContext *C)
}
/* editmode _or_ weight paint vertex sel */
-static int vertex_group_vert_select_poll_ex(bContext *C, const short ob_type_flag)
+static int vertex_group_vert_poll_ex(bContext *C, const bool needs_select, const short ob_type_flag)
{
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
@@ -2513,12 +2519,17 @@ static int vertex_group_vert_select_poll_ex(bContext *C, const short ob_type_fla
return true;
}
else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (BKE_object_is_in_wpaint_select_vert(ob)) {
- return true;
+ if (needs_select) {
+ if (BKE_object_is_in_wpaint_select_vert(ob)) {
+ return true;
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
+ return false;
+ }
}
else {
- CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
- return false;
+ return true;
}
}
else {
@@ -2526,15 +2537,31 @@ static int vertex_group_vert_select_poll_ex(bContext *C, const short ob_type_fla
}
}
+#if 0
+static int vertex_group_vert_poll(bContext *C)
+{
+ return vertex_group_vert_poll_ex(C, false, 0);
+}
+#endif
+
+
+static int vertex_group_mesh_vert_poll(bContext *C)
+{
+ return vertex_group_vert_poll_ex(C, false, (1 << OB_MESH));
+}
+
static int vertex_group_vert_select_poll(bContext *C)
{
- return vertex_group_vert_select_poll_ex(C, 0);
+ return vertex_group_vert_poll_ex(C, true, 0);
}
+#if 0
static int vertex_group_mesh_vert_select_poll(bContext *C)
{
- return vertex_group_vert_select_poll_ex(C, (1 << OB_MESH));
+ return vertex_group_vert_poll_ex(C, true, (1 << OB_MESH));
}
+#endif
+
/* editmode _or_ weight paint vertex sel and active group unlocked */
static int vertex_group_vert_select_unlocked_poll(bContext *C)
@@ -3081,13 +3108,12 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
const float fac = RNA_float_get(op->ptr, "factor");
const int repeat = RNA_int_get(op->ptr, "repeat");
eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- const int source = RNA_enum_get(op->ptr, "source");
const float fac_expand = RNA_float_get(op->ptr, "expand");
int subset_count, vgroup_tot;
const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand, source);
+ vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand);
MEM_freeN((void *)vgroup_validmap);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -3099,20 +3125,13 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot)
{
- static EnumPropertyItem smooth_source_item[] = {
- {WEIGHT_SMOOTH_ALL, "ALL", 0, "All", ""},
- {WEIGHT_SMOOTH_SELECT, "SELECT", 0, "Only Selected", ""},
- {WEIGHT_SMOOTH_DESELECT, "DESELECT", 0, "Only Deselected", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
/* identifiers */
ot->name = "Smooth Vertex Weights";
ot->idname = "OBJECT_OT_vertex_group_smooth";
ot->description = "Smooth weights for selected vertices";
/* api callbacks */
- ot->poll = vertex_group_mesh_vert_select_poll;
+ ot->poll = vertex_group_mesh_vert_poll;
ot->exec = vertex_group_smooth_exec;
/* flags */
@@ -3123,7 +3142,6 @@ void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot)
RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
RNA_def_float(ot->srna, "expand", 0.0f, -1.0f, 1.0, "Expand/Contract", "Expand/contract weights", -1.0f, 1.0f);
- RNA_def_enum(ot->srna, "source", smooth_source_item, -1, "Source", "Vertices to mix with");
}
static int vertex_group_clean_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index 3d7a45843cc..edc3f6c784c 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -279,10 +279,10 @@ void DPAINT_OT_output_toggle(wmOperatorType *ot)
/***************************** Image Sequence Baking ******************************/
typedef struct DynamicPaintBakeJob {
- /* from wmJob */
- void *owner;
- short *stop, *do_update;
- float *progress;
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+ float *progress;
struct Main *bmain;
Scene *scene;
@@ -297,13 +297,13 @@ typedef struct DynamicPaintBakeJob {
static void dpaint_bake_free(void *customdata)
{
- DynamicPaintBakeJob *job = customdata;
- MEM_freeN(job);
+ DynamicPaintBakeJob *job = customdata;
+ MEM_freeN(job);
}
static void dpaint_bake_endjob(void *customdata)
{
- DynamicPaintBakeJob *job = customdata;
+ DynamicPaintBakeJob *job = customdata;
DynamicPaintCanvasSettings *canvas = job->canvas;
canvas->flags &= ~MOD_DPAINT_BAKING;
@@ -311,7 +311,7 @@ static void dpaint_bake_endjob(void *customdata)
dynamicPaint_freeSurfaceData(job->surface);
G.is_rendering = false;
- BKE_spacedata_draw_locks(false);
+ BKE_spacedata_draw_locks(false);
WM_set_locked_interface(G.main->wm.first, false);
@@ -421,26 +421,26 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- DynamicPaintBakeJob *job = customdata;
+ DynamicPaintBakeJob *job = customdata;
- job->stop = stop;
- job->do_update = do_update;
- job->progress = progress;
+ job->stop = stop;
+ job->do_update = do_update;
+ job->progress = progress;
job->start = PIL_check_seconds_timer();
job->success = 1;
- G.is_break = false; /* reset BKE_blender_test_break*/
+ G.is_break = false; /* reset BKE_blender_test_break*/
/* 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_rendering = true;
+ BKE_spacedata_draw_locks(true);
dynamicPaint_bakeImageSequence(job);
- *do_update = true;
- *stop = 0;
+ *do_update = true;
+ *stop = 0;
}
/*
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index e22a145b3a6..72c5a74aee9 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -424,7 +424,6 @@ static bool PE_create_shape_tree(PEData *data, Object *shapeob)
return false;
}
- DM_ensure_looptri(dm);
return (bvhtree_from_mesh_looptri(&data->shape_bvh, dm, 0.0f, 4, 8) != NULL);
}
@@ -4419,7 +4418,7 @@ void PE_undo_push(Scene *scene, const char *str)
undo= undo->prev;
}
if (undo) {
- while (edit->undo.first!=undo) {
+ while (edit->undo.first != undo) {
PTCacheUndo *first= edit->undo.first;
BLI_remlink(&edit->undo, first);
free_PTCacheUndo(first);
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 4a4474868a2..29b652e1326 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -1035,7 +1035,7 @@ static bool copy_particle_systems_to_object(Main *bmain,
psys_from;
psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
- psys = BKE_object_copy_particlesystem(psys_from);
+ psys = BKE_object_copy_particlesystem(psys_from, 0);
tmp_psys[i] = psys;
if (psys_start == NULL)
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index e81aa584586..f36ebb3715e 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -99,45 +99,45 @@ static int ptcache_job_break(void *customdata)
static void ptcache_job_update(void *customdata, float progress, int *cancel)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
- if (ptcache_job_break(job)) {
- *cancel = 1;
- }
+ if (ptcache_job_break(job)) {
+ *cancel = 1;
+ }
- *(job->do_update) = true;
- *(job->progress) = progress;
+ *(job->do_update) = true;
+ *(job->progress) = progress;
}
static void ptcache_job_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
- job->stop = stop;
- job->do_update = do_update;
- job->progress = progress;
+ job->stop = stop;
+ job->do_update = do_update;
+ job->progress = progress;
- G.is_break = false;
+ G.is_break = false;
- /* XXX annoying hack: needed to prevent data corruption when changing
- * scene frame in separate threads
- */
- G.is_rendering = true;
- BKE_spacedata_draw_locks(true);
+ /* XXX annoying hack: needed to prevent data corruption when changing
+ * scene frame in separate threads
+ */
+ G.is_rendering = true;
+ BKE_spacedata_draw_locks(true);
BKE_ptcache_bake(job->baker);
- *do_update = true;
- *stop = 0;
+ *do_update = true;
+ *stop = 0;
}
static void ptcache_job_endjob(void *customdata)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
Scene *scene = job->baker->scene;
- G.is_rendering = false;
- BKE_spacedata_draw_locks(false);
+ G.is_rendering = false;
+ BKE_spacedata_draw_locks(false);
WM_set_locked_interface(G.main->wm.first, false);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 43b1d033d23..da14e72f887 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -1171,7 +1171,7 @@ static void render_update_resolution(Render *re, const RenderPreview *rp,
}
if (rp->has_freestyle) {
- if (rp->resolution_divider == 1) {
+ if (rp->resolution_divider == BKE_render_preview_pixel_size(&rp->scene->r)) {
RE_ChangeModeFlag(re, R_EDGE_FRS, false);
}
else {
@@ -1237,7 +1237,7 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
use_border = render_view3d_disprect(rp->scene, rp->ar, rp->v3d,
rp->rv3d, &cliprct);
- if ((update_flag & (PR_UPDATE_RENDERSIZE | PR_UPDATE_DATABASE)) || rstats->convertdone == 0) {
+ if ((update_flag & (PR_UPDATE_RENDERSIZE | PR_UPDATE_DATABASE | PR_UPDATE_VIEW)) || rstats->convertdone == 0) {
RenderData rdata;
/* no osa, blur, seq, layers, savebuffer etc for preview render */
@@ -1312,11 +1312,12 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
RE_updateRenderInstances(re, ob_inst_update_flag);
for (;;) {
+ int pixel_size = BKE_render_preview_pixel_size(&rp->scene->r);
if (first_time == false) {
if (restore)
RE_DataBase_IncrementalView(re, rp->viewmat, 1);
- rp->resolution_divider /= 2;
+ rp->resolution_divider = MAX2(rp->resolution_divider/2, pixel_size);
*do_update = 1;
render_update_resolution(re, rp, use_border, &cliprct);
@@ -1333,7 +1334,7 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
first_time = false;
- if (*stop || rp->resolution_divider == 1) {
+ if (*stop || rp->resolution_divider == pixel_size) {
break;
}
}
@@ -1435,7 +1436,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C)
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
int width = ar->winx, height = ar->winy;
- int divider = 1;
+ int divider = BKE_render_preview_pixel_size(&scene->r);
int resolution_threshold = scene->r.preview_start_resolution *
scene->r.preview_start_resolution;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index fa18b82507e..35d772afae7 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -1180,7 +1180,7 @@ void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rec
ip.bmain = bmain;
ip.scene = scene;
- ip.owner = id;
+ ip.owner = BKE_previewimg_id_ensure(id);
ip.id = id;
icon_preview_add_size(&ip, rect, sizex, sizey);
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 0878636d0fa..d252d764b42 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -1298,16 +1298,16 @@ static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
switch (freestyle_get_modifier_type(&ptr)) {
case LS_MODIFIER_TYPE_COLOR:
- BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier);
+ BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0);
break;
case LS_MODIFIER_TYPE_ALPHA:
- BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier);
+ BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0);
break;
case LS_MODIFIER_TYPE_THICKNESS:
- BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier);
+ BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0);
break;
case LS_MODIFIER_TYPE_GEOMETRY:
- BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier);
+ BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0);
break;
default:
BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
@@ -1781,6 +1781,8 @@ static void copy_mtex_copybuf(ID *id)
case ID_LS:
mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
break;
+ default:
+ break;
}
if (mtex && *mtex) {
@@ -1818,7 +1820,7 @@ static void paste_mtex_copybuf(ID *id)
mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
break;
default:
- BLI_assert("invalid id type");
+ BLI_assert(!"invalid id type");
return;
}
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index c165bbfd301..293e507c2b3 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -54,6 +54,7 @@
#include "ED_armature.h"
#include "ED_gpencil.h"
+#include "ED_anim_api.h"
#include "WM_api.h"
#include "UI_interface.h"
@@ -87,7 +88,7 @@ const char *screen_context_dir[] = {
"visible_gpencil_layers", "editable_gpencil_layers", "editable_gpencil_strokes",
"active_gpencil_layer", "active_gpencil_frame", "active_gpencil_palette",
"active_gpencil_palettecolor", "active_gpencil_brush",
- "active_operator",
+ "active_operator", "selected_editable_fcurves",
NULL};
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
@@ -608,6 +609,30 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
}
+ else if (CTX_data_equals(member, "selected_editable_fcurves"))
+ {
+ bAnimContext ac;
+
+ if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_ACTION, SPACE_IPO)) {
+ bAnimListElem *ale;
+ ListBase anim_data = {NULL, NULL};
+
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS | ANIMFILTER_SEL) |
+ (ac.spacetype == SPACE_IPO ? ANIMFILTER_CURVE_VISIBLE : ANIMFILTER_LIST_VISIBLE);
+
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_FCURVE)
+ CTX_data_list_add(result, ale->id, &RNA_FCurve, ale->data);
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
else {
return 0; /* not found */
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 7d2b77028fc..71b00a0a7c6 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -467,7 +467,7 @@ bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name)
bScreen *sc;
ScrVert *sv1, *sv2, *sv3, *sv4;
- sc = BKE_libblock_alloc(G.main, ID_SCR, name);
+ sc = BKE_libblock_alloc(G.main, ID_SCR, name, 0);
sc->scene = scene;
sc->do_refresh = true;
sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN;
@@ -1228,6 +1228,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
winrct.ymax = winsize_y - 1;
/* header size depends on DPI, let's verify */
+ WM_window_set_dpi(win);
screen_refresh_headersizes();
screen_test_scale(win->screen, winsize_x, winsize_y);
@@ -1762,7 +1763,7 @@ bool ED_screen_delete_scene(bContext *C, Scene *scene)
BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
- BKE_libblock_free(bmain, scene);
+ BKE_libblock_free_us(bmain, scene);
return true;
}
@@ -1893,17 +1894,28 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
if (sa && sa->full) {
/* restoring back to SCREENNORMAL */
- ScrArea *old;
-
sc = sa->full; /* the old screen to restore */
oldscreen = win->screen; /* the one disappearing */
sc->state = SCREENNORMAL;
- /* find old area */
- for (old = sc->areabase.first; old; old = old->next)
- if (old->full) break;
- if (old == NULL) {
+ /* find old area to restore from */
+ ScrArea *fullsa = NULL;
+ for (ScrArea *old = sc->areabase.first; old; old = old->next) {
+ /* area to restore from is always first */
+ if (old->full && !fullsa) {
+ fullsa = old;
+ }
+
+ /* clear full screen state */
+ old->full = NULL;
+ old->flag &= ~AREA_TEMP_INFO;
+ }
+
+ sa->flag &= ~AREA_TEMP_INFO;
+ sa->full = NULL;
+
+ if (fullsa == NULL) {
if (G.debug & G_DEBUG)
printf("%s: something wrong in areafullscreen\n", __func__);
return NULL;
@@ -1916,9 +1928,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
}
- ED_area_data_swap(old, sa);
- if (sa->flag & AREA_TEMP_INFO) sa->flag &= ~AREA_TEMP_INFO;
- old->full = NULL;
+ ED_area_data_swap(fullsa, sa);
/* animtimer back */
sc->animtimer = oldscreen->animtimer;
@@ -1926,7 +1936,6 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
ED_screen_set(C, sc);
- BKE_screen_free(oldscreen);
BKE_libblock_free(CTX_data_main(C), oldscreen);
/* After we've restored back to SCREENNORMAL, we have to wait with
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 9dbc082c119..27e19ca1fc3 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -2260,25 +2260,28 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
BLI_dlrbTree_linkedlist_sync(&keys);
/* find matching keyframe in the right direction */
- do {
- if (next)
- ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra);
- else
- ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra);
-
- if (ak) {
- if (CFRA != (int)ak->cfra) {
- /* this changes the frame, so set the frame and we're done */
- CFRA = (int)ak->cfra;
- done = true;
+ if (next)
+ ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra);
+ else
+ ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra);
+
+ while ((ak != NULL) && (done == false)) {
+ if (CFRA != (int)ak->cfra) {
+ /* this changes the frame, so set the frame and we're done */
+ CFRA = (int)ak->cfra;
+ done = true;
+ }
+ else {
+ /* take another step... */
+ if (next) {
+ ak = ak->next;
}
else {
- /* make this the new starting point for the search */
- cfra = ak->cfra;
+ ak = ak->prev;
}
}
- } while ((ak != NULL) && (done == false));
-
+ }
+
/* free temp stuff */
BLI_dlrbTree_free(&keys);
@@ -3756,7 +3759,7 @@ static int screen_animation_cancel_exec(bContext *C, wmOperator *op)
bScreen *screen = ED_screen_animation_playing(CTX_wm_manager(C));
if (screen) {
- if (RNA_boolean_get(op->ptr, "restore_frame")) {
+ if (RNA_boolean_get(op->ptr, "restore_frame") && screen->animtimer) {
ScreenAnimData *sad = screen->animtimer->customdata;
Scene *scene = CTX_data_scene(C);
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 4f93c12385d..09b0847b306 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -797,6 +797,7 @@ static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus
float map_alpha = (rgb[3] == 0.0f) ? rrgbf[3] : rrgbf[3] / rgb[3];
mul_v3_v3fl(rrgbf, rgb, map_alpha);
+ rrgbf[3] = rgb[3];
}
else {
unsigned char straight[4];
@@ -806,6 +807,7 @@ static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus
rrgb[0] = straight[0];
rrgb[1] = straight[1];
rrgb[2] = straight[2];
+ rrgb[3] = straight[3];
}
}
@@ -995,7 +997,7 @@ static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos, short tile)
IMB_rectblend(ibufb, ibufb, ibuf, NULL, NULL, NULL, 0, region[a].destx, region[a].desty,
region[a].destx, region[a].desty,
region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, IMB_BLEND_COPY_RGB, false);
+ region[a].width, region[a].height, IMB_BLEND_COPY, false);
}
static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
@@ -1096,6 +1098,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
/* lift from canvas */
if (s->tool == PAINT_TOOL_SOFTEN) {
paint_2d_lift_soften(s, s->canvas, ibufb, bpos, tile);
+ blend = IMB_BLEND_INTERPOLATE;
}
else if (s->tool == PAINT_TOOL_SMEAR) {
if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
@@ -1103,6 +1106,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
paint_2d_convert_brushco(ibufb, lastpos, blastpos);
paint_2d_lift_smear(s->canvas, ibufb, blastpos, tile);
+ blend = IMB_BLEND_INTERPOLATE;
}
else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
liftpos[0] = pos[0] - offset[0] * s->canvas->x;
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index d0f1cc99b8d..8586eb42bec 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3712,8 +3712,12 @@ static void project_paint_prepare_all_faces(
}
/* don't allow using the same inage for painting and stencilling */
- if (slot->ima == ps->stencil_ima)
+ if (slot->ima == ps->stencil_ima) {
+ /* While this shouldn't be used, face-winding reads all polys.
+ * It's less trouble to set all faces to valid UV's, avoiding NULL checks all over. */
+ ps->dm_mloopuv[lt->poly] = mloopuv_base;
continue;
+ }
tpage = slot->ima;
}
@@ -4291,7 +4295,7 @@ static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, f
return;
}
else {
- blend_color_interpolate_float(rgba, rgba, projPixel->pixel.f_pt, mask);
+ blend_color_interpolate_float(rgba, projPixel->pixel.f_pt, rgba, mask);
}
BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
@@ -4750,6 +4754,9 @@ static void *do_projectpaint_thread(void *ph_v)
copy_v3_v3(texrgb, texrgba);
mask *= texrgba[3];
}
+ else {
+ zero_v3(texrgb);
+ }
/* extra mask for normal, layer stencil, .. */
mask *= ((float)projPixel->mask) * (1.0f / 65535.0f);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index fc15556b6d9..8ceded9c42a 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -821,8 +821,6 @@ static int brush_uv_sculpt_tool_set_exec(bContext *C, wmOperator *op)
static void BRUSH_OT_uv_sculpt_tool_set(wmOperatorType *ot)
{
- /* from rna_scene.c */
- extern EnumPropertyItem uv_sculpt_tool_items[];
/* identifiers */
ot->name = "UV Sculpt Tool Set";
ot->description = "Set the UV sculpt tool";
@@ -836,7 +834,7 @@ static void BRUSH_OT_uv_sculpt_tool_set(wmOperatorType *ot)
ot->flag = 0;
/* props */
- ot->prop = RNA_def_enum(ot->srna, "tool", uv_sculpt_tool_items, 0, "Tool", "");
+ ot->prop = RNA_def_enum(ot->srna, "tool", rna_enum_uv_sculpt_tool_items, 0, "Tool", "");
}
/***** Stencil Control *****/
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 31c471c3517..10628d8cccb 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -426,7 +426,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active_from_context(C);
Palette *palette = BKE_paint_palette(paint);
- PaletteColor *color;
+ PaletteColor *color = NULL;
Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
unsigned int col;
const unsigned char *cp;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 746c560090d..0f674d32985 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4483,8 +4483,11 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op,
const float mouse[2])
{
/* Don't start the stroke until mouse goes over the mesh.
- * note: mouse will only be null when re-executing the saved stroke. */
- if (!mouse || over_mesh(C, op, mouse[0], mouse[1])) {
+ * note: mouse will only be null when re-executing the saved stroke.
+ * We have exception for 'exec' strokes since they may not set 'mouse', only 'location', see: T52195. */
+ if (((op->flag & OP_IS_INVOKE) == 0) ||
+ (mouse == NULL) || over_mesh(C, op, mouse[0], mouse[1]))
+ {
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 553be0ad290..17edbc6cc1d 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -262,6 +262,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
{
/* loop over data selecting */
switch (ale->type) {
+#if 0 /* XXXX: Keyframes are not currently shown here */
case ANIMTYPE_GPDATABLOCK:
{
bGPdata *gpd = ale->data;
@@ -271,6 +272,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
}
break;
}
+#endif
case ANIMTYPE_GPLAYER:
ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
break;
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 72de7e5c81c..1d67ac620b0 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -470,7 +470,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts)
}
else {
/* set one user as active based on active index */
- if (ct->index == BLI_listbase_count_ex(&ct->users, ct->index + 1))
+ if (ct->index >= BLI_listbase_count_ex(&ct->users, ct->index + 1))
ct->index = 0;
ct->user = BLI_findlink(&ct->users, ct->index);
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 695d04d3850..a71b2baa96f 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -365,9 +365,11 @@ static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int
static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track)
{
+#define MAX_STATIC_PATH 64
int count = sc->path_length;
int i, a, b, curindex = -1;
- float path[102][2];
+ float path_static[(MAX_STATIC_PATH + 1) * 2][2];
+ float (*path)[2];
int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr, start_frame;
MovieTrackingMarker *marker;
@@ -380,6 +382,13 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
if (marker->framenr != framenr || marker->flag & MARKER_DISABLED)
return;
+ if (count < MAX_STATIC_PATH) {
+ path = path_static;
+ }
+ else {
+ path = MEM_mallocN(sizeof(*path) * (count + 1) * 2, "path");
+ }
+
a = count;
i = framenr - 1;
while (i >= framenr - count) {
@@ -470,6 +479,11 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
glVertex2f(path[i][0], path[i][1]);
}
glEnd();
+
+ if (path != path_static) {
+ MEM_freeN(path);
+ }
+#undef MAX_STATIC_PATH
}
static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 237082f948b..58930fa2cf2 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -821,6 +821,7 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
#endif
}
+/* DO NOT make this static, this hides the symbol and breaks API generation script. */
const char *clip_context_dir[] = {"edit_movieclip", "edit_mask", NULL};
static int clip_context(const bContext *C, const char *member, bContextDataResult *result)
diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c
index 368cbeaf955..42b017e6324 100644
--- a/source/blender/editors/space_clip/tracking_ops_track.c
+++ b/source/blender/editors/space_clip/tracking_ops_track.c
@@ -212,7 +212,7 @@ static int track_markers_initjob(bContext *C,
}
}
- tmj->context = BKE_autotrack_context_new(clip, &sc->user, backwards, 1);
+ tmj->context = BKE_autotrack_context_new(clip, &sc->user, backwards, true);
clip->tracking_context = tmj->context;
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 6c33091ff01..d94aad640b7 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -277,9 +277,10 @@ typedef struct FileListFilter {
/* FileListFilter.flags */
enum {
- FLF_HIDE_DOT = 1 << 0,
- FLF_HIDE_PARENT = 1 << 1,
- FLF_HIDE_LIB_DIR = 1 << 2,
+ FLF_DO_FILTER = 1 << 0,
+ FLF_HIDE_DOT = 1 << 1,
+ FLF_HIDE_PARENT = 1 << 2,
+ FLF_HIDE_LIB_DIR = 1 << 3,
};
typedef struct FileList {
@@ -594,24 +595,27 @@ static bool is_filtered_file(FileListInternEntry *file, const char *UNUSED(root)
{
bool is_filtered = !is_hidden_file(file->relpath, filter);
- if (is_filtered && filter->filter && !FILENAME_IS_CURRPAR(file->relpath)) {
- if (file->typeflag & FILE_TYPE_DIR) {
- if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
- if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
- is_filtered = false;
+ if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ /* We only check for types if some type are enabled in filtering. */
+ if (filter->filter) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ is_filtered = false;
+ }
+ }
+ else {
+ if (!(filter->filter & FILE_TYPE_FOLDER)) {
+ is_filtered = false;
+ }
}
}
else {
- if (!(filter->filter & FILE_TYPE_FOLDER)) {
+ if (!(file->typeflag & filter->filter)) {
is_filtered = false;
}
}
}
- else {
- if (!(file->typeflag & filter->filter)) {
- is_filtered = false;
- }
- }
if (is_filtered && (filter->filter_search[0] != '\0')) {
if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
is_filtered = false;
@@ -631,28 +635,31 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis
if (BLO_library_path_explode(path, dir, &group, &name)) {
is_filtered = !is_hidden_file(file->relpath, filter);
- if (is_filtered && filter->filter && !FILENAME_IS_CURRPAR(file->relpath)) {
- if (file->typeflag & FILE_TYPE_DIR) {
- if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
- if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
- is_filtered = false;
+ if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ /* We only check for types if some type are enabled in filtering. */
+ if (filter->filter || filter->filter_id) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ is_filtered = false;
+ }
}
- }
- else {
- if (!(filter->filter & FILE_TYPE_FOLDER)) {
- is_filtered = false;
+ else {
+ if (!(filter->filter & FILE_TYPE_FOLDER)) {
+ is_filtered = false;
+ }
}
}
- }
- if (is_filtered && group) {
- if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
- is_filtered = false;
- }
- else {
- unsigned int filter_id = groupname_to_filter_id(group);
- if (!(filter_id & filter->filter_id)) {
+ if (is_filtered && group) {
+ if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
is_filtered = false;
}
+ else {
+ unsigned int filter_id = groupname_to_filter_id(group);
+ if (!(filter_id & filter->filter_id)) {
+ is_filtered = false;
+ }
+ }
}
}
if (is_filtered && (filter->filter_search[0] != '\0')) {
@@ -729,12 +736,17 @@ void filelist_filter(FileList *filelist)
MEM_freeN(filtered_tmp);
}
-void filelist_setfilter_options(FileList *filelist, const bool hide_dot, const bool hide_parent,
+void filelist_setfilter_options(FileList *filelist, const bool do_filter,
+ const bool hide_dot, const bool hide_parent,
const unsigned int filter, const unsigned int filter_id,
const char *filter_glob, const char *filter_search)
{
bool update = false;
+ if (((filelist->filter_data.flags & FLF_DO_FILTER) != 0) != (do_filter != 0)) {
+ filelist->filter_data.flags ^= FLF_DO_FILTER;
+ update = true;
+ }
if (((filelist->filter_data.flags & FLF_HIDE_DOT) != 0) != (hide_dot != 0)) {
filelist->filter_data.flags ^= FLF_HIDE_DOT;
update = true;
@@ -1104,7 +1116,10 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat
preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source);
IMB_thumb_path_unlock(preview->path);
- preview->flags = 0; /* Used to tell free func to not free anything! */
+ /* Used to tell free func to not free anything.
+ * Note that we do not care about cas result here,
+ * we only want value attribution itself to be atomic (and memory barier).*/
+ atomic_cas_uint32(&preview->flags, preview->flags, 0);
BLI_thread_queue_push(cache->previews_done, preview);
// printf("%s: End (%d)...\n", __func__, threadid);
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index f4304681780..4e9c1e0dd1d 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -68,7 +68,8 @@ int folderlist_clear_next(struct SpaceFile *sfile);
void filelist_setsorting(struct FileList *filelist, const short sort);
void filelist_sort(struct FileList *filelist);
-void filelist_setfilter_options(struct FileList *filelist, const bool hide_dot, const bool hide_parent,
+void filelist_setfilter_options(struct FileList *filelist, const bool do_filter,
+ const bool hide_dot, const bool hide_parent,
const unsigned int filter, const unsigned int filter_id,
const char *filter_glob, const char *filter_search);
void filelist_filter(struct FileList *filelist);
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 374db92297d..287b98fa589 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -223,9 +223,10 @@ static void file_refresh(const bContext *C, ScrArea *sa)
filelist_setdir(sfile->files, params->dir);
filelist_setrecursion(sfile->files, params->recursion_level);
filelist_setsorting(sfile->files, params->sort);
- filelist_setfilter_options(sfile->files, (params->flag & FILE_HIDE_DOT) != 0,
+ filelist_setfilter_options(sfile->files, (params->flag & FILE_FILTER) != 0,
+ (params->flag & FILE_HIDE_DOT) != 0,
false, /* TODO hide_parent, should be controllable? */
- (params->flag & FILE_FILTER) ? params->filter : 0,
+ params->filter,
params->filter_id,
params->filter_glob,
params->filter_search);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index c2cfca295a4..3c64d1ebb71 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1067,6 +1067,7 @@ typedef struct ImageOpenData {
typedef struct ImageFrameRange {
struct ImageFrameRange *next, *prev;
ListBase frames;
+ /** The full path of the first file in the list of image files */
char filepath[FILE_MAX];
} ImageFrameRange;
@@ -1092,12 +1093,12 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
/**
* \brief Get a list of frames from the list of image files matching the first file name sequence pattern
* \param ptr [in] the RNA pointer containing the "directory" entry and "files" collection
- * \param frames [out] the list of frame numbers found in the files matching the first one by name
- * \param path [out] the full path of the first file in the list of image files
+ * \param frames_all [out] the list of frame numbers found in the files matching the first one by name
*/
static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all)
{
char dir[FILE_MAXDIR];
+ const bool do_frame_range = RNA_boolean_get(ptr, "use_sequence_detection");
ImageFrameRange *frame_range = NULL;
RNA_string_get(ptr, "directory", dir);
@@ -1113,7 +1114,8 @@ static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_al
frame->framenr = BLI_stringdec(filename, head, tail, &digits);
/* still in the same sequence */
- if ((frame_range != NULL) &&
+ if (do_frame_range &&
+ (frame_range != NULL) &&
(STREQLEN(base_head, head, FILE_MAX)) &&
(STREQLEN(base_tail, tail, FILE_MAX)))
{
@@ -1167,6 +1169,7 @@ static int image_sequence_get_len(ListBase *frames, int *ofs)
}
return frame_curr - (*ofs);
}
+ *ofs = 0;
return 0;
}
@@ -1325,7 +1328,11 @@ static int image_open_exec(bContext *C, wmOperator *op)
iuser->frames = frame_seq_len;
iuser->sfra = 1;
iuser->framenr = 1;
- iuser->offset = frame_ofs - 1;
+ if (ima->source == IMA_SRC_MOVIE) {
+ iuser->offset = 0;
+ } else {
+ iuser->offset = frame_ofs - 1;
+ }
iuser->fie_ima = 2;
iuser->scene = scene;
BKE_image_init_imageuser(ima, iuser);
@@ -1448,6 +1455,9 @@ void IMAGE_OT_open(wmOperatorType *ot)
ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH,
FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+
+ RNA_def_boolean(ot->srna, "use_sequence_detection", true, "Detect Sequences",
+ "Automatically detect animated sequences in selected images (based on file names)");
}
/******************** Match movie length operator ********************/
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 0e427623840..b87a0de23b9 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -162,7 +162,6 @@ static int pack_all_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
packAll(bmain, op->reports, true);
- G.fileflags |= G_AUTOPACK;
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 5355b8012db..c774b99629c 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -552,7 +552,7 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
strcpy(pt->idname, "NLA_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
- strcpy(pt->category, "Modifiers");
+ strcpy(pt->category, "Modifiers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_modifiers;
pt->poll = nla_strip_eval_panel_poll;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index f58b4050834..6185f4afbe2 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -638,7 +638,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
* highlight also if node itself is selected, since we don't display the node body separately!
*/
for (sock = node->inputs.first; sock; sock = sock->next) {
- node_socket_circle_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
+ node_socket_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
}
UI_block_end(C, node->block);
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 6e25c87d274..213e326b1a6 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -617,34 +617,22 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
glDisable(GL_LINE_SMOOTH);
}
-/* this might have some more generic use */
-static void node_circle_draw(float x, float y, float size, const float col[4], int highlight)
+static void node_socket_shape_draw(
+ float x, float y, float size, const float col[4], bool highlight,
+ const float coords[][2], int coords_len)
{
- /* 16 values of sin function */
- static const float si[16] = {
- 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
- 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
- -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
- -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
- };
- /* 16 values of cos function */
- static const float co[16] = {
- 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
- -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
- -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
- 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
- };
int a;
-
+
glColor4fv(col);
-
+
glEnable(GL_BLEND);
glBegin(GL_POLYGON);
- for (a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
+ for (a = 0; a < coords_len; a++) {
+ glVertex2f(x + size * coords[a][0], y + size * coords[a][1]);
+ }
glEnd();
glDisable(GL_BLEND);
-
+
if (highlight) {
UI_ThemeColor(TH_TEXT_HI);
glLineWidth(1.5f);
@@ -655,14 +643,16 @@ static void node_circle_draw(float x, float y, float size, const float col[4], i
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBegin(GL_LINE_LOOP);
- for (a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
+ for (a = 0; a < coords_len; a++) {
+ glVertex2f(x + size * coords[a][0], y + size * coords[a][1]);
+ }
glEnd();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
-void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, int highlight)
+
+void node_socket_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, bool highlight)
{
PointerRNA ptr, node_ptr;
float color[4];
@@ -670,7 +660,60 @@ void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, bNode *node, b
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
- node_circle_draw(sock->locx, sock->locy, size, color, highlight);
+
+ /* 16 values of {sin, cos} function */
+ const float shape_circle[16][2] = {
+ {0.00000000f, 1.00000000f},
+ {0.39435585f, 0.91895781f},
+ {0.72479278f, 0.68896691f},
+ {0.93775213f, 0.34730525f},
+ {0.99871650f, -0.05064916f},
+ {0.89780453f, -0.44039415f},
+ {0.65137248f, -0.75875812f},
+ {0.29936312f, -0.95413925f},
+ {-0.10116832f, -0.99486932f},
+ {-0.48530196f, -0.87434661f},
+ {-0.79077573f, -0.61210598f},
+ {-0.96807711f, -0.25065253f},
+ {-0.98846832f, 0.15142777f},
+ {-0.84864425f, 0.52896401f},
+ {-0.57126821f, 0.82076344f},
+ {-0.20129852f, 0.97952994f }
+ };
+
+ const float shape_diamond[4][2] = {
+ {0.0f, 1.2f},
+ {1.2f, 0.0f},
+ {0.0f, -1.2f},
+ {-1.2f, 0.0f},
+ };
+
+ const float shape_square[4][2] = {
+ {-0.9f, 0.9f},
+ {0.9f, 0.9f},
+ {0.9f, -0.9f},
+ {-0.9f, -0.9f},
+ };
+
+ const float (*shape)[2];
+ int shape_len;
+ switch (sock->draw_shape) {
+ default:
+ case SOCK_DRAW_SHAPE_CIRCLE:
+ shape = shape_circle;
+ shape_len = ARRAY_SIZE(shape_circle);
+ break;
+ case SOCK_DRAW_SHAPE_DIAMOND:
+ shape = shape_diamond;
+ shape_len = ARRAY_SIZE(shape_diamond);
+ break;
+ case SOCK_DRAW_SHAPE_SQUARE:
+ shape = shape_square;
+ shape_len = ARRAY_SIZE(shape_square);
+ break;
+ }
+
+ node_socket_shape_draw(sock->locx, sock->locy, size, color, highlight, shape, shape_len);
}
/* ************** Socket callbacks *********** */
@@ -935,7 +978,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
- node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
+ node_socket_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* socket outputs */
@@ -943,7 +986,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
- node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
+ node_socket_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* preview */
@@ -1066,13 +1109,15 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* sockets */
for (sock = node->inputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
+ if (!nodeSocketIsHidden(sock)) {
+ node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
+ }
}
for (sock = node->outputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
+ if (!nodeSocketIsHidden(sock)) {
+ node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
+ }
}
UI_block_end(C, node->block);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 9dc39b1839b..5f8f839025f 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -2086,7 +2086,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
/* make sure all clipboard nodes would be valid in the target tree */
all_nodes_valid = true;
for (node = clipboard_nodes_lb->first; node; node = node->next) {
- if (!node->typeinfo->poll_instance(node, ntree)) {
+ if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree)) {
all_nodes_valid = false;
BKE_reportf(op->reports, RPT_ERROR, "Cannot add node %s into node tree %s", node->name, ntree->id.name + 2);
}
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 914f8ffbe10..9d750bfe348 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -37,6 +37,7 @@
#include "DNA_anim_types.h"
#include "BLI_listbase.h"
+#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLT_translation.h"
@@ -186,6 +187,7 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
bNode *node, *nextnode;
bNodeTree *ngroup, *wgroup;
ListBase anim_basepaths = {NULL, NULL};
+ LinkNode *nodes_delayed_free = NULL;
ngroup = (bNodeTree *)gnode->id;
@@ -208,8 +210,8 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
* This also removes remaining links to and from interface nodes.
*/
if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
- nodeFreeNode(wgroup, node);
- continue;
+ /* We must delay removal since sockets will reference this node. see: T52092 */
+ BLI_linklist_prepend(&nodes_delayed_free, node);
}
/* keep track of this node's RNA "base" path (the part of the path identifying the node)
@@ -336,6 +338,11 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
}
}
+ while (nodes_delayed_free) {
+ node = BLI_linklist_pop(&nodes_delayed_free);
+ nodeFreeNode(ntree, node);
+ }
+
/* delete the group instance */
nodeFreeNode(ntree, gnode);
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 6b8fa0b88fe..352f9e51012 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -67,8 +67,9 @@ void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transfo
/* node_draw.c */
int node_get_colorid(struct bNode *node);
-void node_socket_circle_draw(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node,
- struct bNodeSocket *sock, float size, int highlight);
+void node_socket_draw(
+ const struct bContext *C, struct bNodeTree *ntree, struct bNode *node,
+ struct bNodeSocket *sock, float size, bool highlight);
int node_get_resize_cursor(int directions);
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 5f592431558..3b03399a5e7 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -567,7 +567,13 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
ntree->is_updating = true;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
bNodeLink *link = linkdata->data;
-
+
+ /* See note below, but basically TEST flag means that the link
+ * was connected to output (or to a node which affects the
+ * output).
+ */
+ do_tag_update |= (link->flag & NODE_LINK_TEST) != 0;
+
if (apply_links && link->tosock && link->fromsock) {
/* before actually adding the link,
* let nodes perform special link insertion handling
@@ -593,11 +599,6 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
}
}
else {
- /* See note below, but basically TEST flag means that the link
- * was connected to output (or to a node which affects the
- * output).
- */
- do_tag_update |= (link->flag & NODE_LINK_TEST) != 0;
nodeRemLink(ntree, link);
}
}
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index bbdf6feef01..2267316d257 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -753,6 +753,10 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi
break;
}
break;
+ case NC_WM:
+ if (wmn->data == ND_JOB)
+ ED_region_tag_redraw(ar);
+ break;
case NC_SCENE:
case NC_MATERIAL:
case NC_TEXTURE:
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 121fe812016..af6fdf2ab86 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1273,7 +1273,10 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
}
else {
- switch (GS(tselem->id->name)) {
+ /* TODO(sergey): Casting to short here just to handle ID_NLA which is
+ * NOT inside of IDType enum.
+ */
+ switch ((short)GS(tselem->id->name)) {
case ID_SCE:
tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
case ID_ME:
@@ -1343,6 +1346,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
case ID_GD:
tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break;
+ default:
+ break;
}
}
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 335eb95da0e..f4089667b04 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -1092,7 +1092,7 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
te = outliner_find_id(so, &so->tree, &obact->id);
- if (obact->type == OB_ARMATURE) {
+ if (te != NULL && obact->type == OB_ARMATURE) {
/* traverse down the bone hierarchy in case of armature */
TreeElement *te_obact = te;
@@ -1944,7 +1944,7 @@ static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEv
{
/* present a prompt to informing users that this change is irreversible */
return WM_operator_confirm_message(C, op,
- "Purging unused data-blocks cannot be undone. "
+ "Purging unused data-blocks cannot be undone and saves to current .blend file. "
"Click here to proceed...");
}
@@ -1966,7 +1966,8 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
/* identifiers */
ot->idname = "OUTLINER_OT_orphans_purge";
ot->name = "Purge All";
- ot->description = "Clear all orphaned data-blocks without any users from the file (cannot be undone)";
+ ot->description = "Clear all orphaned data-blocks without any users from the file "
+ "(cannot be undone, saves to current .blend file)";
/* callbacks */
ot->invoke = outliner_orphans_purge_invoke;
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 7e05c76b35b..18cc2a015e6 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -707,7 +707,12 @@ static eOLDrawState tree_element_active_pose(
{
Object *ob = (Object *)tselem->id;
Base *base = BKE_scene_base_find(scene, ob);
-
+
+ if (base == NULL) {
+ /* Armature not instantiated in current scene (e.g. inside an appended group...). */
+ return OL_DRAWSEL_NONE;
+ }
+
if (set != OL_SETSEL_NONE) {
if (scene->obedit)
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index cdb3df0fae9..29dcf73109c 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -235,8 +235,7 @@ static void unlink_group_cb(
}
else {
Main *bmain = CTX_data_main(C);
- BKE_libblock_unlink(bmain, group, false, false);
- BKE_libblock_free(bmain, group);
+ BKE_libblock_delete(bmain, group);
}
}
@@ -399,7 +398,7 @@ static void object_deselect_cb(
static void object_delete_cb(
bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+ TreeStoreElem *tsep, TreeStoreElem *tselem, void *user_data)
{
Base *base = (Base *)te->directdata;
@@ -436,7 +435,7 @@ static void object_delete_cb(
* Should not happen ideally, but does happens, see T51625.
* Rather than twisting in all kind of ways to address all possible cases leading to that situation, simpler
* to allow deleting such object as a mere generic data-block. */
- WM_operator_name_call(C, "OUTLINER_OT_id_delete", WM_OP_INVOKE_REGION_WIN, NULL);
+ id_delete_cb(C, reports, scene, te, tsep, tselem, user_data);
}
}
@@ -1058,7 +1057,7 @@ static EnumPropertyItem prop_group_op_types[] = {
{OL_GROUPOP_UNLINK, "UNLINK", 0, "Unlink Group", ""},
{OL_GROUPOP_LOCAL, "LOCAL", 0, "Make Local Group", ""},
{OL_GROUPOP_LINK, "LINK", 0, "Link Group Objects to Scene", ""},
- {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", "WARNING: no undo"},
+ {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", ""},
{OL_GROUPOP_REMAP, "REMAP", 0, "Remap Users",
"Make all users of selected data-blocks to use instead current (clicked) one"},
{OL_GROUPOP_INSTANCE, "INSTANCE", 0, "Instance Groups in Scene", ""},
@@ -1097,7 +1096,7 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op)
DAG_relations_tag_update(CTX_data_main(C));
break;
case OL_GROUPOP_DELETE:
- WM_operator_name_call(C, "OUTLINER_OT_id_delete", WM_OP_INVOKE_REGION_WIN, NULL);
+ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
break;
case OL_GROUPOP_REMAP:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ec46c5df9a0..4b0b0e2e0f0 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -882,6 +882,8 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
break;
}
+ default:
+ break;
}
}
@@ -1080,6 +1082,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv;
PropertyRNA *prop, *iterprop;
PropertyType proptype;
+
+ /* Don't display arrays larger, weak but index is stored as a short,
+ * also the outliner isn't intended for editing such large data-sets. */
+ BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!");
+ const int tot_limit = SHRT_MAX;
+
int a, tot;
/* we do lazy build, for speed and to avoid infinite recusion */
@@ -1101,6 +1109,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
iterprop = RNA_struct_iterator_property(ptr->type);
tot = RNA_property_collection_length(ptr, iterprop);
+ CLAMP_MAX(tot, tot_limit);
/* auto open these cases */
if (!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER)
@@ -1147,6 +1156,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
else if (proptype == PROP_COLLECTION) {
tot = RNA_property_collection_length(ptr, prop);
+ CLAMP_MAX(tot, tot_limit);
if (TSELEM_OPEN(tselem, soops)) {
for (a = 0; a < tot; a++) {
@@ -1159,6 +1169,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
tot = RNA_property_array_length(ptr, prop);
+ CLAMP_MAX(tot, tot_limit);
if (TSELEM_OPEN(tselem, soops)) {
for (a = 0; a < tot; a++)
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 70a6e6d83cb..97961501c6d 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -40,6 +40,7 @@
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
+#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
@@ -1116,18 +1117,16 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
bool draw_metadata = false;
- if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
+ if (G.is_rendering == false && (scene->r.seq_prev_type) == OB_RENDER) {
/* stop all running jobs, except screen one. currently previews frustrate Render
* needed to make so sequencer's rendering doesn't conflict with compositor
*/
WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_COMPOSITE);
- if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
- /* in case of final rendering used for preview, kill all previews,
- * otherwise threading conflict will happen in rendering module
- */
- WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW);
- }
+ /* in case of final rendering used for preview, kill all previews,
+ * otherwise threading conflict will happen in rendering module
+ */
+ WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW);
}
if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) {
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 2d6892c1091..b22a158e151 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -727,7 +727,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
if (!skip_dup) {
/* Duplicate AFTER the first change */
- seqn = BKE_sequence_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
+ seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
}
if (seqn) {
@@ -820,7 +820,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
if (!skip_dup) {
/* Duplicate AFTER the first change */
- seqn = BKE_sequence_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
+ seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
}
if (seqn) {
@@ -2162,7 +2162,7 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
if (ed == NULL)
return OPERATOR_CANCELLED;
- BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT);
+ BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0);
if (nseqbase.first) {
Sequence *seq = nseqbase.first;
@@ -3200,7 +3200,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME);
+ BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME, 0);
/* To make sure the copied strips have unique names between each other add
* them temporarily to the end of the original seqbase. (bug 25932)
@@ -3267,7 +3267,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
ED_sequencer_deselect_all(scene);
ofs = scene->r.cfra - seqbase_clipboard_frame;
- BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME);
+ BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME, 0);
/* transform pasted strips before adding */
if (ofs) {
@@ -3352,6 +3352,9 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
if (seq_act->sound) BKE_sound_add_scene_sound_defaults(scene, seq_act);
if (seq_other->sound) BKE_sound_add_scene_sound_defaults(scene, seq_other);
+ BKE_sequence_invalidate_cache(scene, seq_act);
+ BKE_sequence_invalidate_cache(scene, seq_other);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -3509,7 +3512,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75");
bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100");
- bool override = RNA_boolean_get(op->ptr, "override");
+ bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
bool turnon = true;
if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) {
@@ -3545,7 +3548,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
else
seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100;
- if (!override)
+ if (!overwrite)
seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
else
seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING;
@@ -3577,7 +3580,7 @@ void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "proxy_50", false, "50%", "");
RNA_def_boolean(ot->srna, "proxy_75", false, "75%", "");
RNA_def_boolean(ot->srna, "proxy_100", false, "100%", "");
- RNA_def_boolean(ot->srna, "override", false, "Override", "");
+ RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", "");
}
/* change ops */
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 48c49f36471..d88ed36e392 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -683,7 +683,7 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
if (!select_more_less_seq__internal(scene, false, false))
return OPERATOR_CANCELLED;
-
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index a2a80297041..f1d0f23f8af 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -435,6 +435,7 @@ static void sequencer_dropboxes(void)
/* ************* end drop *********** */
+/* DO NOT make this static, this hides the symbol and breaks API generation script. */
const char *sequencer_context_dir[] = {"edit_mask", NULL};
static int sequencer_context(const bContext *C, const char *member, bContextDataResult *result)
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 9b0bd30ff11..da5fa9da046 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -328,7 +328,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
if (tools & TOOL_SUGG_LIST) {
texttool_suggest_clear();
}
- if (tools & TOOL_DOCUMENT) {
+ if (tools & TOOL_DOCUMENT) {
texttool_docs_clear();
doc_scroll = 0;
}
diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c
index eb6877d297d..1ef3322711c 100644
--- a/source/blender/editors/space_text/text_format_pov.c
+++ b/source/blender/editors/space_text/text_format_pov.c
@@ -49,36 +49,38 @@ static int txtfmt_pov_find_keyword(const char *string)
{
int i, len;
/* Language Directives */
- if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
+ if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "persistent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "patch", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
else i = 0;
/* If next source char is an identifier (eg. 'i' in "definate") no match */
@@ -92,221 +94,275 @@ static int txtfmt_pov_find_reserved_keywords(const char *string)
* list is from...
* http://www.povray.org/documentation/view/3.7.0/212/
*/
+
+ /* Float Functions */
+ if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_intersections", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dimension_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_and", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_or", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_xor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "file_exists", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "precompute", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dimensions", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clipped_by", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "shadowless", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "turb_depth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "reciprocal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quaternion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phong_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tesselate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "save_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "load_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_trace", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "transform", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "translate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "direction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "roughness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "metallic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gts_load", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gts_save", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "location", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "altitude", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "evaluate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inverse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "collect", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "target", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "albedo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "look_at", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "jitter", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "right", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scale", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "child", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "crand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blink", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "defined", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "degrees", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inside", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radians", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vlength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "floor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strcmp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strlen", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tessel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sturm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "abs", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "acosh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "prod", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "with", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "acos", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asc", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asinh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asin", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atan2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atanh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atan", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ceil", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cosh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "log", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "min", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mod", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "seed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "form", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sinh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sqrt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tanh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vdot", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sin", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sqr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sum", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pwr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tan", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "val", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cos", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "div", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sky", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "up", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ln", len)) i = len;
+ /* Color Identifiers */
+ else if (STR_LITERAL_STARTSWITH(string, "transmit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "filter", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbf", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "green", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gray", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgb", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sRGB", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SRGB", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbf", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgb", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "red", len)) i = len;
+ /* Color Spaces */
+ else if (STR_LITERAL_STARTSWITH(string, "pov", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hsl", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hsv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "xyl", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "xyv", len)) i = len;
+ /* Vector Functions */
+ else if (STR_LITERAL_STARTSWITH(string, "vaxis_rotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vturbulence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "min_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vnormalize", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vrotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vcross", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "trace", len)) i = len;
+ /* String Functions */
+ else if (STR_LITERAL_STARTSWITH(string, "file_time", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "datetime", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "concat", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strlwr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strupr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "substr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vstr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "chr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "str", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+
+static int txtfmt_pov_find_reserved_builtins(const char *string)
+{
+ int i, len;
+
+ /* POV-Ray Built-in Variables
+ * list is from...
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
/* Language Keywords */
- if (STR_LITERAL_STARTSWITH(string, "aa_level", len)) i = len;
+ if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "area_illumination", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "all_intersections", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "smooth_triangle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lommel_seeliger", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "falloff_angle", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "aa_threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hypercomplex", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "major_radius", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_iteration", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "colour_space", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color_space", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "iridescence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "subsurface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scattering", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "absorption", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "adc_bailout", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "albedo", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "all_intersections", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "all", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "alpha", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "altitude", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "always_sample", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ambient_light", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ambient", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "angle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aperture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "water_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "reflection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "oren_nayar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "refraction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hierarchy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radiosity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tolerance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interior", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "toroidal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "emission", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "material", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "internal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "photons", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "arc_angle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "area_light", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "area_illumination", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "minnaert", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "texture", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "array", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "assumed_gamma", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "autostop", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "black_hole", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "blur_samples", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "brightness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "brilliance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "caustics", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "charset", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "collect", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "component", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "composite", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "confidence", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "contained_by", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "coords", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "count", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "crand", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "cube", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "diffuse", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "direction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dispersion", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "dist_exp", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "distance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "eccentricity", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "emission", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "error_bound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "evaluate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "exponent", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "exterior", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "extinction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "face_indices", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "falloff_angle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "falloff", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "file_gamma", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "finish", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "flatness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "planet", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "screw", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "keep", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "flip", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "focal_point", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fog_alt", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fog_offset", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fog_type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "form", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fresnel", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gamma", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gather", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "global_settings", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gray_threshold", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hf_gray_16", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hierarchy", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hypercomplex", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "importance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inside_vector", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "internal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "intervals", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ior", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "irid_wavelength", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "irid", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "load_file", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "location", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "move", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "roll", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "look_at", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "looks_like", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "low_error_factor", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "major_radius", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_distance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_gradient", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_intersections", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_iteration", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_sample", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_trace_level", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_trace", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "maximum_reuse", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "metallic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "method", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "metric", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "minimum_reuse", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "nearest_count", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal_indices", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal_vectors", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "now", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "number_of_waves", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "offset", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "open", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "orientation", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pass_through", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "pattern", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "phong_size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "phong", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "point_at", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pot", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "precision", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "precompute", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pretrace_end", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pretrace_start", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "prod", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pwr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quaternion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "radiosity", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "radius", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ratio", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "reciprocal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "recursion_limit", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "reflection", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "refraction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "width", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "right", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "roughness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "samples", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "save_file", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "scattering", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bend", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sky", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "alpha", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "slice", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "smooth", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "solid", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spacing", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "specular", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "split_union", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spotlight", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strength", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sturm", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sum", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "target", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "texture_list", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "thickness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "threshold", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tightness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tolerance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "toroidal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ttf", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "turb_depth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "all", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "now", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pot", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "u_steps", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "up", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "use_alpha", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uv_indices", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uv_vectors", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "v_steps", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "variance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vertex_vectors", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "water_level", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "width", len)) i = len;
-
- else i = 0;
-
- /* If next source char is an identifier (eg. 'i' in "definate") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
-}
-
-
-static int txtfmt_pov_find_reserved_builtins(const char *string)
-{
- int i, len;
-
- /* POV-Ray Built-in Variables
- * list is from...
- * http://www.povray.org/documentation/view/3.7.0/212/
- */
- if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
+ /* Animation Options */
+ else if (STR_LITERAL_STARTSWITH(string, "global_settings", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
- /* Color Identifiers */
- else if (STR_LITERAL_STARTSWITH(string, "blue", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "filter", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gray", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "green", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "red", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rgbft", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rgbf", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rgbt", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rgb", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "srgb", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sRGB", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SRGB", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "srgbft", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "srgbf", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "srgbt", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "transmit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
+ /* Spline Identifiers */
+ else if (STR_LITERAL_STARTSWITH(string, "extended_x_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "general_x_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quadratic_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "basic_x_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "natural_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "linear_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bezier_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "akima_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sor_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tcb_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "linear_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "conic_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "b_spline", len)) i = len;
/* Patterns */
- else if (STR_LITERAL_STARTSWITH(string, "agate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aoi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pigment_pattern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_pattern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "proportion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "triangular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "proximity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spherical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bump_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "wrinkles", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "average", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "voronoi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "masonry", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "binary", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "boxed", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "bozo", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "brick", len)) i = len;
@@ -315,14 +371,11 @@ static int txtfmt_pov_find_reserved_builtins(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "checker", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "crackle", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cylindrical", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "density_file", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "dents", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "facets", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "gradient", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "granite", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "hexagon", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_pattern", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "julia", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "leopard", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "magnet", len)) i = len;
@@ -330,13 +383,11 @@ static int txtfmt_pov_find_reserved_builtins(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "marble", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "onion", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "pavement", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pigment_pattern", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "planar", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "quilted", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "radial", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "ripples", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "slope", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spherical", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "spiral1", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "spiral2", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "spotted", len)) i = len;
@@ -344,95 +395,68 @@ static int txtfmt_pov_find_reserved_builtins(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "tile2", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "tiling", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "tiles", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "triangular", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "waves", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "wood", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "wrinkles", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "agate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aoi", len)) i = len;
/* Objects */
- else if (STR_LITERAL_STARTSWITH(string, "background", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "superellipsoid", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "bicubic_patch", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "blob", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "box", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cone", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "julia_fractal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "height_field", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sphere_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "light_group", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "light_source", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "intersection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "isosurface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "background", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sky_sphere", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "cylinder", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "difference", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brilliance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parametric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interunion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "intermerge", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "polynomial", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "displace", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "specular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ambient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "diffuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "polygon", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quadric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quartic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rainbow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sphere", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "prism", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "galley", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phong", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cone", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blob", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "box", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "disc", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "fog", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "height_field", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "intersection", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "isosurface", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "julia_fractal", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "lathe", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "light_group", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "light_source", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "merge", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "mesh2", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "mesh", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "object", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "ovus", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "parametric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lemon", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "plane", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "poly", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "polygon", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "polynomial", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "prism", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quadric", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quartic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rainbow", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sky_sphere", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "smooth_triangle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sphere_sweep", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sphere", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "superellipsoid", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "irid", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "sor", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "text", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "torus", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "triangle", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len;
- /* Filetypes */
- else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len;
- /* Spline Identifiers */
- else if (STR_LITERAL_STARTSWITH(string, "b_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bezier_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "conic_sweep", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "linear_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "linear_sweep", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "natural_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quadratic_spline", len)) i = len;
- /* Encodings */
- else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len;
- /* Camera Types */
- else if (STR_LITERAL_STARTSWITH(string, "fisheye", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mesh_camera", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "omnimax", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "orthographic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "panoramic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "perspective", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media", len)) i = len;
/* Built-in Vectors */
else if (STR_LITERAL_STARTSWITH(string, "t", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "u", len)) i = len;
@@ -440,7 +464,6 @@ static int txtfmt_pov_find_reserved_builtins(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "x", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "y", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "z", len)) i = len;
-
else i = 0;
/* If next source char is an identifier (eg. 'i' in "definate") no match */
@@ -463,155 +486,201 @@ static int txtfmt_pov_find_specialvar(const char *string)
{
int i, len;
/* Modifiers */
- if (STR_LITERAL_STARTSWITH(string, "adaptive", len)) i = len;
+ if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media_interaction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media_attenuation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "low_error_factor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "recursion_limit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interior_texture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_trace_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gray_threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pretrace_start", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vertex_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "noise_generator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "irid_wavelength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "number_of_waves", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ambient_light", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inside_vector", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "face_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "texture_list", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_gradient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uv_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uv_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "global_lights", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_bump_scale", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pretrace_end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_radiosity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_reflection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "assumed_gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scallop_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "triangle_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "nearest_count", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "maximum_reuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "minimum_reuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "always_sample", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "translucency", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eccentricity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "contained_by", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inside_point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "adc_bailout", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "split_union", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mm_per_unit", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "agate_turb", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "bounded_by", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "brick_size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bump_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bump_size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "circular", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clipped_by", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hf_gray_16", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dispersion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "extinction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "thickness", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "color_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "colour_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "colour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "control0", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "control1", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "cubic_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "density_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "density", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fade_color", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "fade_colour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fade_distance", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "frequency", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "global_lights", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hollow", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "interior_texture", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "interior", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "interpolate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inverse", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "jitter", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "map_type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "material_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "material", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "media", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "media_attenuation", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "media_interaction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mm_per_unit", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mortar", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_bump_scale", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_image", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_radiosity", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_reflection", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_shadow", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "noise_generator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_color", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "normal_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "octaves", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "omega", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "once", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "orient", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "parallel", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "phase", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "photons", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "pigment_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pigment", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "poly_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "quick_color", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "quick_colour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ramp_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rotate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "scale", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "scallop_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "shadowless", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sine_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "slope_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "subsurface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "material_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pass_through", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interpolate", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "texture_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "texture", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "transform", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "translate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "triangle_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "turbulence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error_bound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brightness", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "use_color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_alpha", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "use_colour", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "use_index", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "uv_mapping", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "warp", len)) i = len;
-
- /* Vector Functions */
- else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "min_extent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "trace", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vaxis_rotate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vcross", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vnormalize", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vrotate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vturbulence", len)) i = len;
- /* String Functions */
- else if (STR_LITERAL_STARTSWITH(string, "chr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "concat", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "datetime", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "str", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strlwr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strupr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "substr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vstr", len)) i = len;
- /* Float Functions */
- else if (STR_LITERAL_STARTSWITH(string, "abs", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "acosh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "acos", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "asc", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "asinh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "asin", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "atan2", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "atand", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "atanh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "atan", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bitwise_and", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bitwise_or", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bitwise_xor", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ceil", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cosh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cos", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "defined", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "degrees", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dimension_size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dimensions", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "div", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "exp", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "file_exists", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "floor", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inside", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ln", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "log", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "min", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mod", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pow", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "radians", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rand", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "seed", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sinh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sin", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sqrt", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sqr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strcmp", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strlen", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tanh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tan", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "val", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vdot", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vlength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "importance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_sample", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "intervals", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sine_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "slope_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "poly_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_shadow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ramp_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "precision", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "original", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "map_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_image", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "autostop", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "caustics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "octaves", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aa_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frequency", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_offset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "modulation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "outbound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_cache", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pigment", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "charset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inbound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "outside", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inner", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "turbulence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "polarity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bump_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "circular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "control0", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "control1", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "maximal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "minimal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_alt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "origin", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "amount", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "adaptive", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exponent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fresnel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "albinos", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "finish", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "omega", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fixed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spacing", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "u_steps", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "v_steps", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "offset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hollow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gather", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mortar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "count", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "once", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phase", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ratio", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "open", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ior", len)) i = len;
+ /* Light Types and options*/
+ else if (STR_LITERAL_STARTSWITH(string, "area_light", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "looks_like", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tightness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spotlight", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parallel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "point_at", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "falloff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radius", len)) i = len;
+ /* Camera Types and options*/
+ else if (STR_LITERAL_STARTSWITH(string, "omni_directional_stereo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambert_cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "miller_cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambert_azimuthal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_direction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_location ", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "van_der_grinten", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aitoff_hammer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "smyth_craster", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orthographic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_right", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blur_samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "plate_carree", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "perspective", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mesh_camera", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "focal_point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "balthasart", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "confidence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parallaxe", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hobo_dyer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_up", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "panoramic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eckert_vi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eckert_iv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mollweide", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aperture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "behrmann", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "variance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "stereo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "icosa", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tetra", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "octa", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mercator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "omnimax", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fisheye", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "edwards", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "peters", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gall", len)) i = len;
else i = 0;
/* If next source char is an identifier (eg. 'i' in "definate") no match */
@@ -622,15 +691,43 @@ static int txtfmt_pov_find_bool(const char *string)
{
int i, len;
/*Built-in Constants*/
- if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len;
- else i = 0;
+ if (STR_LITERAL_STARTSWITH(string, "unofficial", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len;
+ /* Encodings */
+ else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bt2020", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bt709", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len;
+ /* Filetypes */
+ else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ttf", len)) i = len;
+ else i = 0;
/* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
@@ -642,7 +739,7 @@ static char txtfmt_pov_format_identifier(const char *str)
if ((txtfmt_pov_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
else if ((txtfmt_pov_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) fmt = FMT_TYPE_RESERVED;
- else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) fmt = FMT_TYPE_DIRECTIVE;
else fmt = FMT_TYPE_DEFAULT;
return fmt;
}
@@ -693,9 +790,9 @@ static void txtfmt_pov_format_line(SpaceText *st, TextLine *line, const bool do_
}
/* Handle continuations */
else if (cont) {
- /* Multi-line comments */
+ /* C-Style comments */
if (cont & FMT_CONT_COMMENT_C) {
- if (*str == ']' && *(str + 1) == ']') {
+ if (*str == '*' && *(str + 1) == '/') {
*fmt = FMT_TYPE_COMMENT; fmt++; str++;
*fmt = FMT_TYPE_COMMENT;
cont = FMT_CONT_NOP;
@@ -752,7 +849,7 @@ static void txtfmt_pov_format_line(SpaceText *st, TextLine *line, const bool do_
}
}
/* Punctuation */
- else if ((*str != '#') && text_check_delim(*str)) {
+ else if (text_check_delim(*str)) {
*fmt = FMT_TYPE_SYMBOL;
}
/* Identifiers and other text (no previous ws. or delims. so text continues) */
@@ -767,7 +864,7 @@ static void txtfmt_pov_format_line(SpaceText *st, TextLine *line, const bool do_
if ((i = txtfmt_pov_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
else if ((i = txtfmt_pov_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
else if ((i = txtfmt_pov_find_reserved_keywords(str)) != -1) prev = FMT_TYPE_RESERVED;
- else if ((i = txtfmt_pov_find_reserved_builtins(str)) != -1) prev = FMT_TYPE_RESERVED;
+ else if ((i = txtfmt_pov_find_reserved_builtins(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
if (i > 0) {
text_format_fill_ascii(&str, &fmt, prev, i);
diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c
index 5c20a1c5f00..453dd1d748c 100644
--- a/source/blender/editors/space_text/text_format_pov_ini.c
+++ b/source/blender/editors/space_text/text_format_pov_ini.c
@@ -49,36 +49,36 @@ static int txtfmt_ini_find_keyword(const char *string)
{
int i, len;
/* Language Directives */
- if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
+ if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "I", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "S", len)) i = len;
@@ -104,25 +104,54 @@ static int txtfmt_ini_find_reserved(const char *string)
* list is from...
* http://www.povray.org/documentation/view/3.7.0/212/
*/
- if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
+ if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Create_Continue_Trace_Log", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "HideWhenMainMinimized", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Confidence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseExtensions", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ReadWriteSourceDir", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionLeft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionTop", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionRight", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionBottom", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionX", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionY", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Subset_Start_Frame", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Subset_End_Frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseToolbar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseTooltips", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Frame_Step", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Cyclic_Animation", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Field_Render", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Odd_Field", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Height", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Start_Column", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Start_Row", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "End_Column", len)) i = len;
@@ -130,10 +159,11 @@ static int txtfmt_ini_find_reserved(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "Test_Abort_Count", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Test_Abort", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Continue_Trace", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Create_Continue_Trace_Log", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bounding_Method", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Create_Ini", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Display_Gamma", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Display", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Version", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Pause_When_Done", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Verbose", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Preview_Start_Size", len)) i = len;
@@ -146,19 +176,6 @@ static int txtfmt_ini_find_reserved(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "Bits_Per_Color", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Compression", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Dither_Method", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Dither", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Return", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Include_Header", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Library_Path", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Debug_Console", len)) i = len;
@@ -182,8 +199,9 @@ static int txtfmt_ini_find_reserved(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "Remove_Bounds", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Split_Unions", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Antialias", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Glare_Desaturation", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Sampling_Method", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Antialias_Threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Stochastic_Seed", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Jitter_Amount", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Jitter", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len;
@@ -217,25 +235,14 @@ static int txtfmt_ini_find_reserved(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "Band3Width", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Band4Width", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "ShowCmd", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionLeft", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionTop", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionRight", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionBottom", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "UseToolbar", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "UseTooltips", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionX", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionY", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Flags", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Transparency", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Use8BitMode", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "MakeActive", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "KeepAboveMain", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "HideWhenMainMinimized", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "AutoClose", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "PreserveBitmap", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "FontSize", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "FontWeight", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Font", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "KeepMessages", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "AlertSound", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Completion", len)) i = len;
@@ -246,14 +253,6 @@ static int txtfmt_ini_find_reserved(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "PreventSleep", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "NoShelloutWait", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "SystemNoActive", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSoundEnabled", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSoundEnabled", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "UseExtensions", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ReadWriteSourceDir", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "NoShellOuts", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "VideoSource", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "SceneFile", len)) i = len;
@@ -265,6 +264,14 @@ static int txtfmt_ini_find_reserved(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "RenderwinClose", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Append_File", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "Warning Level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Height", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Dither", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Flags", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Font", len)) i = len;
/* Filetypes */
else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 15eb154c757..f29d2b30ffe 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -329,6 +329,8 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
case ID_CF:
cachefile_to_keylist(&ads, (CacheFile *)id, &keys, NULL);
break;
+ default:
+ break;
}
/* build linked-list for searching */
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 314b7bf3335..5208013b6fe 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -1903,6 +1903,11 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
}
+ /* custom bone may draw outline double-width */
+ if (arm->flag & ARM_POSEMODE) {
+ glLineWidth(1.0f);
+ }
+
/* draw custom bone shapes as wireframes */
if (!(arm->flag & ARM_NO_CUSTOM) &&
(draw_wire || (dt <= OB_WIRE)) )
@@ -1968,11 +1973,6 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
index = -1;
}
}
-
- /* custom bone may draw outline double-width */
- if (arm->flag & ARM_POSEMODE) {
- glLineWidth(1.0f);
- }
/* wire draw over solid only in posemode */
if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 90960cf7671..5f01092f5b0 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -7347,7 +7347,7 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_
theme_id = TH_GROUP_ACTIVE;
if (scene->basact != base) {
- theme_shade = -16;
+ theme_shade = -32;
}
}
else {
@@ -8378,9 +8378,13 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
DM_update_materials(dm, ob);
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_object_material_bind, NULL, me, DM_DRAW_SKIP_HIDDEN);
+ /* Only draw faces to mask out verts, we don't want their selection ID's. */
+ const int G_f_orig = G.f;
+ G.f &= ~G_BACKBUFSEL;
- GPU_object_material_unbind();
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, NULL, NULL, me, DM_DRAW_SKIP_HIDDEN);
+
+ G.f |= (G_f_orig & G_BACKBUFSEL);
bbs_obmode_mesh_verts(ob, dm, 1);
bm_vertoffs = me->totvert + 1;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index b8228c63209..996506a9cf7 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1412,33 +1412,31 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i
}
}
}
- if ((ID *)v3d->ob_centre == old_id) {
- v3d->ob_centre = (Object *)new_id;
- if (new_id == NULL) { /* Otherwise, bonename may remain valid... We could be smart and check this, too? */
- v3d->ob_centre_bone[0] = '\0';
- }
- }
- if ((ID *)v3d->defmaterial == old_id) {
- v3d->defmaterial = (Material *)new_id;
- }
-#if 0 /* XXX Deprecated? */
- if ((ID *)v3d->gpd == old_id) {
- v3d->gpd = (bGPData *)new_id;
- }
-#endif
+ /* Values in local-view aren't used, see: T52663 */
+ if (is_local == false) {
+ /* Skip 'v3d->defmaterial', it's not library data. */
- if (ELEM(GS(old_id->name), ID_IM, ID_MC)) {
- for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- if ((ID *)bgpic->ima == old_id) {
- bgpic->ima = (Image *)new_id;
- id_us_min(old_id);
- id_us_plus(new_id);
+ if ((ID *)v3d->ob_centre == old_id) {
+ v3d->ob_centre = (Object *)new_id;
+ /* Otherwise, bonename may remain valid... We could be smart and check this, too? */
+ if (new_id == NULL) {
+ v3d->ob_centre_bone[0] = '\0';
}
- if ((ID *)bgpic->clip == old_id) {
- bgpic->clip = (MovieClip *)new_id;
- id_us_min(old_id);
- id_us_plus(new_id);
+ }
+
+ if (ELEM(GS(old_id->name), ID_IM, ID_MC)) {
+ for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ if ((ID *)bgpic->ima == old_id) {
+ bgpic->ima = (Image *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+ if ((ID *)bgpic->clip == old_id) {
+ bgpic->clip = (MovieClip *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 250e6559b8f..56508ea989a 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2471,6 +2471,7 @@ static void view3d_draw_depth_loop(Scene *scene, ARegion *ar, View3D *v3d)
void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
{
+ struct bThemeState theme_state;
RegionView3D *rv3d = ar->regiondata;
short zbuf = v3d->zbuf;
short flag = v3d->flag;
@@ -2483,6 +2484,10 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
U.obcenter_dia = 0;
+ /* Tools may request depth outside of regular drawing code. */
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
/* Setup view matrix. */
ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL);
@@ -2510,6 +2515,8 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
U.glalphaclip = glalphaclip;
v3d->flag = flag;
U.obcenter_dia = obcenter_dia;
+
+ UI_Theme_Restore(&theme_state);
}
void ED_view3d_draw_select_loop(
@@ -2592,7 +2599,7 @@ static void gpu_render_lamp_update(Scene *scene, View3D *v3d,
if (layers &&
GPU_lamp_has_shadow_buffer(lamp) &&
/* keep last, may do string lookup */
- GPU_lamp_override_visible(lamp, srl, NULL))
+ GPU_lamp_visible(lamp, srl, NULL))
{
shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow");
shadow->lamp = lamp;
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 4e3f279e12e..97fcca11962 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -726,10 +726,15 @@ static enum eViewOpsOrbit viewops_orbit_mode(void)
/**
* Calculate the values for #ViewOpsData
+ *
+ * \param use_ensure_persp: When enabled run #view3d_ensure_persp this may switch out of
+ * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
+ * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
+ * so we don't want it to trigger auto-perspective).
*/
static void viewops_data_create_ex(
bContext *C, wmOperator *op, const wmEvent *event,
- bool switch_from_camera, enum eViewOpsOrbit orbit_mode)
+ bool use_ensure_persp, enum eViewOpsOrbit orbit_mode)
{
ViewOpsData *vod = op->customdata;
RegionView3D *rv3d = vod->rv3d;
@@ -750,8 +755,7 @@ static void viewops_data_create_ex(
vod->use_dyn_ofs = false;
}
- if (switch_from_camera) {
- /* switch from camera view when: */
+ if (use_ensure_persp) {
if (view3d_ensure_persp(vod->v3d, vod->ar)) {
/* If we're switching from camera view to the perspective one,
* need to tag viewport update, so camera vuew and borders
@@ -853,10 +857,10 @@ static void viewops_data_create_ex(
rv3d->rflag |= RV3D_NAVIGATING;
}
-static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event, bool switch_from_camera)
+static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event, bool use_ensure_persp)
{
enum eViewOpsOrbit orbit_mode = viewops_orbit_mode();
- viewops_data_create_ex(C, op, event, switch_from_camera, orbit_mode);
+ viewops_data_create_ex(C, op, event, use_ensure_persp, orbit_mode);
}
static void viewops_data_free(bContext *C, wmOperator *op)
@@ -1673,7 +1677,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
viewops_data_alloc(C, op);
viewops_data_create_ex(
C, op, event,
- viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false), false);
+ false, viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -1742,7 +1746,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
viewops_data_alloc(C, op);
viewops_data_create_ex(
C, op, event,
- viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false), false);
+ false, viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
vod = op->customdata;
@@ -4753,13 +4757,20 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
- float co_curr[2], co_prev[2];
+ if (U.uiflag & USER_LOCK_CURSOR_ADJUST) {
- if ((ED_view3d_project_float_global(ar, fp_prev, co_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
- (ED_view3d_project_float_global(ar, fp_curr, co_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
- {
- rv3d->ofs_lock[0] += (co_curr[0] - co_prev[0]) / (ar->winx * 0.5f);
- rv3d->ofs_lock[1] += (co_curr[1] - co_prev[1]) / (ar->winy * 0.5f);
+ float co_curr[2], co_prev[2];
+
+ if ((ED_view3d_project_float_global(ar, fp_prev, co_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
+ (ED_view3d_project_float_global(ar, fp_curr, co_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
+ {
+ rv3d->ofs_lock[0] += (co_curr[0] - co_prev[0]) / (ar->winx * 0.5f);
+ rv3d->ofs_lock[1] += (co_curr[1] - co_prev[1]) / (ar->winy * 0.5f);
+ }
+ }
+ else {
+ /* Cursor may be outside of the view, prevent it getting 'lost', see: T40353 & T45301 */
+ zero_v2(rv3d->ofs_lock);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index aefe30bbe32..714db0db0ff 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -48,7 +48,6 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_transform.h"
#include "ED_transform_snap_object_context.h"
#include "ED_space_api.h"
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index eda4d51e7e8..16b626a5be4 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -54,6 +54,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "UI_resources.h"
+
#include "GPU_select.h"
#include "WM_api.h"
@@ -812,19 +814,108 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
}
-float ED_view3d_depth_read_cached(const ViewContext *vc, int x, int y)
+/* -------------------------------------------------------------------- */
+
+/** \name Depth Utilities
+ * \{ */
+
+float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2])
{
ViewDepths *vd = vc->rv3d->depths;
- x -= vc->ar->winrct.xmin;
- y -= vc->ar->winrct.ymin;
+ int x = mval[0];
+ int y = mval[1];
- if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h)
+ if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) {
return vd->depths[y * vd->w + x];
- else
- return 1;
+ }
+ else {
+ BLI_assert(1.0 <= vd->depth_range[1]);
+ return 1.0f;
+ }
+}
+
+bool ED_view3d_depth_read_cached_normal(
+ const ViewContext *vc, const bglMats *mats, const int mval[2],
+ float r_normal[3])
+{
+ /* Note: we could support passing in a radius.
+ * For now just read 9 pixels. */
+
+ /* pixels surrounding */
+ bool depths_valid[9] = {false};
+ float coords[9][3] = {{0}};
+
+ ARegion *ar = vc->ar;
+ const ViewDepths *depths = vc->rv3d->depths;
+
+ for (int x = 0, i = 0; x < 2; x++) {
+ for (int y = 0; y < 2; y++) {
+ const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
+
+ const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
+ if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
+ if (ED_view3d_depth_unproject(ar, mats, mval_ofs, depth, coords[i])) {
+ depths_valid[i] = true;
+ }
+ }
+ i++;
+ }
+ }
+
+ const int edges[2][6][2] = {
+ /* x edges */
+ {{0, 1}, {1, 2},
+ {3, 4}, {4, 5},
+ {6, 7}, {7, 8}},
+ /* y edges */
+ {{0, 3}, {3, 6},
+ {1, 4}, {4, 7},
+ {2, 5}, {5, 8}},
+ };
+
+ float cross[2][3] = {{0.0f}};
+
+ for (int i = 0; i < 6; i++) {
+ for (int axis = 0; axis < 2; axis++) {
+ if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) {
+ float delta[3];
+ sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]);
+ add_v3_v3(cross[axis], delta);
+ }
+ }
+ }
+
+ cross_v3_v3v3(r_normal, cross[0], cross[1]);
+
+ if (normalize_v3(r_normal) != 0.0f) {
+ return true;
+ }
+ else {
+ return false;
+ }
}
+bool ED_view3d_depth_unproject(
+ const ARegion *ar, const bglMats *mats,
+ const int mval[2], const double depth,
+ float r_location_world[3])
+{
+ double p[3];
+ if (gluUnProject(
+ (double)ar->winrct.xmin + mval[0] + 0.5,
+ (double)ar->winrct.ymin + mval[1] + 0.5,
+ depth, mats->modelview, mats->projection, (const GLint *)mats->viewport,
+ &p[0], &p[1], &p[2]))
+ {
+ copy_v3fl_v3db(r_location_world, p);
+ return true;
+ }
+ return false;
+}
+
+/** \} */
+
void ED_view3d_depth_tag_update(RegionView3D *rv3d)
{
if (rv3d->depths)
@@ -1117,6 +1208,7 @@ int view3d_opengl_select(
ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input,
eV3DSelectMode select_mode)
{
+ struct bThemeState theme_state;
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
@@ -1161,6 +1253,10 @@ int view3d_opengl_select(
}
}
+ /* Tools may request depth outside of regular drawing code. */
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
/* Re-use cache (rect must be smaller then the cached)
* other context is assumed to be unchanged */
if (GPU_select_is_cached()) {
@@ -1191,7 +1287,7 @@ int view3d_opengl_select(
hits = GPU_select_end();
/* second pass, to get the closest object to camera */
- if (do_passes) {
+ if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest);
@@ -1213,6 +1309,8 @@ int view3d_opengl_select(
finally:
if (hits < 0) printf("Too many objects in select buffer\n"); /* XXX make error message */
+ UI_Theme_Restore(&theme_state);
+
return hits;
}
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 542dc410bc3..5248a260617 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -49,7 +49,6 @@
#include "ED_screen.h"
#include "ED_space_api.h"
-#include "ED_transform.h"
#include "ED_transform_snap_object_context.h"
#include "PIL_time.h" /* smoothview */
@@ -674,16 +673,6 @@ static int walkEnd(bContext *C, WalkInfo *walk)
return OPERATOR_CANCELLED;
}
-static bool wm_event_is_last_mousemove(const wmEvent *event)
-{
- while ((event = event->next)) {
- if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- return false;
- }
- }
- return true;
-}
-
static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event)
{
if (event->type == TIMER && event->customdata == walk->timer) {
@@ -736,7 +725,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent
}
else
#endif
- if (wm_event_is_last_mousemove(event)) {
+ if (WM_event_is_last_mousemove(event)) {
wmWindow *win = CTX_wm_window(C);
#ifdef __APPLE__
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index d786c755529..8cabf8d78ed 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -2878,7 +2878,9 @@ static void initBend(TransInfo *t)
t->flag |= T_NO_CONSTRAINT;
//copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
- calculateCenterCursor(t, t->center);
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ calculateCenterCursor(t, t->center);
+ }
calculateCenterGlobal(t, t->center, t->center_global);
t->val = 0.0f;
@@ -3051,19 +3053,13 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
/** \name Transform Shear
* \{ */
-static void postInputShear(TransInfo *UNUSED(t), float values[3])
-{
- mul_v3_fl(values, 0.05f);
-}
-
static void initShear(TransInfo *t)
{
t->mode = TFM_SHEAR;
t->transform = applyShear;
t->handleEvent = handleEventShear;
-
- setInputPostFct(&t->mouse, postInputShear);
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
t->idx_max = 0;
t->num.idx_max = 0;
@@ -3085,24 +3081,24 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
/* Use custom.mode.data pointer to signal Shear direction */
if (t->custom.mode.data == NULL) {
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_RATIO);
t->custom.mode.data = (void *)1;
}
else {
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
t->custom.mode.data = NULL;
}
status = TREDRAW_HARD;
}
else if (event->type == XKEY && event->val == KM_PRESS) {
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
t->custom.mode.data = NULL;
status = TREDRAW_HARD;
}
else if (event->type == YKEY && event->val == KM_PRESS) {
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_RATIO);
t->custom.mode.data = (void *)1;
status = TREDRAW_HARD;
@@ -4073,13 +4069,15 @@ static void initTrackball(TransInfo *t)
static void applyTrackballValue(TransInfo *t, const float axis1[3], const float axis2[3], float angles[2])
{
TransData *td = t->data;
- float mat[3][3], smat[3][3], totmat[3][3];
+ float mat[3][3];
+ float axis[3];
+ float angle;
int i;
- axis_angle_normalized_to_mat3(smat, axis1, angles[0]);
- axis_angle_normalized_to_mat3(totmat, axis2, angles[1]);
-
- mul_m3_m3m3(mat, smat, totmat);
+ mul_v3_v3fl(axis, axis1, angles[0]);
+ madd_v3_v3fl(axis, axis2, angles[1]);
+ angle = normalize_v3(axis);
+ axis_angle_normalized_to_mat3(mat, axis, angle);
for (i = 0; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
@@ -4089,10 +4087,7 @@ static void applyTrackballValue(TransInfo *t, const float axis1[3], const float
continue;
if (t->flag & T_PROP_EDIT) {
- axis_angle_normalized_to_mat3(smat, axis1, td->factor * angles[0]);
- axis_angle_normalized_to_mat3(totmat, axis2, td->factor * angles[1]);
-
- mul_m3_m3m3(mat, smat, totmat);
+ axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
}
ElementRotation(t, td, mat, t->around);
@@ -4278,7 +4273,7 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system,
B_UNIT_LENGTH, do_split, false);
}
- else if (dist > 1e10f || dist < -1e10f) {
+ else if (dist > 1e10f || dist < -1e10f) {
/* prevent string buffer overflow */
BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist);
}
@@ -5565,7 +5560,7 @@ static void slide_origdata_interp_data_vert(
float v_proj[3][3];
if (do_loop_weight || do_loop_mdisps) {
- project_plane_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis);
}
// BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
@@ -5599,19 +5594,19 @@ static void slide_origdata_interp_data_vert(
/* In the unlikely case that we're next to a zero length edge - walk around the to the next.
* Since we only need to check if the vertex is in this corner,
* its not important _which_ loop - as long as its not overlapping 'sv->co_orig_3d', see: T45096. */
- project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
((l_prev = l_prev->prev) != l->next)))
{
co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
- project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
}
- project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
((l_next = l_next->next) != l->prev)))
{
co_next = slide_origdata_orig_vert_co(sod, l_next->v);
- project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
}
if (co_prev_ok && co_next_ok) {
@@ -8367,8 +8362,15 @@ static void initTimeSlide(TransInfo *t)
TransData *td = t->data;
for (i = 0; i < t->total; i++, td++) {
- if (min > *(td->val)) min = *(td->val);
- if (max < *(td->val)) max = *(td->val);
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+ float val = *(td->val);
+
+ /* strip/action time to global (mapped) time */
+ if (adt)
+ val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP);
+
+ if (min > val) min = val;
+ if (max < val) max = val;
}
if (min == max) {
@@ -8443,25 +8445,38 @@ static void applyTimeSlideValue(TransInfo *t, float sval)
*/
AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
float cval = t->values[0];
-
- /* apply NLA-mapping to necessary values */
- if (adt)
- cval = BKE_nla_tweakedit_remap(adt, cval, NLATIME_CONVERT_UNMAP);
-
+
/* only apply to data if in range */
if ((sval > minx) && (sval < maxx)) {
float cvalc = CLAMPIS(cval, minx, maxx);
+ float ival = td->ival;
float timefac;
-
+
+ /* NLA mapping magic here works as follows:
+ * - "ival" goes from strip time to global time
+ * - calculation is performed into td->val in global time
+ * (since sval and min/max are all in global time)
+ * - "td->val" then gets put back into strip time
+ */
+ if (adt) {
+ /* strip to global */
+ ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP);
+ }
+
/* left half? */
- if (td->ival < sval) {
- timefac = (sval - td->ival) / (sval - minx);
+ if (ival < sval) {
+ timefac = (sval - ival) / (sval - minx);
*(td->val) = cvalc - timefac * (cvalc - minx);
}
else {
- timefac = (td->ival - sval) / (maxx - sval);
+ timefac = (ival - sval) / (maxx - sval);
*(td->val) = cvalc + timefac * (maxx - cvalc);
}
+
+ if (adt) {
+ /* global to strip */
+ *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP);
+ }
}
}
}
@@ -8520,9 +8535,11 @@ static void initTimeScale(TransInfo *t)
/* recalculate center2d to use CFRA and mouse Y, since that's
* what is used in time scale */
- t->center[0] = t->scene->r.cfra;
- projectFloatView(t, t->center, center);
- center[1] = t->mouse.imval[1];
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ t->center[0] = t->scene->r.cfra;
+ projectFloatView(t, t->center, center);
+ center[1] = t->mouse.imval[1];
+ }
/* force a reinit with the center2d used here */
initMouseInput(t, &t->mouse, center, t->mouse.imval, false);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index d60eb2f0778..06a60456cdb 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -533,6 +533,9 @@ typedef struct TransInfo {
/* alternative transformation. used to add offset to tracking markers */
#define T_ALT_TRANSFORM (1 << 24)
+ /** #TransInfo.center has been set, don't change it. */
+#define T_OVERRIDE_CENTER (1 << 25)
+
/* TransInfo->modifiers */
#define MOD_CONSTRAINT_SELECT 0x01
#define MOD_PRECISION 0x02
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 04b9ae75c8f..521179fc1d9 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -771,29 +771,37 @@ int count_set_pose_transflags(int *out_mode, short around, Object *ob)
/* -------- Auto-IK ---------- */
/* adjust pose-channel's auto-ik chainlen */
-static void pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
+static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
{
bConstraint *con;
+ bool changed = false;
/* don't bother to search if no valid constraints */
- if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0)
- return;
+ if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
+ return changed;
+ }
/* check if pchan has ik-constraint */
for (con = pchan->constraints.first; con; con = con->next) {
if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
bKinematicConstraint *data = con->data;
-
+
/* only accept if a temporary one (for auto-ik) */
if (data->flag & CONSTRAINT_IK_TEMP) {
/* chainlen is new chainlen, but is limited by maximum chainlen */
- if ((chainlen == 0) || (chainlen > data->max_rootbone))
+ const int old_rootbone = data->rootbone;
+ if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
data->rootbone = data->max_rootbone;
- else
+ }
+ else {
data->rootbone = chainlen;
+ }
+ changed |= (data->rootbone != old_rootbone);
}
}
}
+
+ return changed;
}
/* change the chain-length of auto-ik */
@@ -809,7 +817,13 @@ void transform_autoik_update(TransInfo *t, short mode)
}
else if (mode == -1) {
/* mode==-1 is from WHEELMOUSEUP... decreases len */
- if (*chainlen > 0) (*chainlen)--;
+ if (*chainlen > 0) {
+ (*chainlen)--;
+ }
+ else {
+ /* IK length did not change, skip updates. */
+ return;
+ }
}
/* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
@@ -817,8 +831,19 @@ void transform_autoik_update(TransInfo *t, short mode)
return;
/* apply to all pose-channels */
+ bool changed = false;
for (pchan = t->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
- pchan_autoik_adjust(pchan, *chainlen);
+ changed |= pchan_autoik_adjust(pchan, *chainlen);
+ }
+
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (!DEG_depsgraph_use_legacy())
+#endif
+ {
+ if (changed) {
+ /* TODO(sergey): Consider doing partial update only. */
+ DAG_relations_tag_update(G.main);
+ }
}
}
@@ -1500,6 +1525,48 @@ static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struc
return hdata;
}
+/**
+ * For the purpose of transform code we need to behave as if handles are selected,
+ * even when they aren't (see special case below).
+ */
+static int bezt_select_to_transform_triple_flag(
+ const BezTriple *bezt, const bool hide_handles)
+{
+ int flag = 0;
+
+ if (hide_handles) {
+ if (bezt->f2 & SELECT) {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+ else {
+ flag = (
+ ((bezt->f1 & SELECT) ? (1 << 0) : 0) |
+ ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
+ ((bezt->f3 & SELECT) ? (1 << 2) : 0)
+ );
+ }
+
+ /* Special case for auto & aligned handles:
+ * When a center point is being moved without the handles,
+ * leaving the handles stationary makes no sense and only causes strange behavior,
+ * where one handle is arbitrarily anchored, the other one is aligned and lengthened
+ * based on where the center point is moved. Also a bug when cancelling, see: T52007.
+ *
+ * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
+ * However that doesn't resolve odd behavior, so best transform the handles in this case.
+ */
+ if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
+ if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) &&
+ ELEM(bezt->h2, HD_AUTO, HD_ALIGN))
+ {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+
+ return flag;
+}
+
static void createTransCurveVerts(TransInfo *t)
{
Curve *cu = t->obedit->data;
@@ -1517,22 +1584,22 @@ static void createTransCurveVerts(TransInfo *t)
/* to be sure */
if (cu->editnurb == NULL) return;
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
+
/* count total of vertices, check identical as in 2nd loop for making transdata! */
nurbs = BKE_curve_editNurbs_get(cu);
for (nu = nurbs->first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
if (bezt->hide == 0) {
- if (hide_handles) {
- if (bezt->f2 & SELECT) countsel += 3;
- if (is_prop_edit) count += 3;
- }
- else {
- if (bezt->f1 & SELECT) countsel++;
- if (bezt->f2 & SELECT) countsel++;
- if (bezt->f3 & SELECT) countsel++;
- if (is_prop_edit) count += 3;
- }
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+ if (bezt_tx & SEL_F1) { countsel++; }
+ if (bezt_tx & SEL_F2) { countsel++; }
+ if (bezt_tx & SEL_F3) { countsel++; }
+ if (is_prop_edit) count += 3;
+
}
}
}
@@ -1583,10 +1650,10 @@ static void createTransCurveVerts(TransInfo *t)
}
}
- if (is_prop_edit ||
- ((bezt->f2 & SELECT) && hide_handles) ||
- ((bezt->f1 & SELECT) && hide_handles == 0))
- {
+ /* Elements that will be transform (not always a match to selection). */
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+
+ if (is_prop_edit || bezt_tx & SEL_F1) {
copy_v3_v3(td->iloc, bezt->vec[0]);
td->loc = bezt->vec[0];
copy_v3_v3(td->center, bezt->vec[(hide_handles ||
@@ -1617,7 +1684,7 @@ static void createTransCurveVerts(TransInfo *t)
}
/* This is the Curve Point, the other two are handles */
- if (is_prop_edit || (bezt->f2 & SELECT)) {
+ if (is_prop_edit || bezt_tx & SEL_F2) {
copy_v3_v3(td->iloc, bezt->vec[1]);
td->loc = bezt->vec[1];
copy_v3_v3(td->center, td->loc);
@@ -1643,7 +1710,7 @@ static void createTransCurveVerts(TransInfo *t)
copy_m3_m3(td->axismtx, axismtx);
}
- if ((bezt->f1 & SELECT) == 0 && (bezt->f3 & SELECT) == 0)
+ if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0)
/* If the middle is selected but the sides arnt, this is needed */
if (hdata == NULL) { /* if the handle was not saved by the previous handle */
hdata = initTransDataCurveHandles(td, bezt);
@@ -1653,10 +1720,7 @@ static void createTransCurveVerts(TransInfo *t)
count++;
tail++;
}
- if (is_prop_edit ||
- ((bezt->f2 & SELECT) && hide_handles) ||
- ((bezt->f3 & SELECT) && hide_handles == 0))
- {
+ if (is_prop_edit || bezt_tx & SEL_F3) {
copy_v3_v3(td->iloc, bezt->vec[2]);
td->loc = bezt->vec[2];
copy_v3_v3(td->center, bezt->vec[(hide_handles ||
@@ -1711,6 +1775,26 @@ static void createTransCurveVerts(TransInfo *t)
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
if (is_prop_edit || (bp->f1 & SELECT)) {
+ float axismtx[3][3];
+
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ float normal[3], plane[3];
+
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+
+ if (createSpaceNormalTangent(axismtx, normal, plane)) {
+ /* pass */
+ }
+ else {
+ normalize_v3(normal);
+ axis_dominant_v3_to_m3(axismtx, normal);
+ invert_m3(axismtx);
+ }
+ }
+ }
+
copy_v3_v3(td->iloc, bp->vec);
td->loc = bp->vec;
copy_v3_v3(td->center, td->loc);
@@ -1729,6 +1813,11 @@ static void createTransCurveVerts(TransInfo *t)
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+ }
td++;
count++;
@@ -1744,6 +1833,10 @@ static void createTransCurveVerts(TransInfo *t)
calc_distanceCurveVerts(head, tail - 1);
}
}
+
+#undef SEL_F1
+#undef SEL_F2
+#undef SEL_F3
}
/* ********************* lattice *************** */
@@ -2008,9 +2101,9 @@ static bool bmesh_test_dist_add(
}
/**
- * \parm mtx: Measure disatnce in this space.
- * \parm dists: Store the closest connected distance to selected vertices.
- * \parm index: Optionally store the original index we're measuring the distance to (can be NULL).
+ * \param mtx: Measure disatnce in this space.
+ * \param dists: Store the closest connected distance to selected vertices.
+ * \param index: Optionally store the original index we're measuring the distance to (can be NULL).
*/
static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index)
{
@@ -2280,7 +2373,7 @@ static struct TransIslandData *editmesh_islands_info_calc(
}
if (group_tot_single != 0) {
- trans_islands = MEM_reallocN(trans_islands, group_tot + group_tot_single);
+ trans_islands = MEM_reallocN(trans_islands, sizeof(*trans_islands) * (group_tot + group_tot_single));
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
@@ -2402,7 +2495,8 @@ static void createTransEditVerts(TransInfo *t)
int island_info_tot;
int *island_vert_map = NULL;
- const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION);
+ /* Even for translation this is needed because of island-orientation, see: T51651. */
+ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
/* Original index of our connected vertex when connected distances are calculated.
* Optional, allocate if needed. */
int *dists_index = NULL;
@@ -2468,11 +2562,6 @@ static void createTransEditVerts(TransInfo *t)
editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
}
- /* Only in case of rotation and resize, we want the elements of the edited
- * object to behave as groups whose pivot are the individual origins
- *
- * TODO: use island_info to detect the closest point when the "Snap Target"
- * in Blender UI is "Closest" */
if (is_island_center) {
/* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
const bool calc_single_islands = (
@@ -5353,7 +5442,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
}
/* update object's loc/rot to get current rigid body transform */
mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat);
- BKE_object_mat3_to_rot(ob, rot, false);
+ sub_v3_v3(ob->loc, ob->dloc);
+ BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */
}
}
@@ -5886,27 +5976,23 @@ static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t)
{
SpaceClip *sc = t->sa->spacedata.first;
MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTrackingPlaneTrack *plane_track;
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- for (plane_track = plane_tracks_base->first;
+ const int framenr = ED_space_clip_get_clip_frame_number(sc);
+ /* Update coordinates of modified plane tracks. */
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
plane_track;
plane_track = plane_track->next)
{
bool do_update = false;
-
if (plane_track->flag & PLANE_TRACK_HIDDEN) {
continue;
}
-
do_update |= PLANE_TRACK_VIEW_SELECTED(plane_track) != 0;
if (do_update == false) {
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
int i;
for (i = 0; i < plane_track->point_tracksnr; i++) {
MovieTrackingTrack *track = plane_track->point_tracks[i];
-
if (TRACK_VIEW_SELECTED(sc, track)) {
do_update = true;
break;
@@ -5914,15 +6000,14 @@ static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t)
}
}
}
-
if (do_update) {
BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
}
}
-
- if (t->scene->nodetree) {
- /* tracks can be used for stabilization nodes,
- * flush update for such nodes */
+ if (t->scene->nodetree != NULL) {
+ /* Tracks can be used for stabilization nodes,
+ * flush update for such nodes.
+ */
nodeUpdateID(t->scene->nodetree, &clip->id);
WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
}
@@ -7750,7 +7835,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
float mtx[3][3], smtx[3][3];
const Scene *scene = CTX_data_scene(C);
- const int cfra = CFRA;
+ const int cfra_scene = CFRA;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
@@ -7775,7 +7860,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
bGPDstroke *gps;
-
+
for (gps = gpf->strokes.first; gps; gps = gps->next) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -7831,6 +7916,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* only editable and visible layers are considered */
if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
bGPDframe *gpf = gpl->actframe;
bGPDstroke *gps;
float diff_mat[4][4];
@@ -7847,7 +7933,6 @@ static void createTransGPencil(bContext *C, TransInfo *t)
* - This is useful when animating as it saves that "uh-oh" moment when you realize you've
* spent too much time editing the wrong frame...
*/
- // XXX: should this be allowed when framelock is enabled?
if (gpf->framenum != cfra) {
gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
/* in some weird situations (framelock enabled) return NULL */
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index f78a23be7b8..179b68dd270 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -971,7 +971,7 @@ static void recalcData_sequencer(TransInfo *t)
/* force recalculation of triangles during transformation */
static void recalcData_gpencil_strokes(TransInfo *t)
- {
+{
TransData *td = t->data;
for (int i = 0; i < t->total; i++, td++) {
bGPDstroke *gps = td->extra;
@@ -1331,7 +1331,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->current_orientation = V3D_MANIP_GLOBAL;
}
}
-
+
if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
RNA_property_is_set(op->ptr, prop)))
{
@@ -1435,6 +1435,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
#endif
setTransformViewAspect(t, t->aspect);
+
+ if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_get_array(op->ptr, prop, t->center);
+ mul_v3_v3(t->center, t->aspect);
+ t->flag |= T_OVERRIDE_CENTER;
+ }
+
setTransformViewMatrices(t);
initNumInput(&t->num);
}
@@ -1835,7 +1842,9 @@ static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[
void calculateCenter(TransInfo *t)
{
- calculateCenter_FromAround(t, t->around, t->center);
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ calculateCenter_FromAround(t, t->around, t->center);
+ }
calculateCenterGlobal(t, t->center, t->center_global);
/* avoid calculating again */
@@ -1849,7 +1858,7 @@ void calculateCenter(TransInfo *t)
calculateCenter2D(t);
/* for panning from cameraview */
- if (t->flag & T_OBJECT) {
+ if ((t->flag & T_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) {
if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
if (t->flag & T_CAMERA) {
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 22c39d6ed0c..5f2e5a99090 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -86,12 +86,11 @@ static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const double mv
output[1] *= mi->factor;
}
-static void InputHorizontalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3])
+static void InputHorizontalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
const int winx = t->ar ? t->ar->winx : 1;
- const double pad = winx / 10;
- output[0] = (mval[0] - pad) / (winx - 2 * pad);
+ output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f;
}
static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
@@ -104,12 +103,11 @@ static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double m
output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f;
}
-static void InputVerticalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3])
+static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
const int winy = t->ar ? t->ar->winy : 1;
- const double pad = winy / 10;
- output[0] = (mval[1] - pad) / (winy - 2 * pad);
+ output[0] = ((mval[1] - mi->imval[1]) / winy) * 2.0f;
}
static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
@@ -314,7 +312,6 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
t->helpline = HLP_TRACKBALL;
break;
case INPUT_HORIZONTAL_RATIO:
- mi->factor = (float)(mi->center[0] - mi->imval[0]);
mi->apply = InputHorizontalRatio;
t->helpline = HLP_HARROW;
break;
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index ab2a0225abc..ec066ba91a4 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -1755,7 +1755,7 @@ static int manipulator_selectbuf(Scene *scene, ScrArea *sa, ARegion *ar, const i
hits = GPU_select_end();
- if (do_passes) {
+ if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
/* do the drawing */
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 2a97384cf7d..1aa800f9fb1 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -565,6 +565,14 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
RNA_def_boolean(ot->srna, "correct_uv", 0, "Correct UVs", "Correct UV coordinates when transforming");
}
+ if (flags & P_CENTER) {
+ /* For manipulators that define their own center. */
+ prop = RNA_def_property(ot->srna, "center_override", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
+ }
+
if ((flags & P_NO_DEFAULTS) == 0) {
// Add confirm method all the time. At the end because it's not really that important and should be hidden only in log, not in keymap edit
/*prop =*/ RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "Always confirm operation when releasing button");
@@ -612,7 +620,8 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_GPENCIL_EDIT);
+ Transform_Properties(
+ ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
}
static int skin_resize_poll(bContext *C)
@@ -663,7 +672,7 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
/* Maybe we could use float_vector_xyz here too? */
RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
@@ -683,7 +692,8 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
- Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT);
+ Transform_Properties(
+ ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
@@ -726,7 +736,7 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
@@ -767,7 +777,7 @@ static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_CENTER);
}
static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
@@ -810,7 +820,7 @@ static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
@@ -828,7 +838,7 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT);
+ Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
@@ -991,7 +1001,8 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_GPENCIL_EDIT);
+ Transform_Properties(
+ ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
void transform_operatortypes(void)
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 23158495b44..54959304d72 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -817,15 +817,21 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
Curve *cu = obedit->data;
Nurb *nu = NULL;
- BezTriple *bezt = NULL;
int a;
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bezt)) {
+ void *vert_act = NULL;
+ if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) {
if (nu->type == CU_BEZIER) {
+ BezTriple *bezt = vert_act;
BKE_nurb_bezt_calc_normal(nu, bezt, normal);
BKE_nurb_bezt_calc_plane(nu, bezt, plane);
}
+ else {
+ BPoint *bp = vert_act;
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+ }
}
else {
const bool use_handle = (cu->drawflag & CU_HIDE_HANDLES) == 0;
@@ -833,7 +839,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
for (nu = nurbs->first; nu; nu = nu->next) {
/* only bezier has a normal */
if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
+ BezTriple *bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
short flag = 0;
@@ -885,6 +891,36 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
bezt++;
}
}
+ else if (nu->bp && (nu->pntsv == 1)) {
+ BPoint *bp = nu->bp;
+ a = nu->pntsu;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ float tvec[3];
+
+ BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
+ BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
+
+ const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT);
+ const bool is_next_sel = bp_next && (bp_next->f1 & SELECT);
+ if (is_prev_sel == false && is_next_sel == false) {
+ /* Isolated, add based on surrounding */
+ BKE_nurb_bpoint_calc_normal(nu, bp, tvec);
+ add_v3_v3(normal, tvec);
+ }
+ else if (is_next_sel) {
+ /* A segment, add the edge normal */
+ sub_v3_v3v3(tvec, bp->vec, bp_next->vec );
+ normalize_v3(tvec);
+ add_v3_v3(normal, tvec);
+ }
+
+ BKE_nurb_bpoint_calc_plane(nu, bp, tvec);
+ add_v3_v3(plane, tvec);
+ }
+ bp++;
+ }
+ }
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 318d2718969..4e8a9f4dd67 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -1017,7 +1017,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
char node_border;
- if (snapNodesTransform(t, t->mval, t->tsnap.modeSelect, loc, &dist_px, &node_border)) {
+ if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
copy_v2_v2(t->tsnap.snapPoint, loc);
t->tsnap.snapNodeBorder = node_border;
@@ -1413,22 +1413,11 @@ static bool snapNodes(
}
bool snapNodesTransform(
- TransInfo *t, const int mval[2], SnapSelect snap_select,
+ TransInfo *t, const int mval[2],
float r_loc[2], float *r_dist_px, char *r_node_border)
{
return snapNodes(
- t->settings, t->sa->spacedata.first, t->ar, mval, snap_select,
- r_loc, r_dist_px, r_node_border);
-}
-
-bool snapNodesContext(
- bContext *C, const int mval[2], SnapSelect snap_select,
- float r_loc[2], float *r_dist_px, char *r_node_border)
-{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- return snapNodes(
- scene->toolsettings, CTX_wm_space_node(C), ar, mval, snap_select,
+ t->settings, t->sa->spacedata.first, t->ar, mval, t->tsnap.modeSelect,
r_loc, r_dist_px, r_node_border);
}
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index b33528b4149..867f04563c6 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -130,18 +130,150 @@ struct SnapObjectContext {
};
-static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
+/** \} */
/* -------------------------------------------------------------------- */
-/** \name Support for storing all depths, not just the first (raycast 'all')
+/** Common utilities
+* \{ */
+
+
+typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
+
+/**
+ * Walks through all objects in the scene to create the list of objets to snap.
*
- * This uses a list of #SnapObjectHitDepth structs.
+ * \param sctx: Snap context to store data.
+ * \param snap_select : from enum SnapSelect.
+ * \param obedit : Object Edited to use its coordinates of BMesh(if any) to do the snapping.
+ */
+static void iter_snap_objects(
+ SnapObjectContext *sctx,
+ const SnapSelect snap_select,
+ Object *obedit,
+ IterSnapObjsCallback sob_callback,
+ void *data)
+{
+ Base *base_act = sctx->scene->basact;
+ /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
+ * which makes the loop skip it, even the derived mesh will never change
+ *
+ * To solve that problem, we do it first as an exception.
+ * */
+ if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) {
+ sob_callback(sctx, false, base_act->object, base_act->object->obmat, data);
+ }
+
+ for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {
+ if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&
+ (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
+ !((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL))) ||
+ (snap_select == SNAP_NOT_ACTIVE && base == base_act)))
+ {
+ bool use_obedit;
+ Object *obj = base->object;
+ if (obj->transflag & OB_DUPLI) {
+ DupliObject *dupli_ob;
+ ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, obj);
+ for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
+ use_obedit = obedit && dupli_ob->ob->data == obedit->data;
+ sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data);
+ }
+ free_object_duplilist(lb);
+ }
+
+ use_obedit = obedit && obj->data == obedit->data;
+ sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data);
+ }
+ }
+}
+
+
+/**
+ * Generates a struct with the immutable parameters that will be used on all objects.
*
- * \{ */
+ * \param snap_to: Element to snap, Vertice, Edge or Face.
+ * \param view_proj: ORTHO or PERSP.
+ * Currently only works one at a time, but can eventually operate as flag.
+ *
+ * \param mval: Mouse coords.
+ * (When NULL, ray-casting is handled without any projection matrix correction.)
+ * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
+ * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
+ * \param ray_direction: Unit length direction of the ray.
+ * \param depth_range: distances of clipe plane min and clip plane max;
+ */
+static void snap_data_set(
+ SnapData *snapdata,
+ const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
+ const float mval[2], const float ray_origin[3], const float ray_start[3],
+ const float ray_direction[3], const float depth_range[2])
+{
+ copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
+ snapdata->win_half[0] = ar->winx / 2;
+ snapdata->win_half[1] = ar->winy / 2;
+ copy_v2_v2(snapdata->mval, mval);
+ snapdata->snap_to = snap_to;
+ copy_v3_v3(snapdata->ray_origin, ray_origin);
+ copy_v3_v3(snapdata->ray_start, ray_start);
+ copy_v3_v3(snapdata->ray_dir, ray_direction);
+ snapdata->view_proj = view_proj;
+ copy_v2_v2(snapdata->depth_range, depth_range);
+}
+
+
+MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
+{
+ float dvec[3];
+ sub_v3_v3v3(dvec, co, ray_start);
+ return dot_v3v3(dvec, ray_dir);
+}
+
+
+static bool walk_parent_bvhroot_cb(const BVHTreeAxisRange *bounds, void *userdata)
+{
+ BVHTreeRay *ray = userdata;
+ const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min};
+ const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max};
+ if (!isect_ray_aabb_v3_simple(ray->origin, ray->direction, bbmin, bbmax, &ray->radius, NULL)) {
+ ray->radius = -1;
+ }
+ return false;
+}
+
+
+static bool isect_ray_bvhroot_v3(struct BVHTree *tree, const float ray_start[3], const float ray_dir[3], float *depth)
+{
+ BVHTreeRay ray;
+ copy_v3_v3(ray.origin, ray_start);
+ copy_v3_v3(ray.direction, ray_dir);
+
+ BLI_bvhtree_walk_dfs(tree, walk_parent_bvhroot_cb, NULL, NULL, &ray);
+
+ if (ray.radius > 0) {
+ *depth = ray.radius;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Ray Cast Funcs
+* \{ */
+
+/* Store all ray-hits
+ * Support for storing all depths, not just the first (raycast 'all') */
-/* Store all ray-hits */
struct RayCastAll_Data {
void *bvhdata;
@@ -162,6 +294,7 @@ struct RayCastAll_Data {
bool retval;
};
+
static struct SnapObjectHitDepth *hit_depth_create(
const float depth, const float co[3], const float no[3], int index,
Object *ob, const float obmat[4][4], unsigned int ob_uuid)
@@ -229,57 +362,501 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
}
}
-/** \} */
+static bool raycastDerivedMesh(
+ SnapObjectContext *sctx,
+ const float ray_start[3], const float ray_dir[3],
+ Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], int *r_index,
+ ListBase *r_hit_list)
+{
+ bool retval = false;
-/* -------------------------------------------------------------------- */
+ if (dm->getNumPolys(dm) == 0) {
+ return retval;
+ }
+
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_dir);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ /* Test BoundBox */
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ if (bb) {
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL))
+ {
+ return retval;
+ }
+ }
+
+ SnapObjectData_Mesh *sod = NULL;
+ BVHTreeFromMesh *treedata;
+
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_MESH;
+ }
+
+ if (sod->bvh_trees[2] == NULL) {
+ sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
+ }
+
+ treedata = sod->bvh_trees[2];
+
+ if (treedata) {
+ /* the tree is owned by the DM and may have been freed since we last used! */
+ if (treedata->tree) {
+ if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) {
+ free_bvhtree_from_mesh(treedata);
+ }
+ else {
+ if (treedata->vert == NULL) {
+ treedata->vert = DM_get_vert_array(dm, &treedata->vert_allocated);
+ }
+ if (treedata->loop == NULL) {
+ treedata->loop = DM_get_loop_array(dm, &treedata->loop_allocated);
+ }
+ if (treedata->looptri == NULL) {
+ if (sod->mpoly == NULL) {
+ sod->mpoly = DM_get_poly_array(dm, &sod->poly_allocated);
+ }
+ treedata->looptri = dm->getLoopTriArray(dm);
+ treedata->looptri_allocated = false;
+ }
+ }
+ }
+
+ if (treedata->tree == NULL) {
+ bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
+
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+ }
+ else {
+ return retval;
+ }
+
+ /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
+ * been *inside* boundbox, leading to snap failures (see T38409).
+ * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ */
+ if (len_diff == 0.0f) { /* do_ray_start_correction */
+ /* We *need* a reasonably valid len_diff in this case.
+ * Get the distance to bvhtree root */
+ if (!isect_ray_bvhroot_v3(treedata->tree, ray_start_local, ray_normal_local, &len_diff)) {
+ return retval;
+ }
+ }
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T38358.
+ */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
+ local_depth -= len_diff;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+
+ if (BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+static bool raycastEditMesh(
+ SnapObjectContext *sctx,
+ const float ray_start[3], const float ray_dir[3],
+ Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], int *r_index,
+ ListBase *r_hit_list)
+{
+ bool retval = false;
+ if (em->bm->totface == 0) {
+ return retval;
+ }
+
+ SnapObjectData_EditMesh *sod = NULL;
+ BVHTreeFromEditMesh *treedata = NULL;
+
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_EDIT_MESH;
+ }
+
+ if (sod->bvh_trees[2] == NULL) {
+ sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
+ }
+ treedata = sod->bvh_trees[2];
+
+ if (treedata) {
+ if (treedata->tree == NULL) {
+ BLI_bitmap *elem_mask = NULL;
+ int looptri_num_active = -1;
+
+ if (sctx->callbacks.edit_mesh.test_face_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
+ looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ em->bm, elem_mask,
+ sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
+ }
+ bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL);
+
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
+ }
+ }
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+ else {
+ return retval;
+ }
+
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_normal_local[3], ray_start_local[3], len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
+
+ copy_v3_v3(ray_normal_local, ray_dir);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ mul_m4_v3(imat, ray_start_local);
+
+ /* local scale in normal direction */
+ float local_scale = normalize_v3(ray_normal_local);
+ float local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ /* Only use closer ray_start in case of ortho view! In perspective one, ray_start
+ * may already been *inside* boundbox, leading to snap failures (see T38409).
+ * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ */
+ if (sctx->use_v3d && !((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp) { /* do_ray_start_correction */
+ /* We *need* a reasonably valid len_diff in this case.
+ * Get the distance to bvhtree root */
+ if (!isect_ray_bvhroot_v3(treedata->tree, ray_start_local, ray_normal_local, &len_diff)) {
+ return retval;
+ }
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T38358.
+ */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
+ local_depth -= len_diff;
+ }
+ else len_diff = 0.0f;
+ }
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+
+ if (BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = hit.index;
+ }
+ }
+ }
+ }
+
+ return retval;
+}
-/** \Common utilities
- * \{ */
/**
- * Generates a struct with the immutable parameters that will be used on all objects.
- *
- * \param snap_to: Element to snap, Vertice, Edge or Face.
- * \param view_proj: ORTHO or PERSP.
- * Currently only works one at a time, but can eventually operate as flag.
+ * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
*
- * \param mval: Mouse coords.
- * (When NULL, ray-casting is handled without any projection matrix correction.)
- * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
- * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
- * \param ray_direction: Unit length direction of the ray.
- * \param depth_range: distances of clipe plane min and clip plane max;
+ * \note Duplicate args here are documented at #snapObjectsRay
*/
-static void snap_data_set(
- SnapData *snapdata,
- const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
- const float mval[2], const float ray_origin[3], const float ray_start[3],
- const float ray_direction[3], const float depth_range[2])
+static bool raycastObj(
+ SnapObjectContext *sctx,
+ const float ray_start[3], const float ray_dir[3],
+ Object *ob, float obmat[4][4], const unsigned int ob_index,
+ bool use_obedit,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], int *r_index,
+ Object **r_ob, float r_obmat[4][4],
+ ListBase *r_hit_list)
{
- if (ar) {
- copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
- snapdata->win_half[0] = ar->winx / 2;
- snapdata->win_half[1] = ar->winy / 2;
+ bool retval = false;
+
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em;
+
+ if (use_obedit) {
+ em = BKE_editmesh_from_object(ob);
+ retval = raycastEditMesh(
+ sctx,
+ ray_start, ray_dir,
+ ob, em, obmat, ob_index,
+ ray_depth, r_loc, r_no, r_index, r_hit_list);
+ }
+ else {
+ /* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
+ * still set the 'em' to NULL, since we only want the 'dm'. */
+ DerivedMesh *dm;
+ em = BKE_editmesh_from_object(ob);
+ if (em) {
+ editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm);
+ }
+ else {
+ dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
+ }
+ retval = raycastDerivedMesh(
+ sctx,
+ ray_start, ray_dir,
+ ob, dm, obmat, ob_index,
+ ray_depth, r_loc, r_no, r_index, r_hit_list);
+ }
}
- if (mval) {
- copy_v2_v2(snapdata->mval, mval);
+
+ if (retval) {
+ if (r_ob) {
+ *r_ob = ob;
+ copy_m4_m4(r_obmat, obmat);
+ }
}
- snapdata->snap_to = snap_to;
- copy_v3_v3(snapdata->ray_origin, ray_origin);
- copy_v3_v3(snapdata->ray_start, ray_start);
- copy_v3_v3(snapdata->ray_dir, ray_direction);
- snapdata->view_proj = view_proj;
- copy_v2_v2(snapdata->depth_range, depth_range);
+
+ return retval;
}
-MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
+
+struct RaycastObjUserData {
+ const float *ray_start;
+ const float *ray_dir;
+ unsigned int ob_index;
+ /* read/write args */
+ float *ray_depth;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ ListBase *r_hit_list;
+ bool ret;
+};
+
+static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
{
- float dvec[3];
- sub_v3_v3v3(dvec, co, ray_start);
- return dot_v3v3(dvec, ray_dir);
+ struct RaycastObjUserData *dt = data;
+ dt->ret |= raycastObj(
+ sctx,
+ dt->ray_start, dt->ray_dir,
+ ob, obmat, dt->ob_index++, is_obedit,
+ dt->ray_depth,
+ dt->r_loc, dt->r_no, dt->r_index,
+ dt->r_ob, dt->r_obmat,
+ dt->r_hit_list);
+}
+
+/**
+ * Main RayCast Function
+ * ======================
+ *
+ * Walks through all objects in the scene to find the `hit` on object surface.
+ *
+ * \param sctx: Snap context to store data.
+ * \param snapdata: struct generated in `set_snapdata`.
+ * \param snap_select : from enum SnapSelect.
+ * \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping.
+ * \param obj_list: List with objects to snap (created in `create_object_list`).
+ *
+ * Read/Write Args
+ * ---------------
+ *
+ * \param ray_depth: maximum depth allowed for r_co, elements deeper than this value will be ignored.
+ *
+ * Output Args
+ * -----------
+ *
+ * \param r_loc: Hit location.
+ * \param r_no: Hit normal (optional).
+ * \param r_index: Hit index or -1 when no valid index is found.
+ * (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``).
+ * \param r_ob: Hit object.
+ * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
+ * \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
+ *
+ */
+static bool raycastObjects(
+ SnapObjectContext *sctx,
+ const float ray_start[3], const float ray_dir[3],
+ const SnapSelect snap_select, const bool use_object_edit_cage,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], int *r_index,
+ Object **r_ob, float r_obmat[4][4],
+ ListBase *r_hit_list)
+{
+ Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
+
+ struct RaycastObjUserData data = {
+ .ray_start = ray_start,
+ .ray_dir = ray_dir,
+ .ob_index = 0,
+ .ray_depth = ray_depth,
+ .r_loc = r_loc,
+ .r_no = r_no,
+ .r_index = r_index,
+ .r_ob = r_ob,
+ .r_obmat = r_obmat,
+ .r_hit_list = r_hit_list,
+ .ret = false,
+ };
+
+ iter_snap_objects(sctx, snap_select, obedit, raycast_obj_cb, &data);
+
+ return data.ret;
}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** Snap Nearest utilities
+ * \{ */
+
static void copy_dm_vert_no(const int index, float r_no[3], const BVHTreeFromMesh *data)
{
const MVert *vert = data->vert + index;
@@ -558,15 +1135,12 @@ static float dist_squared_to_projected_aabb(
vb2d[0] *= data->win_half[0];
vb2d[1] *= data->win_half[1];
- //float dvec[2], edge[2], rdist;
- //sub_v2_v2v2(dvec, data->mval, va2d);
- //sub_v2_v2v2(edge, vb2d, va2d);
- float rdist;
- short dvec[2] = {data->mval[0] - va2d[0], data->mval[1] - va2d[1]};
- short edge[2] = {vb2d[0] - va2d[0], vb2d[1] - va2d[1]};
- float lambda = dvec[0] * edge[0] + dvec[1] * edge[1];
+ float dvec[2], edge[2], lambda, rdist;
+ sub_v2_v2v2(dvec, data->mval, va2d);
+ sub_v2_v2v2(edge, vb2d, va2d);
+ lambda = dot_v2v2(dvec, edge);
if (lambda != 0.0f) {
- lambda /= edge[0] * edge[0] + edge[1] * edge[1];
+ lambda /= len_squared_v2(edge);
if (lambda <= 0.0f) {
rdist = len_squared_v2v2(data->mval, va2d);
r_axis_closest[main_axis] = true;
@@ -603,24 +1177,12 @@ static float dist_squared_to_projected_aabb_simple(
return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy);
}
-static float dist_aabb_to_plane(
- const float bbmin[3], const float bbmax[3],
- const float plane_co[3], const float plane_no[3])
-{
- const float local_bvmin[3] = {
- (plane_no[0] < 0) ? bbmax[0] : bbmin[0],
- (plane_no[1] < 0) ? bbmax[1] : bbmin[1],
- (plane_no[2] < 0) ? bbmax[2] : bbmin[2],
- };
- return depth_get(local_bvmin, plane_co, plane_no);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
-/** \Walk DFS
+/** Walk DFS
* \{ */
typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data);
@@ -1053,21 +1615,15 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
static bool snapDerivedMesh(
SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
+ Object *ob, DerivedMesh *dm, float obmat[4][4],
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+ float r_loc[3], float r_no[3])
{
bool retval = false;
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- if (dm->getNumPolys(dm) == 0) {
- return retval;
- }
- }
- else if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (dm->getNumEdges(dm) == 0) {
return retval;
}
@@ -1078,38 +1634,27 @@ static bool snapDerivedMesh(
}
}
- bool need_ray_start_correction_init =
- (snapdata->snap_to == SCE_SNAP_MODE_FACE) &&
- (snapdata->view_proj == VIEW_PROJ_ORTHO);
-
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff;
+ float ray_normal_local[3];
+ float local_scale;
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_start_local, snapdata->ray_start);
copy_v3_v3(ray_normal_local, snapdata->ray_dir);
- mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
/* local scale in normal direction */
local_scale = normalize_v3(ray_normal_local);
- local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
float lpmat[4][4];
float ray_org_local[3];
float ray_min_dist;
- if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- ray_min_dist = snapdata->depth_range[0] * local_scale;
- }
+
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ ray_min_dist = snapdata->depth_range[0] * local_scale;
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
@@ -1118,26 +1663,12 @@ static bool snapDerivedMesh(
BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
/* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- float dist_px_sq = dist_squared_to_projected_aabb_simple(
- lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
- ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
- if (dist_px_sq > SQUARE(*dist_px)) {
- return retval;
- }
- }
- else {
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
- {
- return retval;
- }
+ float dist_px_sq = dist_squared_to_projected_aabb_simple(
+ lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
+ ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
+ if (dist_px_sq > SQUARE(*dist_px)) {
+ return retval;
}
- /* was local_depth, see: T47838 */
- len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local);
- if (len_diff < 0) len_diff = 0.0f;
- need_ray_start_correction_init = false;
}
SnapObjectData_Mesh *sod = NULL;
@@ -1154,9 +1685,6 @@ static bool snapDerivedMesh(
int tree_index = -1;
switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- tree_index = 2;
- break;
case SCE_SNAP_MODE_EDGE:
tree_index = 1;
break;
@@ -1176,183 +1704,75 @@ static bool snapDerivedMesh(
free_bvhtree_from_mesh(treedata);
}
else {
- if (!treedata->vert_allocated) {
+ if (treedata->vert == NULL) {
treedata->vert = DM_get_vert_array(dm, &treedata->vert_allocated);
}
- if ((tree_index == 1) && !treedata->edge_allocated) {
- treedata->edge = DM_get_edge_array(dm, &treedata->vert_allocated);
- }
- if (tree_index == 2) {
- if (!treedata->loop_allocated) {
- treedata->loop = DM_get_loop_array(dm, &treedata->loop_allocated);
- }
- if (!treedata->looptri_allocated) {
- if (!sod->poly_allocated) {
- sod->mpoly = DM_get_poly_array(dm, &sod->poly_allocated);
- }
- treedata->looptri = DM_get_looptri_array(
- dm, treedata->vert,
- sod->mpoly, dm->getNumPolys(dm),
- treedata->loop, dm->getNumLoops(dm),
- &treedata->looptri_allocated);
- }
+ if ((tree_index == 1) && (treedata->edge == NULL)) {
+ treedata->edge = DM_get_edge_array(dm, &treedata->edge_allocated);
}
}
}
}
- if (treedata && treedata->tree == NULL) {
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
- break;
- case SCE_SNAP_MODE_EDGE:
- bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
- break;
- case SCE_SNAP_MODE_VERTEX:
- bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
- break;
+ if (treedata) {
+ if (treedata->tree == NULL) {
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_EDGE:
+ bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
+ break;
+ }
+ }
+ if (treedata->tree == NULL) {
+ return retval;
}
}
- if (!treedata || !treedata->tree) {
+ else {
return retval;
}
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
- * been *inside* boundbox, leading to snap failures (see T38409).
- * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
- */
- if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
- if (need_ray_start_correction_init) {
- /* We *need* a reasonably valid len_diff in this case.
- * Use BHVTree to find the closest face from ray_start_local.
- */
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
- if (nearest.index != -1) {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- }
- }
- /* You need to make sure that ray_start is really far away,
- * because even in the Orthografic view, in some cases,
- * the ray can start inside the object (see T50486) */
- if (len_diff > 400.0f) {
- /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
- * very far away ray_start values (as returned in case of ortho view3d), see T38358.
- */
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3v3fl(
- ray_start_local, ray_org_local, ray_normal_local,
- len_diff + snapdata->depth_range[0] * local_scale);
- local_depth -= len_diff;
- }
- else len_diff = 0.0f;
- }
- else {
- len_diff = 0.0f;
- }
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+ /* Warning: the depth_max is currently being used only in perspective view.
+ * It is not correct to limit the maximum depth for elements obtained with nearest
+ * since this limitation depends on the normal and the size of the occlusion face.
+ * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
+ const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
+ Nearest2dUserData neasrest2d = {
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .depth_range = {snapdata->depth_range[0], ray_depth_max_global},
+ .userdata = treedata,
+ .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no,
+ .index = -1};
- retval = true;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat,
+ snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
+ ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local);
- if (r_index) {
- *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
- }
- }
- }
- }
- }
- /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */
- else {
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- /* Warning: the depth_max is currently being used only in perspective view.
- * It is not correct to limit the maximum depth for elements obtained with nearest
- * since this limitation depends on the normal and the size of the occlusion face.
- * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
- const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
-
- Nearest2dUserData neasrest2d = {
- .dist_px_sq = SQUARE(*dist_px),
- .r_axis_closest = {1.0f, 1.0f, 1.0f},
- .depth_range = {snapdata->depth_range[0], ray_depth_max_global},
- .userdata = treedata,
- .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no,
- .index = -1};
-
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat,
- snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
- ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
-
- if (neasrest2d.index != -1) {
- copy_v3_v3(r_loc, neasrest2d.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
- retval = true;
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+
+ retval = true;
}
return retval;
@@ -1360,20 +1780,14 @@ static bool snapDerivedMesh(
static bool snapEditMesh(
SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
+ Object *ob, BMEditMesh *em, float obmat[4][4],
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+ float r_loc[3], float r_no[3])
{
bool retval = false;
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- if (em->bm->totface == 0) {
- return retval;
- }
- }
if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (em->bm->totedge == 0) {
return retval;
@@ -1398,13 +1812,8 @@ static bool snapEditMesh(
/* local scale in normal direction */
float local_scale = normalize_v3(ray_normal_local);
- float local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
SnapObjectData_EditMesh *sod = NULL;
-
BVHTreeFromEditMesh *treedata = NULL;
void **sod_p;
@@ -1418,9 +1827,6 @@ static bool snapEditMesh(
int tree_index = -1;
switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- tree_index = 2;
- break;
case SCE_SNAP_MODE_EDGE:
tree_index = 1;
break;
@@ -1435,197 +1841,90 @@ static bool snapEditMesh(
treedata = sod->bvh_trees[tree_index];
}
- if (treedata && treedata->tree == NULL) {
- BLI_bitmap *elem_mask = NULL;
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- {
- int looptri_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_face_fn) {
- elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
- looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
- em->bm, elem_mask,
- sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
+ if (treedata) {
+ if (treedata->tree == NULL) {
+ BLI_bitmap *elem_mask = NULL;
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_EDGE:
+ {
+ int edges_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_edge_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
+ edges_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_EDGES_OF_MESH, em->bm, elem_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
+ sctx->callbacks.edit_mesh.user_data);
+ }
+ bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6);
+ break;
}
- bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL);
- break;
- }
- case SCE_SNAP_MODE_EDGE:
- {
- int edges_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_edge_fn) {
- elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
- edges_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_EDGES_OF_MESH, em->bm, elem_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
- sctx->callbacks.edit_mesh.user_data);
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ int verts_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_vert_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+ verts_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_VERTS_OF_MESH, em->bm, elem_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
+ sctx->callbacks.edit_mesh.user_data);
+ }
+ bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6);
+ break;
}
- bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6);
- break;
}
- case SCE_SNAP_MODE_VERTEX:
- {
- int verts_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_vert_fn) {
- elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
- verts_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_VERTS_OF_MESH, em->bm, elem_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6);
- break;
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
}
}
- if (elem_mask) {
- MEM_freeN(elem_mask);
+ if (treedata->tree == NULL) {
+ return retval;
}
}
-
- if (!treedata || !treedata->tree) {
+ else {
return retval;
}
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- float ray_start_local[3];
- copy_v3_v3(ray_start_local, snapdata->ray_start);
- mul_m4_v3(imat, ray_start_local);
+ float ray_org_local[3];
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
- /* Only use closer ray_start in case of ortho view! In perspective one, ray_start
- * may already been *inside* boundbox, leading to snap failures (see T38409).
- * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
- */
- float len_diff = 0.0f;
- if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
- /* We *need* a reasonably valid len_diff in this case.
- * Use BHVTree to find the closest face from ray_start_local.
- */
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- if (BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
- {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- /* You need to make sure that ray_start is really far away,
- * because even in the Orthografic view, in some cases,
- * the ray can start inside the object (see T50486) */
- if (len_diff > 400.0f) {
- float ray_org_local[3];
-
- copy_v3_v3(ray_org_local, snapdata->ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
- /* We pass a temp ray_start, set from object's boundbox,
- * to avoid precision issues with very far away ray_start values
- * (as returned in case of ortho view3d), see T38358.
- */
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3v3fl(
- ray_start_local, ray_org_local, ray_normal_local,
- len_diff + snapdata->depth_range[0] * local_scale);
- local_depth -= len_diff;
- }
- else len_diff = 0.0f;
- }
- }
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+ Nearest2dUserData neasrest2d = {
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
+ .userdata = treedata,
+ .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no,
+ .index = -1};
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat,
+ snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
+ (snapdata->depth_range[0] * local_scale), snapdata->mval,
+ ray_org_local, ray_normal_local);
- retval = true;
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- if (r_index) {
- *r_index = hit.index;
- }
- }
- }
- }
- }
- else {
- float ray_org_local[3];
- copy_v3_v3(ray_org_local, snapdata->ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
- Nearest2dUserData neasrest2d = {
- .dist_px_sq = SQUARE(*dist_px),
- .r_axis_closest = {1.0f, 1.0f, 1.0f},
- .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
- .userdata = treedata,
- .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no,
- .index = -1};
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat,
- snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
- (snapdata->depth_range[0] * local_scale), snapdata->mval,
- ray_org_local, ray_normal_local);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
-
- if (neasrest2d.index != -1) {
- copy_v3_v3(r_loc, neasrest2d.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
- retval = true;
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+
+ retval = true;
}
return retval;
@@ -1638,14 +1937,13 @@ static bool snapEditMesh(
*/
static bool snapObject(
SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4], const unsigned int ob_index,
+ Object *ob, float obmat[4][4],
bool use_obedit,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4],
- ListBase *r_hit_list)
+ float r_loc[3], float r_no[3],
+ Object **r_ob, float r_obmat[4][4])
{
bool retval = false;
@@ -1655,10 +1953,9 @@ static bool snapObject(
if (use_obedit) {
em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
- sctx, snapdata, ob, em, obmat, ob_index,
+ sctx, snapdata, ob, em, obmat,
ray_depth, dist_px,
- r_loc, r_no, r_index,
- r_hit_list);
+ r_loc, r_no);
}
else {
/* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
@@ -1672,10 +1969,9 @@ static bool snapObject(
dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
}
retval = snapDerivedMesh(
- sctx, snapdata, ob, dm, obmat, ob_index,
+ sctx, snapdata, ob, dm, obmat,
ray_depth, dist_px,
- r_loc, r_no,
- r_index, r_hit_list);
+ r_loc, r_no);
dm->release(dm);
}
@@ -1720,6 +2016,34 @@ static bool snapObject(
return retval;
}
+
+struct SnapObjUserData {
+ SnapData *snapdata;
+ /* read/write args */
+ float *ray_depth;
+ float *dist_px;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ bool ret;
+};
+
+static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
+{
+ struct SnapObjUserData *dt = data;
+ dt->ret |= snapObject(
+ sctx, dt->snapdata,
+ ob, obmat, is_obedit,
+ /* read/write args */
+ dt->ray_depth, dt->dist_px,
+ /* return args */
+ dt->r_loc, dt->r_no,
+ dt->r_ob, dt->r_obmat);
+}
+
+
/**
* Main Snapping Function
* ======================
@@ -1728,8 +2052,8 @@ static bool snapObject(
*
* \param sctx: Snap context to store data.
* \param snapdata: struct generated in `get_snapdata`.
- * \param snap_select: from enum SnapSelect.
- * \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping.
+ * \param snap_select : from enum SnapSelect.
+ * \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping.
*
* Read/Write Args
* ---------------
@@ -1746,89 +2070,33 @@ static bool snapObject(
* (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``).
* \param r_ob: Hit object.
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
- * \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*
*/
static bool snapObjectsRay(
SnapObjectContext *sctx, SnapData *snapdata,
- const SnapSelect snap_select,
- const bool use_object_edit_cage,
+ const SnapSelect snap_select, const bool use_object_edit_cage,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4],
- ListBase *r_hit_list)
+ float r_loc[3], float r_no[3],
+ Object **r_ob, float r_obmat[4][4])
{
- bool retval = false;
-
- unsigned int ob_index = 0;
Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
- /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
- * which makes the loop skip it, even the derived mesh will never change
- *
- * To solve that problem, we do it first as an exception.
- * */
- Base *base_act = sctx->scene->basact;
- if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) {
- Object *ob = base_act->object;
-
- retval |= snapObject(
- sctx, snapdata, ob, ob->obmat, ob_index++, false,
- ray_depth, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
- }
-
- bool ignore_object_selected = false, ignore_object_active = false;
- switch (snap_select) {
- case SNAP_ALL:
- break;
- case SNAP_NOT_SELECTED:
- ignore_object_selected = true;
- break;
- case SNAP_NOT_ACTIVE:
- ignore_object_active = true;
- break;
- }
- for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {
- if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&
- (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
-
- !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) ||
- (ignore_object_active && base == base_act)))
- {
- Object *ob = base->object;
-
- if (ob->transflag & OB_DUPLI) {
- DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob);
-
- for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- bool use_obedit_dupli = (obedit && dupli_ob->ob->data == obedit->data);
- Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
-
- retval |= snapObject(
- sctx, snapdata, dupli_snap, dupli_ob->mat,
- ob_index++, use_obedit_dupli,
- ray_depth, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
- }
-
- free_object_duplilist(lb);
- }
+ struct SnapObjUserData data = {
+ .snapdata = snapdata,
+ .ray_depth = ray_depth,
+ .dist_px = dist_px,
+ .r_loc = r_loc,
+ .r_no = r_no,
+ .r_ob = r_ob,
+ .r_obmat = r_obmat,
+ .ret = false,
+ };
- bool use_obedit = (obedit != NULL) && (ob->data == obedit->data);
- Object *ob_snap = use_obedit ? obedit : ob;
+ iter_snap_objects(sctx, snap_select, obedit, sanp_obj_cb, &data);
- retval |= snapObject(
- sctx, snapdata, ob_snap, ob->obmat, ob_index++, use_obedit,
- ray_depth, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
- }
- }
-
- return retval;
+ return data.ret;
}
/** \} */
@@ -1922,25 +2190,17 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
bool ED_transform_snap_object_project_ray_ex(
SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3],
float *ray_depth,
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
- const float depth_range[2] = {0.0f, FLT_MAX};
-
- SnapData snapdata;
- snap_data_set(
- &snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE,
- NULL, ray_start, ray_start, ray_normal, depth_range);
-
- return snapObjectsRay(
- sctx, &snapdata,
+ return raycastObjects(
+ sctx,
+ ray_start, ray_normal,
params->snap_select, params->use_object_edit_cage,
- ray_depth, NULL,
- r_loc, r_no, r_index, r_ob, r_obmat, NULL);
+ ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
/**
@@ -1952,13 +2212,11 @@ bool ED_transform_snap_object_project_ray_ex(
*/
bool ED_transform_snap_object_project_ray_all(
SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3],
float ray_depth, bool sort,
ListBase *r_hit_list)
{
- const float depth_range[2] = {0.0f, FLT_MAX};
if (ray_depth == -1.0f) {
ray_depth = BVH_RAYCAST_DIST_MAX;
}
@@ -1967,15 +2225,11 @@ bool ED_transform_snap_object_project_ray_all(
float ray_depth_prev = ray_depth;
#endif
- SnapData snapdata;
- snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL,
- ray_start, ray_start, ray_normal, depth_range);
-
- bool retval = snapObjectsRay(
- sctx, &snapdata,
+ bool retval = raycastObjects(
+ sctx,
+ ray_start, ray_normal,
params->snap_select, params->use_object_edit_cage,
- &ray_depth, NULL,
- NULL, NULL, NULL, NULL, NULL,
+ &ray_depth, NULL, NULL, NULL, NULL, NULL,
r_hit_list);
/* meant to be readonly for 'all' hits, ensure it is */
@@ -2008,7 +2262,6 @@ static bool transform_snap_context_project_ray_impl(
/* try snap edge, then face if it fails */
ret = ED_transform_snap_object_project_ray_ex(
sctx,
- SCE_SNAP_MODE_FACE,
params,
ray_start, ray_normal, ray_depth,
r_co, r_no, NULL,
@@ -2154,16 +2407,24 @@ bool ED_transform_snap_object_project_view3d_ex(
ray_depth = &ray_depth_fallback;
}
- SnapData snapdata;
- const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
- snap_data_set(&snapdata, ar, snap_to, view_proj, mval,
- ray_origin, ray_start, ray_normal, depth_range);
+ if (snap_to == SCE_SNAP_MODE_FACE) {
+ return raycastObjects(
+ sctx,
+ ray_start, ray_normal,
+ params->snap_select, params->use_object_edit_cage,
+ ray_depth, r_loc, r_no, r_index, NULL, NULL, NULL);
+ }
+ else {
+ SnapData snapdata;
+ const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
+ snap_data_set(&snapdata, ar, snap_to, view_proj, mval,
+ ray_origin, ray_start, ray_normal, depth_range);
- return snapObjectsRay(
- sctx, &snapdata,
- params->snap_select, params->use_object_edit_cage,
- ray_depth, dist_px,
- r_loc, r_no, r_index, NULL, NULL, NULL);
+ return snapObjectsRay(
+ sctx, &snapdata,
+ params->snap_select, params->use_object_edit_cage,
+ ray_depth, dist_px, r_loc, r_no, NULL, NULL);
+ }
}
bool ED_transform_snap_object_project_view3d(
@@ -2204,7 +2465,6 @@ bool ED_transform_snap_object_project_all_view3d_ex(
return ED_transform_snap_object_project_ray_all(
sctx,
- SCE_SNAP_MODE_FACE,
params,
ray_start, ray_normal, ray_depth, sort,
r_hit_list);
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 4e021d4833e..419c15bf83f 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -334,6 +334,12 @@ static int ed_undo_redo_exec(bContext *C, wmOperator *UNUSED(op))
return ret ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
+static int ed_undo_redo_poll(bContext *C)
+{
+ wmOperator *last_op = WM_operator_last_redo(C);
+ return last_op && ED_operator_screenactive(C) &&
+ WM_operator_check_ui_enabled(C, last_op->type->name);
+}
/* ********************** */
@@ -385,7 +391,7 @@ void ED_OT_undo_redo(wmOperatorType *ot)
/* api callbacks */
ot->exec = ed_undo_redo_exec;
- ot->poll = ED_operator_screenactive;
+ ot->poll = ed_undo_redo_poll;
}
/* ui callbacks should call this rather than calling WM_operator_repeat() themselves */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 193b006cf0d..d7361f5a259 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -1136,8 +1136,13 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
- /* use winding so we don't consider overlapping islands as connected, see T44320 */
- vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, true);
+ /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320
+ * this made *every* projection split the island into front/back islands.
+ * Keep 'use_winding' to false, see: T50970.
+ *
+ * Better solve this by having a delimit option for select-linked operator,
+ * keeping island-select working as is. */
+ vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false);
if (vmap == NULL)
return;
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index bdfff123aa4..8c76d03035a 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -2859,7 +2859,7 @@ static PBool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PV
PEdge *cure = NULL, *firste1 = NULL, *firste2 = NULL, *nextbe;
float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f;
float len1, len2;
-
+
/* find longest series of verts split in the chart itself, these are
* marked during construction */
be = outer;
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index f63cf771120..1dbac1848b7 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -524,7 +524,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
// We'll generate both with tips and without tips
// coordinates, on two different UV layers.
- if (ma->mtex[a]->texflag & MTEX_TIPS) {
+ if (ma->mtex[a]->texflag & MTEX_TIPS) {
BLI_strncpy(ma->mtex[a]->uvname, uvNames[1], sizeof(ma->mtex[a]->uvname));
}
else {
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h
index d65b0ea803b..444fd7c4785 100644
--- a/source/blender/freestyle/intern/geometry/matrix_util.h
+++ b/source/blender/freestyle/intern/geometry/matrix_util.h
@@ -50,15 +50,15 @@ namespace MatrixUtil {
/**
* computes the eigen values and eigen vectors of a semi definite symmetric matrix
*
- * @param matrix is stored in column symmetric storage, i.e.
+ * \param mat: The matrix stored in column symmetric storage, i.e.
* matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
* size = n(n+1)/2
*
- * @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
+ * \param eigen_vec: (return) = { v1, v2, v3, ..., vn }
* where vk = vk0, vk1, ..., vkn
* size = n^2, must be allocated by caller
*
- * @param eigen_values (return) are in decreasing order
+ * \param eigen_val: (return) are in decreasing order
* size = n, must be allocated by caller
*/
void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 6db23686832..dbfcd4d1ea4 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -226,7 +226,7 @@ void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
-bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
+bool GPU_lamp_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 0324d090a21..e288c74fee6 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -76,7 +76,7 @@ typedef struct {
static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type);
-const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
+static const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
/* vertex */
{GL_ARRAY_BUFFER, 3},
/* normal */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 1583d16ca27..2d7fa760e49 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -682,10 +682,10 @@ int GPU_verify_image(
if (do_color_management) {
srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "floar_buf_col_cor");
gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf);
- frect = srgb_frect + texwinsy * ibuf->x + texwinsx;
+ frect = srgb_frect + (4 * (texwinsy * ibuf->x + texwinsx));
}
else {
- frect = ibuf->rect_float + texwinsy * ibuf->x + texwinsx;
+ frect = ibuf->rect_float + (ibuf->channels * (texwinsy * ibuf->x + texwinsx));
}
}
else {
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 1f3ae7f708a..f39cad20b9b 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -312,9 +312,11 @@ void GPU_material_free(ListBase *gpumaterial)
BLI_freelistN(gpumaterial);
}
-bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
+bool GPU_lamp_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
{
- if (srl && srl->light_override)
+ if (lamp->hide)
+ return false;
+ else if (srl && srl->light_override)
return BKE_group_object_exists(srl->light_override, lamp->ob);
else if (ma && ma->group)
return BKE_group_object_exists(ma->group, lamp->ob);
@@ -338,8 +340,8 @@ void GPU_material_bind(
for (LinkData *nlink = material->lamps.first; nlink; nlink = nlink->next) {
GPULamp *lamp = nlink->data;
- if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay)) &&
- GPU_lamp_override_visible(lamp, srl, material->ma))
+ if ((lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay)) &&
+ GPU_lamp_visible(lamp, srl, material->ma))
{
lamp->dynenergy = lamp->energy;
copy_v3_v3(lamp->dyncol, lamp->col);
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 9496ff137dc..632b0cfee1b 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -75,6 +75,12 @@ static GPUSelectState g_select_state = {0};
*/
void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *input, char mode, int oldhits)
{
+ if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ /* In the case hits was '-1', don't start the second pass since it's not going to give useful results.
+ * As well as buffer overflow in 'gpu_select_query_load_id'. */
+ BLI_assert(oldhits != -1);
+ }
+
g_select_state.select_is_active = true;
g_select_state.use_gpu_select = GPU_select_query_check_active();
g_select_state.mode = mode;
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index ba5fefc5227..3d589986281 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -142,13 +142,17 @@ bool gpu_select_query_load_id(unsigned int id)
g_query_state.active_query++;
g_query_state.query_issued = true;
- if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS && g_query_state.index < g_query_state.oldhits) {
- if (g_query_state.buffer[g_query_state.index][3] == id) {
- g_query_state.index++;
- return true;
- }
- else {
- return false;
+ if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ /* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */
+ BLI_assert(g_query_state.oldhits != -1);
+ if (g_query_state.index < g_query_state.oldhits) {
+ if (g_query_state.buffer[g_query_state.index][3] == id) {
+ g_query_state.index++;
+ return true;
+ }
+ else {
+ return false;
+ }
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 5c52b7fd153..3dbecc58a7e 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2621,29 +2621,26 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 resu
void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
- float clearcoat_gloss, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
{
/* ambient light */
// TODO: set ambient light to an appropriate value
- vec3 L = vec3(mix(0.1, 0.03, metallic)) * base_color.rgb;
+ vec3 L = mix(0.1, 0.03, metallic) * mix(base_color.rgb, subsurface_color.rgb, subsurface * (1.0 - metallic));
float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
/* set the viewing vector */
- vec3 V = -normalize(I);
+ vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? -normalize(I) : vec3(0.0, 0.0, 1.0);
/* get the tangent */
vec3 Tangent = T;
if (T == vec3(0.0)) {
// if no tangent is set, use a default tangent
- Tangent = vec3(1.0, 0.0, 0.0);
- if (N.x != 0.0 || N.y != 0.0) {
- vec3 N_xz = normalize(vec3(N.x, 0.0, N.z));
-
- vec3 axis = normalize(cross(vec3(0.0, 0.0, 1.0), N_xz));
- float angle = acos(dot(vec3(0.0, 0.0, 1.0), N_xz));
-
- Tangent = normalize(rotate_vector(vec3(1.0, 0.0, 0.0), axis, angle));
+ if(N.x != N.y || N.x != N.z) {
+ Tangent = vec3(N.z-N.y, N.x-N.z, N.y-N.x); // (1,1,1) x N
+ }
+ else {
+ Tangent = vec3(N.z-N.y, N.x+N.z, -N.y-N.x); // (-1,1,1) x N
}
}
@@ -2663,10 +2660,11 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
/* directional lights */
for (int i = 0; i < NUM_LIGHTS; i++) {
vec3 light_position_world = gl_LightSource[i].position.xyz;
- vec3 light_position = normalize(gl_NormalMatrix * light_position_world);
+ vec3 light_position = normalize(light_position_world);
vec3 H = normalize(light_position + V);
+ vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
vec3 light_specular = gl_LightSource[i].specular.rgb;
float NdotL = dot(N, light_position);
@@ -2711,8 +2709,9 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
// sheen
vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen;
- diffuse_and_specular_bsdf = (M_1_PI * mix(Fd, ss, subsurface) * base_color.rgb + Fsheen)
- * (1.0 - metallic) + Gs * Fs * Ds;
+ vec3 diffuse_bsdf = (mix(Fd * base_color.rgb, ss * subsurface_color.rgb, subsurface) + Fsheen) * light_diffuse;
+ vec3 specular_bsdf = Gs * Fs * Ds * light_specular;
+ diffuse_and_specular_bsdf = diffuse_bsdf * (1.0 - metallic) + specular_bsdf;
}
diffuse_and_specular_bsdf *= max(NdotL, 0.0);
@@ -2725,15 +2724,15 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
//float FH = schlick_fresnel(LdotH);
// clearcoat (ior = 1.5 -> F0 = 0.04)
- float Dr = GTR1(CNdotH, mix(0.1, 0.001, clearcoat_gloss));
+ float Dr = GTR1(CNdotH, sqr(clearcoat_roughness));
float Fr = fresnel_dielectric_cos(LdotH, 1.5); //mix(0.04, 1.0, FH);
float Gr = smithG_GGX(CNdotL, 0.25) * smithG_GGX(CNdotV, 0.25);
- clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25);
+ clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25) * light_specular;
}
clearcoat_bsdf *= max(CNdotL, 0.0);
- L += light_specular * (diffuse_and_specular_bsdf + clearcoat_bsdf);
+ L += diffuse_and_specular_bsdf + clearcoat_bsdf;
}
result = vec4(L, 1.0);
@@ -3032,10 +3031,10 @@ vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bi
float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0);
float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
- if(min_dist >= mortar_size) {
+ if (min_dist >= mortar_size) {
return vec2(tint, 0.0);
}
- else if(mortar_smooth == 0.0) {
+ else if (mortar_smooth == 0.0) {
return vec2(tint, 1.0);
}
else {
@@ -3117,15 +3116,17 @@ void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
}
void node_tex_image_box(vec3 texco,
- vec3 nob,
+ vec3 N,
sampler2D ima,
float blend,
out vec4 color,
out float alpha)
{
+ vec3 signed_N = N;
+
/* project from direction vector to barycentric coordinates in triangles */
- nob = vec3(abs(nob.x), abs(nob.y), abs(nob.z));
- nob /= (nob.x + nob.y + nob.z);
+ N = vec3(abs(N.x), abs(N.y), abs(N.z));
+ N /= (N.x + N.y + N.z);
/* basic idea is to think of this as a triangle, each corner representing
* one of the 3 faces of the cube. in the corners we have single textures,
@@ -3141,37 +3142,37 @@ void node_tex_image_box(vec3 texco,
float limit = 0.5 * (1.0 + blend);
/* first test for corners with single texture */
- if (nob.x > limit * (nob.x + nob.y) && nob.x > limit * (nob.x + nob.z)) {
+ if (N.x > limit * (N.x + N.y) && N.x > limit * (N.x + N.z)) {
weight.x = 1.0;
}
- else if (nob.y > limit * (nob.x + nob.y) && nob.y > limit * (nob.y + nob.z)) {
+ else if (N.y > limit * (N.x + N.y) && N.y > limit * (N.y + N.z)) {
weight.y = 1.0;
}
- else if (nob.z > limit * (nob.x + nob.z) && nob.z > limit * (nob.y + nob.z)) {
+ else if (N.z > limit * (N.x + N.z) && N.z > limit * (N.y + N.z)) {
weight.z = 1.0;
}
else if (blend > 0.0) {
/* in case of blending, test for mixes between two textures */
- if (nob.z < (1.0 - limit) * (nob.y + nob.x)) {
- weight.x = nob.x / (nob.x + nob.y);
+ if (N.z < (1.0 - limit) * (N.y + N.x)) {
+ weight.x = N.x / (N.x + N.y);
weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
weight.y = 1.0 - weight.x;
}
- else if (nob.x < (1.0 - limit) * (nob.y + nob.z)) {
- weight.y = nob.y / (nob.y + nob.z);
+ else if (N.x < (1.0 - limit) * (N.y + N.z)) {
+ weight.y = N.y / (N.y + N.z);
weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
weight.z = 1.0 - weight.y;
}
- else if (nob.y < (1.0 - limit) * (nob.x + nob.z)) {
- weight.x = nob.x / (nob.x + nob.z);
+ else if (N.y < (1.0 - limit) * (N.x + N.z)) {
+ weight.x = N.x / (N.x + N.z);
weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
weight.z = 1.0 - weight.x;
}
else {
/* last case, we have a mix between three */
- weight.x = ((2.0 - limit) * nob.x + (limit - 1.0)) / (2.0 * limit - 1.0);
- weight.y = ((2.0 - limit) * nob.y + (limit - 1.0)) / (2.0 * limit - 1.0);
- weight.z = ((2.0 - limit) * nob.z + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight.x = ((2.0 - limit) * N.x + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight.y = ((2.0 - limit) * N.y + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight.z = ((2.0 - limit) * N.z + (limit - 1.0)) / (2.0 * limit - 1.0);
}
}
else {
@@ -3180,13 +3181,25 @@ void node_tex_image_box(vec3 texco,
}
color = vec4(0);
if (weight.x > 0.0) {
- color += weight.x * texture2D(ima, texco.yz);
+ vec2 uv = texco.yz;
+ if(signed_N.x < 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ color += weight.x * texture2D(ima, uv);
}
if (weight.y > 0.0) {
- color += weight.y * texture2D(ima, texco.xz);
+ vec2 uv = texco.xz;
+ if(signed_N.y > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ color += weight.y * texture2D(ima, uv);
}
if (weight.z > 0.0) {
- color += weight.z * texture2D(ima, texco.yx);
+ vec2 uv = texco.yx;
+ if(signed_N.z > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ color += weight.z * texture2D(ima, uv);
}
alpha = color.a;
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index 6ea311b2c7b..f837789914e 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -217,9 +217,27 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3]) // nr =
copy_m4_m3(ikmat, ik_mat);
if (pchan->parent)
- mul_m4_series(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat);
+ mul_m4_m4m4(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat);
else
- mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, ikmat);
+ copy_m4_m4(pchan->pose_mat, pchan->chan_mat);
+
+#ifdef USE_NONUNIFORM_SCALE
+ /* apply IK mat, but as if the bones have uniform scale since the IK solver
+ * is not aware of non-uniform scale */
+ float scale[3];
+ mat4_to_size(scale, pchan->pose_mat);
+ normalize_v3_length(pchan->pose_mat[0], scale[1]);
+ normalize_v3_length(pchan->pose_mat[2], scale[1]);
+#endif
+
+ mul_m4_m4m4(pchan->pose_mat, pchan->pose_mat, ikmat);
+
+#ifdef USE_NONUNIFORM_SCALE
+ float ik_scale[3];
+ mat3_to_size(ik_scale, ik_mat);
+ normalize_v3_length(pchan->pose_mat[0], scale[0] * ik_scale[0]);
+ normalize_v3_length(pchan->pose_mat[2], scale[2] * ik_scale[2]);
+#endif
/* calculate head */
copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]);
@@ -308,6 +326,10 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* change length based on bone size */
length = bone->length * len_v3(R_bonemat[1]);
+ /* basis must be pure rotation */
+ normalize_m3(R_bonemat);
+ normalize_m3(R_parmat);
+
/* compute rest basis and its inverse */
copy_m3_m3(rest_basis, bone->bone_mat);
transpose_m3_m3(irest_basis, bone->bone_mat);
@@ -317,11 +339,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
mul_m3_m3m3(full_basis, iR_parmat, R_bonemat);
mul_m3_m3m3(basis, irest_basis, full_basis);
- /* basis must be pure rotation */
- normalize_m3(basis);
-
/* transform offset into local bone space */
- normalize_m3(iR_parmat);
mul_m3_v3(iR_parmat, start);
IK_SetTransform(seg, start, rest_basis, basis, length);
@@ -545,18 +563,6 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan
tree->pchan[a]->flag |= POSE_CHAIN;
}
-#ifdef USE_NONUNIFORM_SCALE
- float (*pchan_scale_data)[3] = MEM_mallocN(sizeof(float[3]) * tree->totchannel, __func__);
-
- for (a = 0; a < tree->totchannel; a++) {
- mat4_to_size(pchan_scale_data[a], tree->pchan[a]->pose_mat);
-
- /* make uniform at y scale since this controls the length */
- normalize_v3_length(tree->pchan[a]->pose_mat[0], pchan_scale_data[a][1]);
- normalize_v3_length(tree->pchan[a]->pose_mat[2], pchan_scale_data[a][1]);
- }
-#endif
-
/* 5. execute the IK solver */
execute_posetree(scene, ob, tree);
@@ -571,14 +577,6 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan
where_is_ik_bone(tree->pchan[a], tree->basis_change[a]);
}
-#ifdef USE_NONUNIFORM_SCALE
- for (a = 0; a < tree->totchannel; a++) {
- normalize_v3_length(tree->pchan[a]->pose_mat[0], pchan_scale_data[a][0]);
- normalize_v3_length(tree->pchan[a]->pose_mat[2], pchan_scale_data[a][2]);
- }
- MEM_freeN(pchan_scale_data);
-#endif
-
/* 7. and free */
BLI_remlink(&pchan_root->iktree, tree);
free_posetree(tree);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 93d2b3e0cd0..f1f36351e79 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -166,7 +166,7 @@ struct ImBuf *IMB_makeSingleUser(struct ImBuf *ibuf);
*
* \attention Defined in allocimbuf.c
*/
-struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1);
+struct ImBuf *IMB_dupImBuf(const struct ImBuf *ibuf1);
/**
*
@@ -205,6 +205,7 @@ typedef enum IMB_BlendMode {
IMB_BLEND_SATURATION = 21,
IMB_BLEND_LUMINOSITY = 22,
IMB_BLEND_COLOR = 23,
+ IMB_BLEND_INTERPOLATE = 24,
IMB_BLEND_COPY = 1000,
IMB_BLEND_COPY_RGB = 1001,
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index f4b2539d7d7..1701c2ba307 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -237,9 +237,8 @@ typedef struct ImBuf {
/**
* \name Imbuf Component flags
* \brief These flags determine the components of an ImBuf struct.
- */
-/**@{*/
-/** \brief Flag defining the components of the ImBuf struct. */
+ *
+ * \{ */
#define IB_rect (1 << 0)
#define IB_test (1 << 1)
@@ -259,15 +258,20 @@ typedef struct ImBuf {
#define IB_thumbnail (1 << 15)
#define IB_multiview (1 << 16)
+/** \} */
+
/**
* \name Imbuf preset profile tags
* \brief Some predefined color space profiles that 8 bit imbufs can represent
- */
+ *
+ * \{ */
#define IB_PROFILE_NONE 0
#define IB_PROFILE_LINEAR_RGB 1
#define IB_PROFILE_SRGB 2
#define IB_PROFILE_CUSTOM 3
+/** \} */
+
/* dds */
#ifdef WITH_DDS
#ifndef DDS_MAKEFOURCC
@@ -298,8 +302,16 @@ extern const char *imb_ext_audio[];
/* image formats that can only be loaded via filepath */
extern const char *imb_ext_image_filepath_only[];
+/**
+ * \name Imbuf Color Management Flag
+ * \brief Used with #ImBuf.colormanage_flag
+ *
+ * \{ */
+
enum {
IMB_COLORMANAGE_IS_DATA = (1 << 0)
};
-#endif
+/** \} */
+
+#endif /* __IMB_IMBUF_TYPES_H__ */
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 33750478bb4..6e9bfa1fc4e 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -506,7 +506,7 @@ bool IMB_initImBuf(struct ImBuf *ibuf,
}
/* does no zbuffers? */
-ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
+ImBuf *IMB_dupImBuf(const ImBuf *ibuf1)
{
ImBuf *ibuf2, tbuf;
int flags = 0;
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 8b4e95ac452..429a19936a5 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -183,7 +183,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
if (verbose) printf("DPX: File is LSB.\n");
}
else {
- if (verbose) {
+ if (verbose) {
printf("DPX: Bad magic number %u in \"%s\".\n",
header.fileHeader.magic_num, byteStuff);
}
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index ff19a14dbff..f510ded6b60 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -47,6 +47,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_filetype.h"
+#include "IMB_filter.h"
#include "IMB_moviecache.h"
#include "MEM_guardedalloc.h"
@@ -63,6 +64,7 @@
#include "BKE_context.h"
#include "BKE_image.h"
#include "BKE_main.h"
+#include "BKE_sequencer.h"
#include "RNA_define.h"
@@ -1112,6 +1114,7 @@ void IMB_colormanagement_check_file_config(Main *bmain)
for (scene = bmain->scene.first; scene; scene = scene->id.next) {
ColorManagedColorspaceSettings *sequencer_colorspace_settings;
+ /* check scene color management settings */
colormanage_check_display_settings(&scene->display_settings, "scene", default_display);
colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene");
@@ -1122,6 +1125,15 @@ void IMB_colormanagement_check_file_config(Main *bmain)
if (sequencer_colorspace_settings->name[0] == '\0') {
BLI_strncpy(sequencer_colorspace_settings->name, global_role_default_sequencer, MAX_COLORSPACE_NAME);
}
+
+ /* check sequencer strip input color space settings */
+ Sequence *seq;
+ SEQ_BEGIN (scene->ed, seq) {
+ if (seq->strip) {
+ colormanage_check_colorspace_settings(&seq->strip->colorspace_settings, "sequencer strip");
+ }
+ }
+ SEQ_END
}
/* ** check input color space settings ** */
@@ -1624,12 +1636,13 @@ static void *do_processor_transform_thread(void *handle_v)
if (float_from_byte) {
IMB_buffer_float_from_byte(float_buffer, byte_buffer,
IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- true,
+ false,
width, height, width, width);
- IMB_colormanagement_processor_apply(handle->cm_processor,
- float_buffer,
- width, height, channels,
- predivide);
+ IMB_colormanagement_processor_apply(handle->cm_processor,
+ float_buffer,
+ width, height, channels,
+ predivide);
+ IMB_premultiply_rect_float(float_buffer, 4, width, height);
}
else {
if (byte_buffer != NULL) {
@@ -1765,14 +1778,15 @@ void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsig
*/
IMB_buffer_float_from_byte(float_buffer, byte_buffer,
IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- true,
+ false,
width, height, width, width);
+ IMB_premultiply_rect_float(float_buffer, 4, width, height);
return;
}
cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
processor_transform_apply_threaded(byte_buffer, float_buffer,
width, height, channels,
- cm_processor, true, true);
+ cm_processor, false, true);
IMB_colormanagement_processor_free(cm_processor);
}
@@ -2554,6 +2568,14 @@ const char *IMB_colormanagement_colorspace_get_indexed_name(int index)
void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSettings *colorspace_settings, ImBuf *ibuf)
{
+ /* Don't modify non-color data space, it does not change with file type. */
+ ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name);
+
+ if (colorspace && colorspace->is_data) {
+ return;
+ }
+
+ /* Get color space from file type. */
const ImFileType *type;
for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index 390f2502ee7..388c2734fe9 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -588,7 +588,7 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
img_fol_t img_fol; /* only needed for cinema presets */
memset(&img_fol, 0, sizeof(img_fol_t));
- if (ibuf->float_colorspace) {
+ if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) {
/* float buffer was managed already, no need in color space conversion */
chanel_colormanage_cb = channel_colormanage_noop;
}
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index ec544e65355..1fa3b943524 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -1104,7 +1104,7 @@ void IMB_exr_write_channels(void *handle)
if (data->channels.first) {
const size_t num_pixels = ((size_t)data->width) * data->height;
- half *rect_half = NULL, *current_rect_half;
+ half *rect_half = NULL, *current_rect_half = NULL;
/* We allocate teporary storage for half pixels for all the channels at once. */
if (data->num_half_channels != 0) {
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index 503e63a3fb1..dded0f7aecf 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -152,7 +152,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
compression = (int)(((float)(ibuf->foptions.quality) / 11.1111f));
compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression);
- if (ibuf->float_colorspace) {
+ if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) {
/* float buffer was managed already, no need in color space conversion */
chanel_colormanage_cb = channel_colormanage_noop;
}
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index 3360fd7548e..c4325caac91 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -301,8 +301,8 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height,
IMB_BlendMode mode, bool accumulate)
{
- unsigned int *drect = NULL, *orect, *srect = NULL, *dr, *or, *sr;
- float *drectf = NULL, *orectf, *srectf = NULL, *drf, *orf, *srf;
+ unsigned int *drect = NULL, *orect = NULL, *srect = NULL, *dr, *or, *sr;
+ float *drectf = NULL, *orectf = NULL, *srectf = NULL, *drf, *orf, *srf;
unsigned short *cmaskrect = curvemask, *cmr;
unsigned short *dmaskrect = dmask, *dmr;
unsigned short *texmaskrect = texmask, *tmr;
@@ -424,6 +424,7 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
else {
switch (mode) {
case IMB_BLEND_MIX:
+ case IMB_BLEND_INTERPOLATE:
func = blend_color_mix_byte;
func_float = blend_color_mix_float;
break;
@@ -563,9 +564,15 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
mask_src[0] = src[0];
mask_src[1] = src[1];
mask_src[2] = src[2];
- mask_src[3] = divide_round_i(src[3] * mask, 65535);
- func((unsigned char *)dr, (unsigned char *)or, mask_src);
+ if (mode == IMB_BLEND_INTERPOLATE) {
+ mask_src[3] = src[3];
+ blend_color_interpolate_byte((unsigned char *)dr, (unsigned char *)or, mask_src, mask / 65535.0f);
+ }
+ else {
+ mask_src[3] = divide_round_i(src[3] * mask, 65535);
+ func((unsigned char *)dr, (unsigned char *)or, mask_src);
+ }
}
}
}
@@ -588,9 +595,15 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
mask_src[0] = src[0];
mask_src[1] = src[1];
mask_src[2] = src[2];
- mask_src[3] = divide_round_i(src[3] * mask, 65535);
- func((unsigned char *)dr, (unsigned char *)or, mask_src);
+ if (mode == IMB_BLEND_INTERPOLATE) {
+ mask_src[3] = src[3];
+ blend_color_interpolate_byte((unsigned char *)dr, (unsigned char *)or, mask_src, mask / 65535.0f);
+ }
+ else {
+ mask_src[3] = divide_round_i(src[3] * mask, 65535);
+ func((unsigned char *)dr, (unsigned char *)or, mask_src);
+ }
}
}
}
@@ -642,12 +655,16 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
mask = min_ff(mask, 65535.0);
if (mask > *dmr) {
- float mask_srf[4];
-
*dmr = mask;
- mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
- func_float(drf, orf, mask_srf);
+ if (mode == IMB_BLEND_INTERPOLATE) {
+ blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
+ }
+ else {
+ float mask_srf[4];
+ mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
+ func_float(drf, orf, mask_srf);
+ }
}
}
}
@@ -664,11 +681,15 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
mask = min_ff(mask, 65535.0);
if (srf[3] && (mask > 0.0f)) {
- float mask_srf[4];
-
- mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
+ if (mode == IMB_BLEND_INTERPOLATE) {
+ blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
+ }
+ else {
+ float mask_srf[4];
+ mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
+ func_float(drf, orf, mask_srf);
+ }
- func_float(drf, orf, mask_srf);
}
}
}
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index 4368a428186..8e5cf80e013 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -822,7 +822,7 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
/* convert from float source */
float rgb[4];
- if (ibuf->float_colorspace) {
+ if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) {
/* float buffer was managed already, no need in color space conversion */
copy_v3_v3(rgb, &fromf[from_i]);
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index da0f505c4f3..b2a3cb4f9bc 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -127,8 +127,7 @@ typedef struct ID {
/**
* LIB_TAG_... tags (runtime only, cleared at read time).
*/
- short tag;
- short pad_s1;
+ int tag;
int us;
int icon_id;
IDProperty *properties;
@@ -288,7 +287,7 @@ typedef enum ID_Type {
#ifdef GS
# undef GS
#endif
-#define GS(a) (CHECK_TYPE_ANY(a, char *, const char *, char [66], const char[66]), (*((const short *)(a))))
+#define GS(a) (CHECK_TYPE_ANY(a, char *, const char *, char [66], const char[66]), (ID_Type)(*((const short *)(a))))
#define ID_NEW_SET(_id, _idn) \
(((ID *)(_id))->newid = (ID *)(_idn), ((ID *)(_id))->newid->tag |= LIB_TAG_NEW, (void *)((ID *)(_id))->newid)
@@ -350,6 +349,13 @@ enum {
LIB_TAG_ID_RECALC_DATA = 1 << 13,
LIB_TAG_ANIM_NO_RECALC = 1 << 14,
LIB_TAG_ID_RECALC_ALL = (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA),
+
+ /* RESET_NEVER tag datablock for freeing etc. behavior (usually set when copying real one into temp/runtime one). */
+ LIB_TAG_NO_MAIN = 1 << 16, /* Datablock is not listed in Main database. */
+ LIB_TAG_NO_USER_REFCOUNT = 1 << 17, /* Datablock does not refcount usages of other IDs. */
+ /* Datablock was not allocated by standard system (BKE_libblock_alloc), do not free its memory
+ * (usual type-specific freeing is called though). */
+ LIB_TAG_NOT_ALLOCATED = 1 << 18,
};
/* To filter ID types (filter_id) */
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 1083400ece2..d49960771d0 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -514,7 +514,7 @@ typedef enum eActionGroup_Flag {
AGRP_MODIFIERS_OFF = (1 << 7),
AGRP_TEMP = (1 << 30),
- AGRP_MOVED = (1 << 31)
+ AGRP_MOVED = (1u << 31)
} eActionGroup_Flag;
@@ -757,7 +757,7 @@ typedef enum ACHAN_FLAG {
ACHAN_EXPANDED = (1 << 4),
ACHAN_SHOWIPO = (1 << 5),
ACHAN_SHOWCONS = (1 << 6),
- ACHAN_MOVED = (1 << 31)
+ ACHAN_MOVED = (1u << 31)
} ACHAN_FLAG;
#endif /* __DNA_ACTION_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index e50a2637fff..935a893f689 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -685,7 +685,7 @@ typedef enum eNlaStrip_Flag {
/* temporary editing flags */
/* NLA-Strip is really just a temporary meta used to facilitate easier transform code */
NLASTRIP_FLAG_TEMP_META = (1<<30),
- NLASTRIP_FLAG_EDIT_TOUCHED = (1<<31)
+ NLASTRIP_FLAG_EDIT_TOUCHED = (1u << 31)
} eNlaStrip_Flag;
/* NLA Strip Type */
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 733a9f64c29..bb6b0f8955a 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -215,7 +215,7 @@ typedef enum BrushFlags {
BRUSH_CUSTOM_ICON = (1 << 28),
BRUSH_LINE = (1 << 29),
BRUSH_ABSOLUTE_JITTER = (1 << 30),
- BRUSH_CURVE = (1 << 31)
+ BRUSH_CURVE = (1u << 31)
} BrushFlags;
typedef enum {
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 823a7f0812f..67b29264d6c 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -98,7 +98,7 @@ typedef enum ModifierMode {
eModifierMode_Expanded = (1 << 4),
eModifierMode_Virtual = (1 << 5),
eModifierMode_ApplyOnSpline = (1 << 6),
- eModifierMode_DisableTemporary = (1 << 31)
+ eModifierMode_DisableTemporary = (1u << 31)
} ModifierMode;
typedef struct ModifierData {
@@ -924,9 +924,10 @@ typedef struct ScrewModifierData {
unsigned int iter;
float screw_ofs;
float angle;
- char axis;
- char pad;
+ float merge_dist;
short flag;
+ char axis;
+ char pad[5];
} ScrewModifierData;
enum {
@@ -937,6 +938,7 @@ enum {
MOD_SCREW_SMOOTH_SHADING = (1 << 5),
MOD_SCREW_UV_STRETCH_U = (1 << 6),
MOD_SCREW_UV_STRETCH_V = (1 << 7),
+ MOD_SCREW_MERGE = (1 << 8),
};
typedef struct OceanModifierData {
@@ -1515,7 +1517,7 @@ enum {
MOD_DATATRANSFER_USE_VERT = 1 << 28,
MOD_DATATRANSFER_USE_EDGE = 1 << 29,
MOD_DATATRANSFER_USE_LOOP = 1 << 30,
- MOD_DATATRANSFER_USE_POLY = 1 << 31,
+ MOD_DATATRANSFER_USE_POLY = 1u << 31,
};
/* Set Split Normals modifier */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index b922ac072b0..e6bc315b728 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -111,7 +111,7 @@ typedef struct bNodeSocket {
short stack_index; /* local stack index */
/* XXX deprecated, kept for forward compatibility */
short stack_type DNA_DEPRECATED;
- int pad;
+ char draw_shape, pad[3];
void *cache; /* cached data from execution */
@@ -143,6 +143,13 @@ typedef enum eNodeSocketDatatype {
SOCK_STRING = 7
} eNodeSocketDatatype;
+/* socket shape */
+typedef enum eNodeSocketDrawShape {
+ SOCK_DRAW_SHAPE_CIRCLE = 0,
+ SOCK_DRAW_SHAPE_SQUARE = 1,
+ SOCK_DRAW_SHAPE_DIAMOND = 2
+} eNodeSocketDrawShape;
+
/* socket side (input/output) */
typedef enum eNodeSocketInOut {
SOCK_IN = 1,
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 1deb9bf3787..f6bed37dfa2 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -323,7 +323,7 @@ typedef struct ParticleSystem {
struct ParticleDrawData *pdd;
float dt_frac; /* current time step, as a fraction of a frame */
- float _pad; /* spare capacity */
+ float lattice_strength; /* influence of the lattice modifier */
} ParticleSystem;
typedef enum eParticleDrawFlag {
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 40413a03044..2a36d8bbea1 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -751,7 +751,7 @@ typedef struct RenderData {
/* sequencer options */
char seq_prev_type;
- char seq_rend_type;
+ char seq_rend_type; /* UNUSED! */
char seq_flag; /* flag use for sequence render/draw */
char pad5[5];
@@ -790,14 +790,13 @@ typedef struct RenderData {
struct BakeData bake;
int preview_start_resolution;
+ short preview_pixel_size;
/* Type of the debug pass to use.
* Only used when built with debug passes support.
*/
short debug_pass_type;
- short pad;
-
/* MultiView */
ListBase views; /* SceneRenderView */
short actview;
@@ -1759,8 +1758,7 @@ typedef struct Scene {
/* use preview range */
#define SCER_PRV_RANGE (1<<0)
#define SCER_LOCK_FRAME_SELECTION (1<<1)
- /* timeline/keyframe jumping - only selected items (on by default) */
-#define SCE_KEYS_NO_SELONLY (1<<2)
+ /* show/use subframes (for checking motion blur) */
#define SCER_SHOW_SUBFRAME (1<<3)
/* mode (int now) */
@@ -1800,7 +1798,7 @@ typedef struct Scene {
#define R_USE_WS_SHADING 0x8000000 /* use world space interpretation of lighting data */
/* seq_flag */
-#define R_SEQ_GL_PREV 1
+// #define R_SEQ_GL_PREV 1 // UNUSED, we just use setting from seq_prev_type now.
// #define R_SEQ_GL_REND 2 // UNUSED, opengl render has its own operator now.
#define R_SEQ_SOLID_TEX 4
@@ -1945,16 +1943,18 @@ extern const char *RE_engine_id_CYCLES;
/* **************** SCENE ********************* */
/* note that much higher maxframes give imprecise sub-frames, see: T46859 */
+/* Current precision is 16 for the sub-frames closer to MAXFRAME. */
+
/* for general use */
-#define MAXFRAME 500000
-#define MAXFRAMEF 500000.0f
+#define MAXFRAME 1048574
+#define MAXFRAMEF 1048574.0f
#define MINFRAME 0
#define MINFRAMEF 0.0f
/* (minimum frame number for current-frame) */
-#define MINAFRAME -500000
-#define MINAFRAMEF -500000.0f
+#define MINAFRAME -1048574
+#define MINAFRAMEF -1048574.0f
/* depricate this! */
#define TESTBASE(v3d, base) ( \
@@ -2094,6 +2094,7 @@ typedef enum eVGroupSelect {
#define SCE_DS_COLLAPSED (1<<1)
#define SCE_NLA_EDIT_ON (1<<2)
#define SCE_FRAME_DROP (1<<3)
+#define SCE_KEYS_NO_SELONLY (1<<4)
/* return flag BKE_scene_base_iter_next functions */
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index e208ef39719..fd63d7c471c 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -366,7 +366,7 @@ enum {
/* uiList filter orderby type */
enum {
UILST_FLT_SORT_ALPHA = 1 << 0,
- UILST_FLT_SORT_REVERSE = 1 << 31 /* Special value, bitflag used to reverse order! */
+ UILST_FLT_SORT_REVERSE = 1u << 31 /* Special value, bitflag used to reverse order! */
};
#define UILST_FLT_SORT_MASK (((unsigned int)UILST_FLT_SORT_REVERSE) - 1)
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 1f4e4df4660..74a1a13c2eb 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -442,7 +442,7 @@ enum {
/* access scene strips directly (like a metastrip) */
SEQ_SCENE_STRIPS = (1 << 30),
- SEQ_INVALID_EFFECT = (1 << 31),
+ SEQ_INVALID_EFFECT = (1u << 31),
};
/* StripProxy->storage */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 0e5d9bd33e6..d6490d99016 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -741,7 +741,7 @@ typedef enum eFileSel_File_Types {
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),
+ FILE_TYPE_BLENDERLIB = (1u << 31),
} eFileSel_File_Types;
/* Selection Flags in filesel: struct direntry, unsigned char selflag */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 5e7e7366e35..cddb1e06b8c 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -48,7 +48,8 @@ struct ColorBand;
#define MAX_STYLE_NAME 64
-/* default uifont_id offered by Blender */
+/* default offered by Blender.
+ * uiFont.uifont_id */
typedef enum eUIFont_ID {
UIFONT_DEFAULT = 0,
/* UIFONT_BITMAP = 1 */ /* UNUSED */
@@ -64,7 +65,7 @@ typedef struct uiFont {
struct uiFont *next, *prev;
char filename[1024];/* 1024 = FILE_MAX */
short blf_id; /* from blfont lib */
- short uifont_id; /* own id */
+ short uifont_id; /* own id (eUIFont_ID) */
short r_to_l; /* fonts that read from left to right */
short hinting;
} uiFont;
@@ -84,7 +85,7 @@ typedef struct uiFontStyle {
float shadowcolor; /* 1 value, typically white or black anyway */
} uiFontStyle;
-/* uiFontStyle->align */
+/* uiFontStyle.align */
typedef enum eFontStyle_Align {
UI_STYLE_TEXT_LEFT = 0,
UI_STYLE_TEXT_CENTER = 1,
@@ -354,11 +355,11 @@ typedef struct ThemeWireColor {
char select[4];
char active[4];
- short flag;
+ short flag; /* eWireColor_Flags */
short pad;
} ThemeWireColor;
-/* flags for ThemeWireColor */
+/* ThemeWireColor.flag */
typedef enum eWireColor_Flags {
TH_WIRECOLOR_CONSTCOLS = (1 << 0),
TH_WIRECOLOR_TEXTCOLS = (1 << 1),
@@ -434,7 +435,8 @@ typedef struct UserDef {
/* UserDef has separate do-version handling, and can be read from other files */
int versionfile, subversionfile;
- int flag, dupflag;
+ int flag; /* eUserPref_Flag */
+ int dupflag; /* eDupli_ID_Flags */
int savetime;
char tempdir[768]; /* FILE_MAXDIR length */
char fontdir[768];
@@ -450,14 +452,15 @@ typedef struct UserDef {
int anim_player_preset;
short v2d_min_gridsize; /* minimum spacing between gridlines in View2D grids */
- short timecode_style; /* style of timecode display */
+ short timecode_style; /* eTimecodeStyles, style of timecode display */
short versions;
short dbl_click_time;
short gameflags;
short wheellinescroll;
- int uiflag, uiflag2;
+ int uiflag; /* eUserpref_UI_Flag */
+ int uiflag2; /* eUserpref_UI_Flag2 */
int language;
short userpref, viewzoom;
@@ -470,10 +473,10 @@ typedef struct UserDef {
int scrollback; /* console scrollback limit */
int dpi; /* range 48-128? */
float ui_scale; /* interface scale */
- int pad1;
+ int ui_line_width; /* interface line width */
char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */
char pad2;
- short transopts;
+ short transopts; /* eUserpref_Translation_Flags */
short menuthreshold1, menuthreshold2;
/* startup template */
@@ -491,12 +494,12 @@ typedef struct UserDef {
short undosteps;
short undomemory;
short gp_manhattendist, gp_euclideandist, gp_eraser;
- short gp_settings;
+ short gp_settings; /* eGP_UserdefSettings */
short tb_leftmouse, tb_rightmouse;
struct SolidLight light[3];
short tw_hotspot, tw_flag, tw_handlesize, tw_size;
short textimeout, texcollectrate;
- short wmdrawmethod; /* removed wmpad */
+ short wmdrawmethod; /* eWM_DrawMethod */
short dragthreshold;
int memcachelimit;
int prefetchframes;
@@ -509,13 +512,13 @@ typedef struct UserDef {
short smooth_viewtx; /* miliseconds to spend spinning the view */
short glreslimit;
short curssize;
- short color_picker_type;
+ short color_picker_type; /* eColorPicker_Types */
char ipo_new; /* interpolation mode for newly added F-Curves */
char keyhandles_new; /* handle types for newly added keyframes */
char gpu_select_method;
char gpu_select_pick_deph;
char pad4;
- char view_frame_type;
+ char view_frame_type; /* eZoomFrame_Mode */
int view_frame_keyframes; /* number of keyframes to zoom around current frame */
float view_frame_seconds; /* seconds to zoom around current frame */
@@ -530,15 +533,16 @@ typedef struct UserDef {
float ndof_sensitivity; /* overall sensitivity of 3D mouse */
float ndof_orbit_sensitivity;
float ndof_deadzone; /* deadzone of 3D mouse */
- int ndof_flag; /* flags for 3D mouse */
+ int ndof_flag; /* eNdof_Flag, flags for 3D mouse */
- short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */
+ short ogl_multisamples; /* eMultiSample_Type, amount of samples for OpenGL FSA, if zero no FSA */
- short image_draw_method; /* Method to be used to draw the images (AUTO, GLSL, Textures or DrawPixels) */
+ /* eImageDrawMethod, Method to be used to draw the images (AUTO, GLSL, Textures or DrawPixels) */
+ short image_draw_method;
float glalphaclip;
- short autokey_mode; /* autokeying mode */
+ short autokey_mode; /* eAutokey_Mode, autokeying mode */
short autokey_flag; /* flags for autokeying */
short text_render, pad9; /* options for text rendering */
@@ -582,7 +586,7 @@ extern UserDef U; /* from blenkernel blender.c */
/* ***************** USERDEF ****************** */
-/* userpref/section */
+/* UserDef.userpref (UI active_section) */
typedef enum eUserPref_Section {
USER_SECTION_INTERFACE = 0,
USER_SECTION_EDIT = 1,
@@ -593,19 +597,19 @@ typedef enum eUserPref_Section {
USER_SECTION_ADDONS = 6,
} eUserPref_Section;
-/* flag */
+/* UserDef.flag */
typedef enum eUserPref_Flag {
USER_AUTOSAVE = (1 << 0),
-/* USER_AUTOGRABGRID = (1 << 1), deprecated */
-/* USER_AUTOROTGRID = (1 << 2), deprecated */
-/* USER_AUTOSIZEGRID = (1 << 3), deprecated */
+ USER_FLAG_DEPRECATED_1 = (1 << 1), /* cleared */
+ USER_FLAG_DEPRECATED_2 = (1 << 2), /* cleared */
+ USER_FLAG_DEPRECATED_3 = (1 << 3), /* cleared */
USER_SCENEGLOBAL = (1 << 4),
USER_TRACKBALL = (1 << 5),
-/* USER_DUPLILINK = (1 << 6), deprecated */
-/* USER_FSCOLLUM = (1 << 7), deprecated */
+ USER_FLAG_DEPRECATED_6 = (1 << 6), /* cleared */
+ USER_FLAG_DEPRECATED_7 = (1 << 7), /* cleared */
USER_MAT_ON_OB = (1 << 8),
-/* USER_NO_CAPSLOCK = (1 << 9), */ /* not used anywhere */
-/* USER_VIEWMOVE = (1 << 10), */ /* not used anywhere */
+ USER_FLAG_DEPRECATED_9 = (1 << 9), /* cleared */
+ USER_FLAG_DEPRECATED_10 = (1 << 10), /* cleared */
USER_TOOLTIPS = (1 << 11),
USER_TWOBUTTONMOUSE = (1 << 12),
USER_NONUMPAD = (1 << 13),
@@ -624,7 +628,7 @@ typedef enum eUserPref_Flag {
USER_TOOLTIPS_PYTHON = (1 << 26),
} eUserPref_Flag;
-/* flag */
+/* bPathCompare.flag */
typedef enum ePathCompare_Flag {
USER_PATHCMP_GLOB = (1 << 0),
} ePathCompare_Flag;
@@ -635,33 +639,34 @@ typedef enum ePathCompare_Flag {
cfra = 0; \
} (void)0
-/* viewzoom */
+/* UserDef.viewzoom */
typedef enum eViewZoom_Style {
USER_ZOOM_CONT = 0,
USER_ZOOM_SCALE = 1,
USER_ZOOM_DOLLY = 2
} eViewZoom_Style;
-/* navigation_mode */
+/* UserDef.navigation_mode */
typedef enum eViewNavigation_Method {
VIEW_NAVIGATION_WALK = 0,
VIEW_NAVIGATION_FLY = 1,
} eViewNavigation_Method;
-/* flag */
+/* UserDef.flag */
typedef enum eWalkNavigation_Flag {
USER_WALK_GRAVITY = (1 << 0),
USER_WALK_MOUSE_REVERSE = (1 << 1),
} eWalkNavigation_Flag;
-/* uiflag */
+/* UserDef.uiflag */
typedef enum eUserpref_UI_Flag {
/* flags 0 and 1 were old flags (for autokeying) that aren't used anymore */
USER_WHEELZOOMDIR = (1 << 2),
USER_FILTERFILEEXTS = (1 << 3),
USER_DRAWVIEWINFO = (1 << 4),
USER_PLAINMENUS = (1 << 5),
- /* flags 6 and 7 were old flags that are no-longer used */
+ USER_LOCK_CURSOR_ADJUST = (1 << 6),
+ USER_UIFLAG_DEPRECATED_7 = (1 << 7), /* cleared */
USER_ALLWINCODECS = (1 << 8),
USER_MENUOPENAUTO = (1 << 9),
USER_ZBUF_CURSOR = (1 << 10),
@@ -685,17 +690,18 @@ typedef enum eUserpref_UI_Flag {
USER_HIDE_RECENT = (1 << 28),
USER_SHOW_THUMBNAILS = (1 << 29),
USER_QUIT_PROMPT = (1 << 30),
- USER_HIDE_SYSTEM_BOOKMARKS = (1 << 31)
+ USER_HIDE_SYSTEM_BOOKMARKS = (1u << 31)
} eUserpref_UI_Flag;
-/* uiflag2 */
+/* UserDef.uiflag2 */
typedef enum eUserpref_UI_Flag2 {
USER_KEEP_SESSION = (1 << 0),
USER_REGION_OVERLAP = (1 << 1),
USER_TRACKPAD_NATURAL = (1 << 2),
} eUserpref_UI_Flag2;
-/* Auto-Keying mode */
+/* Auto-Keying mode.
+ * UserDef.autokey_mode */
typedef enum eAutokey_Mode {
/* AUTOKEY_ON is a bitflag */
AUTOKEY_ON = 1,
@@ -705,7 +711,8 @@ typedef enum eAutokey_Mode {
AUTOKEY_MODE_EDITKEYS = 5
} eAutokey_Mode;
-/* Zoom to frame mode */
+/* Zoom to frame mode.
+ * UserDef.view_frame_type */
typedef enum eZoomFrame_Mode {
ZOOM_FRAME_MODE_KEEP_RANGE = 0,
ZOOM_FRAME_MODE_SECONDS = 1,
@@ -728,20 +735,20 @@ typedef enum eAutokey_Flag {
ANIMRECORD_FLAG_WITHNLA = (1 << 10),
} eAutokey_Flag;
-/* transopts */
+/* UserDef.transopts */
typedef enum eUserpref_Translation_Flags {
USER_TR_TOOLTIPS = (1 << 0),
USER_TR_IFACE = (1 << 1),
-/* USER_TR_MENUS = (1 << 2), deprecated */
-/* USER_TR_FILESELECT = (1 << 3), deprecated */
-/* USER_TR_TEXTEDIT = (1 << 4), deprecated */
+ USER_TR_DEPRECATED_2 = (1 << 2), /* cleared */
+ USER_TR_DEPRECATED_3 = (1 << 3), /* cleared */
+ USER_TR_DEPRECATED_4 = (1 << 4), /* cleared */
USER_DOTRANSLATE = (1 << 5),
- USER_USETEXTUREFONT = (1 << 6),
-/* CONVERT_TO_UTF8 = (1 << 7), deprecated */
+ USER_TR_DEPRECATED_6 = (1 << 6), /* cleared */
+ USER_TR_DEPRECATED_7 = (1 << 7), /* cleared */
USER_TR_NEWDATANAME = (1 << 8),
} eUserpref_Translation_Flags;
-/* dupflag */
+/* UserDef.dupflag */
typedef enum eDupli_ID_Flags {
USER_DUP_MESH = (1 << 0),
USER_DUP_CURVE = (1 << 1),
@@ -757,14 +764,13 @@ typedef enum eDupli_ID_Flags {
USER_DUP_PSYS = (1 << 11)
} eDupli_ID_Flags;
-/* gameflags */
+/* UserDef.gameflags */
typedef enum eOpenGL_RenderingOptions {
- /* USER_DEPRECATED_FLAG = (1 << 0), */
- /* USER_DISABLE_SOUND = (1 << 1), */ /* deprecated, don't use without checking for */
- /* backwards compatibilty in do_versions! */
- USER_DISABLE_MIPMAP = (1 << 2),
- /* USER_DISABLE_VBO = (1 << 3), */ /* DEPRECATED we always use vertex buffers now */
- /* USER_DISABLE_AA = (1 << 4), */ /* DEPRECATED */
+ USER_GL_RENDER_DEPRECATED_0 = (1 << 0),
+ USER_GL_RENDER_DEPRECATED_1 = (1 << 1),
+ USER_DISABLE_MIPMAP = (1 << 2),
+ USER_GL_RENDER_DEPRECATED_3 = (1 << 3),
+ USER_GL_RENDER_DEPRECATED_4 = (1 << 4),
} eOpenGL_RenderingOptions;
/* selection method for opengl gpu_select_method */
@@ -774,7 +780,8 @@ typedef enum eOpenGL_SelectOptions {
USER_SELECT_USE_SELECT_RENDERMODE = 2
} eOpenGL_SelectOptions;
-/* wm draw method */
+/* wm draw method.
+ * UserDef.wmdrawmethod */
typedef enum eWM_DrawMethod {
USER_DRAW_TRIPLE = 0,
USER_DRAW_OVERLAP = 1,
@@ -783,20 +790,23 @@ typedef enum eWM_DrawMethod {
USER_DRAW_OVERLAP_FLIP = 4,
} eWM_DrawMethod;
-/* text draw options */
+/* text draw options
+ * UserDef.text_render */
typedef enum eText_Draw_Options {
USER_TEXT_DISABLE_AA = (1 << 0),
} eText_Draw_Options;
/* tw_flag (transform widget) */
-/* gp_settings (Grease Pencil Settings) */
+/* Grease Pencil Settings.
+ * UserDef.gp_settings */
typedef enum eGP_UserdefSettings {
GP_PAINT_DOSMOOTH = (1 << 0),
GP_PAINT_DOSIMPLIFY = (1 << 1),
} eGP_UserdefSettings;
-/* color picker types */
+/* Color Picker Types.
+ * UserDef.color_picker_type */
typedef enum eColorPicker_Types {
USER_CP_CIRCLE_HSV = 0,
USER_CP_SQUARE_SV = 1,
@@ -805,7 +815,8 @@ typedef enum eColorPicker_Types {
USER_CP_CIRCLE_HSL = 4,
} eColorPicker_Types;
-/* timecode display styles */
+/* timecode display styles
+ * UserDef.timecode_style */
typedef enum eTimecodeStyles {
/* as little info as is necessary to show relevant info
* with '+' to denote the frames
@@ -840,7 +851,7 @@ typedef enum eTheme_DrawTypes {
TH_SHADED = 4
} eTheme_DrawTypes;
-/* ndof_flag (3D mouse options) */
+/* UserDef.ndof_flag (3D mouse options) */
typedef enum eNdof_Flag {
NDOF_SHOW_GUIDE = (1 << 0),
NDOF_FLY_HELICOPTER = (1 << 1),
@@ -873,6 +884,7 @@ typedef enum eNdof_Flag {
#define NDOF_PIXELS_PER_SECOND 600.0f
+/* UserDef.ogl_multisamples */
typedef enum eMultiSample_Type {
USER_MULTISAMPLE_NONE = 0,
USER_MULTISAMPLE_2 = 2,
@@ -880,7 +892,8 @@ typedef enum eMultiSample_Type {
USER_MULTISAMPLE_8 = 8,
USER_MULTISAMPLE_16 = 16,
} eMultiSample_Type;
-
+
+/* UserDef.image_draw_method */
typedef enum eImageDrawMethod {
/* IMAGE_DRAW_METHOD_AUTO = 0, */ /* Currently unused */
IMAGE_DRAW_METHOD_GLSL = 1,
@@ -888,6 +901,7 @@ typedef enum eImageDrawMethod {
IMAGE_DRAW_METHOD_DRAWPIXELS = 3,
} eImageDrawMethod;
+/* UserDef.virtual_pixel */
typedef enum eUserpref_VirtualPixel {
VIRTUAL_PIXEL_NATIVE = 0,
VIRTUAL_PIXEL_DOUBLE = 1,
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 4c243507e82..b9894d46b5b 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -225,7 +225,8 @@ typedef struct View3D {
struct GPUFXSettings fx_settings;
void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */
- struct Material *defmaterial; /* used by matcap now */
+ /* Allocated per view, not library data (used by matcap). */
+ struct Material *defmaterial;
/* XXX deprecated? */
struct bGPdata *gpd DNA_DEPRECATED; /* Grease-Pencil Data (annotation layers) */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index a1af3f98274..f83608fa24b 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -783,6 +783,9 @@ const struct ListBase *RNA_struct_type_functions(StructRNA *srna);
char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len);
+bool RNA_struct_available_or_report(struct ReportList *reports, const char *identifier);
+bool RNA_struct_bl_idname_ok_or_report(struct ReportList *reports, const char *identifier, const char *sep);
+
/* Properties
*
* Access to struct properties. All this works with RNA pointers rather than
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 6e62313b00a..42ffe774720 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -62,7 +62,8 @@ void RNA_def_struct_refine_func(StructRNA *srna, const char *refine);
void RNA_def_struct_idprops_func(StructRNA *srna, const char *refine);
void RNA_def_struct_register_funcs(StructRNA *srna, const char *reg, const char *unreg, const char *instance);
void RNA_def_struct_path_func(StructRNA *srna, const char *path);
-void RNA_def_struct_identifier(StructRNA *srna, const char *identifier);
+void RNA_def_struct_identifier_no_struct_map(StructRNA *srna, const char *identifier);
+void RNA_def_struct_identifier(BlenderRNA *brna, StructRNA *srna, const char *identifier);
void RNA_def_struct_ui_text(StructRNA *srna, const char *name, const char *description);
void RNA_def_struct_ui_icon(StructRNA *srna, int icon);
void RNA_struct_free_extension(StructRNA *srna, ExtensionRNA *ext);
@@ -216,8 +217,8 @@ void RNA_enum_item_end(EnumPropertyItem **items, int *totitem);
/* Memory management */
-void RNA_def_struct_duplicate_pointers(StructRNA *srna);
-void RNA_def_struct_free_pointers(StructRNA *srna);
+void RNA_def_struct_duplicate_pointers(BlenderRNA *brna, StructRNA *srna);
+void RNA_def_struct_free_pointers(BlenderRNA *brna, StructRNA *srna);
void RNA_def_func_duplicate_pointers(FunctionRNA *func);
void RNA_def_func_free_pointers(FunctionRNA *func);
void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA *prop);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 1c9b3593d17..f8e240d57bf 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -114,6 +114,8 @@ extern EnumPropertyItem rna_enum_brush_image_tool_items[];
extern EnumPropertyItem rna_enum_gpencil_sculpt_brush_items[];
+extern EnumPropertyItem rna_enum_uv_sculpt_tool_items[];
+
extern EnumPropertyItem rna_enum_axis_xy_items[];
extern EnumPropertyItem rna_enum_axis_xyz_items[];
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index cd04f9e8a6d..e119c49401e 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -178,7 +178,7 @@ typedef enum PropertyFlag {
* after every typed char, instead of waiting final validation. Used e.g. for text searchbox.
* It will also cause UI_BUT_VALUE_CLEAR to be set for text buttons. We could add an own flag
* for search/filter properties, but this works just fine for now. */
- PROP_TEXTEDIT_UPDATE = (1 << 31),
+ PROP_TEXTEDIT_UPDATE = (1u << 31),
/* icon */
PROP_ICONS_CONSECUTIVE = (1 << 12),
@@ -436,6 +436,8 @@ typedef enum StructFlag {
STRUCT_NO_IDPROPERTIES = (1 << 6), /* Menus and Panels don't need properties */
STRUCT_NO_DATABLOCK_IDPROPERTIES = (1 << 7), /* e.g. for Operator */
STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES = (1 << 8), /* for PropertyGroup which contains pointers to datablocks */
+ STRUCT_PUBLIC_NAMESPACE = (1 << 9), /* Added to type-map #BlenderRNA.structs_map */
+ STRUCT_PUBLIC_NAMESPACE_INHERIT = (1 << 10), /* All subtypes are added too. */
} StructFlag;
typedef int (*StructValidateFunc)(struct PointerRNA *ptr, void *data, int *have_function);
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 6a08d762920..9d0ba5586af 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -140,6 +140,9 @@ set(GENSRC_CFLAGS)
if(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
set(GENSRC_CFLAGS "-Wno-missing-prototypes")
endif()
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(GENSRC_CFLAGS "${GENSRC_CFLAGS} -Wno-missing-variable-declarations")
+endif()
if(GENSRC_CFLAGS)
set_source_files_properties(${GENSRC} PROPERTIES COMPILE_FLAGS "${GENSRC_CFLAGS}")
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index de436172bfd..9471d0e3fcf 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -2583,17 +2583,23 @@ static void rna_generate_blender(BlenderRNA *brna, FILE *f)
{
StructRNA *srna;
- fprintf(f, "BlenderRNA BLENDER_RNA = {");
-
+ fprintf(f,
+ "BlenderRNA BLENDER_RNA = {\n"
+ "\t.structs = {"
+ );
srna = brna->structs.first;
- if (srna) fprintf(f, "{&RNA_%s, ", srna->identifier);
- else fprintf(f, "{NULL, ");
+ if (srna) fprintf(f, "&RNA_%s, ", srna->identifier);
+ else fprintf(f, "NULL, ");
srna = brna->structs.last;
- if (srna) fprintf(f, "&RNA_%s}", srna->identifier);
- else fprintf(f, "NULL}");
+ if (srna) fprintf(f, "&RNA_%s},\n", srna->identifier);
+ else fprintf(f, "NULL},\n");
- fprintf(f, "};\n\n");
+ fprintf(f,
+ "\t.structs_map = NULL,\n"
+ "\t.structs_len = 0,\n"
+ "};\n\n"
+ );
}
static void rna_generate_property_prototypes(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE *f)
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index a299302f04f..bfa1e7cef93 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -76,6 +76,9 @@ void RNA_init(void)
StructRNA *srna;
PropertyRNA *prop;
+ BLENDER_RNA.structs_map = BLI_ghash_str_new_ex(__func__, 2048);
+ BLENDER_RNA.structs_len = 0;
+
for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
if (!srna->cont.prophash) {
srna->cont.prophash = BLI_ghash_str_new("RNA_init gh");
@@ -86,6 +89,9 @@ void RNA_init(void)
}
}
}
+ BLI_assert(srna->flag & STRUCT_PUBLIC_NAMESPACE);
+ BLI_ghash_insert(BLENDER_RNA.structs_map, (void *)srna->identifier, srna);
+ BLENDER_RNA.structs_len += 1;
}
}
@@ -513,13 +519,7 @@ static const char *rna_ensure_property_name(const PropertyRNA *prop)
StructRNA *RNA_struct_find(const char *identifier)
{
- StructRNA *type;
- if (identifier) {
- for (type = BLENDER_RNA.structs.first; type; type = type->cont.next)
- if (STREQ(type->identifier, identifier))
- return type;
- }
- return NULL;
+ return BLI_ghash_lookup(BLENDER_RNA.structs_map, identifier);
}
const char *RNA_struct_identifier(const StructRNA *type)
@@ -815,6 +815,89 @@ char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, i
return NULL;
}
+/**
+ * Use when registering structs with the #STRUCT_PUBLIC_NAMESPACE flag.
+ */
+bool RNA_struct_available_or_report(ReportList *reports, const char *identifier)
+{
+ const StructRNA *srna_exists = RNA_struct_find(identifier);
+ if (UNLIKELY(srna_exists != NULL)) {
+ /* Use comprehensive string construction since this is such a rare occurrence
+ * and information here may cut down time troubleshooting. */
+ DynStr *dynstr = BLI_dynstr_new();
+ BLI_dynstr_appendf(dynstr, "Type identifier '%s' is already in use: '", identifier);
+ BLI_dynstr_append(dynstr, srna_exists->identifier);
+ int i = 0;
+ if (srna_exists->base) {
+ for (const StructRNA *base = srna_exists->base; base; base = base->base) {
+ BLI_dynstr_append(dynstr, "(");
+ BLI_dynstr_append(dynstr, base->identifier);
+ i += 1;
+ }
+ while (i--) {
+ BLI_dynstr_append(dynstr, ")");
+ }
+ }
+ BLI_dynstr_append(dynstr, "'.");
+ char *result = BLI_dynstr_get_cstring(dynstr);
+ BLI_dynstr_free(dynstr);
+ BKE_report(reports, RPT_ERROR, result);
+ MEM_freeN(result);
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+bool RNA_struct_bl_idname_ok_or_report(ReportList *reports, const char *identifier, const char *sep)
+{
+ const int len_sep = strlen(sep);
+ const int len_id = strlen(identifier);
+ const char *p = strstr(identifier, sep);
+ /* TODO: make error, for now warning until add-ons update. */
+#if 1
+ const int report_level = RPT_WARNING;
+ const bool failure = true;
+#else
+ const int report_level = RPT_ERROR;
+ const bool failure = false;
+#endif
+ if (p == NULL || p == identifier || p + len_sep >= identifier + len_id) {
+ BKE_reportf(reports, report_level, "'%s' doesn't contain '%s' with prefix & suffix", identifier, sep);
+ return failure;
+ }
+
+ const char *c, *start, *end, *last;
+ start = identifier;
+ end = p;
+ last = end - 1;
+ for (c = start; c != end; c++) {
+ if (((*c >= 'A' && *c <= 'Z') ||
+ ((c != start) && (*c >= '0' && *c <= '9')) ||
+ ((c != start) && (c != last) && (*c == '_'))) == 0)
+ {
+ BKE_reportf(reports, report_level, "'%s' doesn't have upper case alpha-numeric prefix", identifier);
+ return failure;
+ }
+ }
+
+ start = p + len_sep;
+ end = identifier + len_id;
+ last = end - 1;
+ for (c = start; c != end; c++) {
+ if (((*c >= 'A' && *c <= 'Z') ||
+ (*c >= 'a' && *c <= 'z') ||
+ (*c >= '0' && *c <= '9') ||
+ ((c != start) && (c != last) && (*c == '_'))) == 0)
+ {
+ BKE_reportf(reports, report_level, "'%s' doesn't have an alpha-numeric suffix", identifier);
+ return failure;
+ }
+ }
+ return true;
+}
+
/* Property Information */
const char *RNA_property_identifier(PropertyRNA *prop)
@@ -6446,7 +6529,7 @@ static int rna_function_parameter_parse(PointerRNA *ptr, PropertyRNA *prop, Prop
tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(srna));
return -1;
}
-
+
*((void **)dest) = *((void **)src);
break;
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index f271bccd326..d9f673acf89 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -270,9 +270,10 @@ static StructRNA *rna_KeyingSetInfo_register(Main *bmain, ReportList *reports, v
/* check if we have registered this info before, and remove it */
ksi = ANIM_keyingset_info_find_name(dummyksi.idname);
- if (ksi && ksi->ext.srna)
+ if (ksi && ksi->ext.srna) {
rna_KeyingSetInfo_unregister(bmain, ksi->ext.srna);
-
+ }
+
/* create a new KeyingSetInfo type */
ksi = MEM_callocN(sizeof(KeyingSetInfo), "python keying set info");
memcpy(ksi, &dummyksi, sizeof(KeyingSetInfo));
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 891f5c43ca6..ec700eb00de 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -480,7 +480,7 @@ static int rna_Armature_is_editmode_get(PointerRNA *ptr)
static void rna_Armature_transform(struct bArmature *arm, float *mat)
{
- ED_armature_transform(arm, (float (*)[4])mat);
+ ED_armature_transform(arm, (float (*)[4])mat, true);
}
#else
diff --git a/source/blender/makesrna/intern/rna_curve_api.c b/source/blender/makesrna/intern/rna_curve_api.c
index b4b3aa84ec5..be6808567bb 100644
--- a/source/blender/makesrna/intern/rna_curve_api.c
+++ b/source/blender/makesrna/intern/rna_curve_api.c
@@ -45,7 +45,7 @@
#ifdef RNA_RUNTIME
static void rna_Curve_transform(Curve *cu, float *mat, int shape_keys)
{
- BKE_curve_transform(cu, (float (*)[4])mat, shape_keys);
+ BKE_curve_transform(cu, (float (*)[4])mat, shape_keys, true);
DAG_id_tag_update(&cu->id, 0);
}
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 42c0344f46e..0e91c158669 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -135,6 +135,38 @@ void rna_freelistN(ListBase *listbase)
listbase->first = listbase->last = NULL;
}
+static void rna_brna_structs_add(BlenderRNA *brna, StructRNA *srna)
+{
+ rna_addtail(&brna->structs, srna);
+ brna->structs_len += 1;
+
+ /* This exception is only needed for pre-processing.
+ * otherwise we don't allow empty names. */
+ if ((srna->flag & STRUCT_PUBLIC_NAMESPACE) &&
+ (srna->identifier[0] != '\0'))
+ {
+ BLI_ghash_insert(brna->structs_map, (void *)srna->identifier, srna);
+ }
+}
+
+#ifdef RNA_RUNTIME
+static void rna_brna_structs_remove_and_free(BlenderRNA *brna, StructRNA *srna)
+{
+ if ((srna->flag & STRUCT_PUBLIC_NAMESPACE) && brna->structs_map) {
+ if (srna->identifier[0] != '\0') {
+ BLI_ghash_remove(brna->structs_map, (void *)srna->identifier, NULL, NULL);
+ }
+ }
+
+ RNA_def_struct_free_pointers(NULL, srna);
+
+ if (srna->flag & STRUCT_RUNTIME) {
+ rna_freelinkN(&brna->structs, srna);
+ }
+ brna->structs_len -= 1;
+}
+#endif
+
StructDefRNA *rna_find_struct_def(StructRNA *srna)
{
StructDefRNA *dsrna;
@@ -534,6 +566,8 @@ BlenderRNA *RNA_create(void)
const char *error_message = NULL;
BLI_listbase_clear(&DefRNA.structs);
+ brna->structs_map = BLI_ghash_str_new_ex(__func__, 2048);
+
DefRNA.error = 0;
DefRNA.preprocess = 1;
@@ -640,10 +674,8 @@ void RNA_struct_free(BlenderRNA *brna, StructRNA *srna)
rna_freelinkN(&srna->functions, func);
}
- RNA_def_struct_free_pointers(srna);
- if (srna->flag & STRUCT_RUNTIME)
- rna_freelinkN(&brna->structs, srna);
+ rna_brna_structs_remove_and_free(brna, srna);
#else
UNUSED_VARS(brna, srna);
#endif
@@ -654,6 +686,9 @@ void RNA_free(BlenderRNA *brna)
StructRNA *srna, *nextsrna;
FunctionRNA *func;
+ BLI_ghash_free(brna->structs_map, NULL, NULL);
+ brna->structs_map = NULL;
+
if (DefRNA.preprocess) {
RNA_define_free(brna);
@@ -730,12 +765,19 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN
BLI_listbase_clear(&srna->functions);
srna->py_type = NULL;
+ srna->base = srnafrom;
+
if (DefRNA.preprocess) {
- srna->base = srnafrom;
dsfrom = rna_find_def_struct(srnafrom);
}
- else
- srna->base = srnafrom;
+ else {
+ if (srnafrom->flag & STRUCT_PUBLIC_NAMESPACE_INHERIT) {
+ srna->flag |= STRUCT_PUBLIC_NAMESPACE | STRUCT_PUBLIC_NAMESPACE_INHERIT;
+ }
+ else {
+ srna->flag &= ~(STRUCT_PUBLIC_NAMESPACE | STRUCT_PUBLIC_NAMESPACE_INHERIT);
+ }
+ }
}
srna->identifier = identifier;
@@ -747,7 +789,11 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN
if (!srnafrom)
srna->icon = ICON_DOT;
- rna_addtail(&brna->structs, srna);
+ if (DefRNA.preprocess) {
+ srna->flag |= STRUCT_PUBLIC_NAMESPACE;
+ }
+
+ rna_brna_structs_add(brna, srna);
if (DefRNA.preprocess) {
ds = MEM_callocN(sizeof(StructDefRNA), "StructDefRNA");
@@ -819,10 +865,8 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
if (from) {
/* find struct to derive from */
- for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
- if (STREQ(srnafrom->identifier, from))
- break;
-
+ /* Inline RNA_struct_find(...) because it wont link from here. */
+ srnafrom = BLI_ghash_lookup(brna->structs_map, from);
if (!srnafrom) {
fprintf(stderr, "%s: struct %s not found to define %s.\n", __func__, from, identifier);
DefRNA.error = 1;
@@ -901,10 +945,7 @@ void RNA_def_struct_nested(BlenderRNA *brna, StructRNA *srna, const char *struct
StructRNA *srnafrom;
/* find struct to derive from */
- for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
- if (STREQ(srnafrom->identifier, structname))
- break;
-
+ srnafrom = BLI_ghash_lookup(brna->structs_map, structname);
if (!srnafrom) {
fprintf(stderr, "%s: struct %s not found for %s.\n", __func__, structname, srna->identifier);
DefRNA.error = 1;
@@ -965,7 +1006,32 @@ void RNA_def_struct_path_func(StructRNA *srna, const char *path)
if (path) srna->path = (StructPathFunc)path;
}
-void RNA_def_struct_identifier(StructRNA *srna, const char *identifier)
+void RNA_def_struct_identifier(BlenderRNA *brna, StructRNA *srna, const char *identifier)
+{
+ if (DefRNA.preprocess) {
+ fprintf(stderr, "%s: only at runtime.\n", __func__);
+ return;
+ }
+
+ /* Operator registration may set twice, see: operator_properties_init */
+ if (srna->flag & STRUCT_PUBLIC_NAMESPACE) {
+ if (identifier != srna->identifier) {
+ if (srna->identifier[0] != '\0') {
+ BLI_ghash_remove(brna->structs_map, (void *)srna->identifier, NULL, NULL);
+ }
+ if (identifier[0] != '\0') {
+ BLI_ghash_insert(brna->structs_map, (void *)identifier, srna);
+ }
+ }
+ }
+
+ srna->identifier = identifier;
+}
+
+/**
+ * Only used in one case when we name the struct for the purpose of useful error messages.
+ */
+void RNA_def_struct_identifier_no_struct_map(StructRNA *srna, const char *identifier)
{
if (DefRNA.preprocess) {
fprintf(stderr, "%s: only at runtime.\n", __func__);
@@ -3262,21 +3328,41 @@ void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
/* Memory management */
#ifdef RNA_RUNTIME
-void RNA_def_struct_duplicate_pointers(StructRNA *srna)
+void RNA_def_struct_duplicate_pointers(BlenderRNA *brna, StructRNA *srna)
{
- if (srna->identifier) srna->identifier = BLI_strdup(srna->identifier);
- if (srna->name) srna->name = BLI_strdup(srna->name);
- if (srna->description) srna->description = BLI_strdup(srna->description);
+ if (srna->identifier) {
+ srna->identifier = BLI_strdup(srna->identifier);
+ if (srna->flag & STRUCT_PUBLIC_NAMESPACE) {
+ BLI_ghash_replace_key(brna->structs_map, (void *)srna->identifier);
+ }
+ }
+ if (srna->name) {
+ srna->name = BLI_strdup(srna->name);
+ }
+ if (srna->description) {
+ srna->description = BLI_strdup(srna->description);
+ }
srna->flag |= STRUCT_FREE_POINTERS;
}
-void RNA_def_struct_free_pointers(StructRNA *srna)
+void RNA_def_struct_free_pointers(BlenderRNA *brna, StructRNA *srna)
{
if (srna->flag & STRUCT_FREE_POINTERS) {
- if (srna->identifier) MEM_freeN((void *)srna->identifier);
- if (srna->name) MEM_freeN((void *)srna->name);
- if (srna->description) MEM_freeN((void *)srna->description);
+ if (srna->identifier) {
+ if (srna->flag & STRUCT_PUBLIC_NAMESPACE) {
+ if (brna != NULL) {
+ BLI_ghash_remove(brna->structs_map, (void *)srna->identifier, NULL, NULL);
+ }
+ }
+ MEM_freeN((void *)srna->identifier);
+ }
+ if (srna->name) {
+ MEM_freeN((void *)srna->name);
+ }
+ if (srna->description) {
+ MEM_freeN((void *)srna->description);
+ }
}
}
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index bccc47aa95d..ad63a652b12 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -765,6 +765,38 @@ static void rna_FModifierStepped_end_frame_range(PointerRNA *ptr, float *min, fl
*max = MAXFRAMEF;
}
+static void rna_FModifierStepped_frame_start_set(PointerRNA *ptr, float value)
+{
+ FModifier *fcm = (FModifier *)ptr->data;
+ FMod_Stepped *data = fcm->data;
+
+ float prop_clamp_min = -FLT_MAX, prop_clamp_max = FLT_MAX, prop_soft_min, prop_soft_max;
+ rna_FModifierStepped_start_frame_range(ptr, &prop_clamp_min, &prop_clamp_max, &prop_soft_min, &prop_soft_max);
+ value = CLAMPIS(value, prop_clamp_min, prop_clamp_max);
+
+ /* Need to set both step-data's start/end and the start/end on the base-data,
+ * or else Restrict-Range doesn't work due to RNA-property shadowing (T52009)
+ */
+ data->start_frame = value;
+ fcm->sfra = value;
+}
+
+static void rna_FModifierStepped_frame_end_set(PointerRNA *ptr, float value)
+{
+ FModifier *fcm = (FModifier *)ptr->data;
+ FMod_Stepped *data = fcm->data;
+
+ float prop_clamp_min = -FLT_MAX, prop_clamp_max = FLT_MAX, prop_soft_min, prop_soft_max;
+ rna_FModifierStepped_end_frame_range(ptr, &prop_clamp_min, &prop_clamp_max, &prop_soft_min, &prop_soft_max);
+ value = CLAMPIS(value, prop_clamp_min, prop_clamp_max);
+
+ /* Need to set both step-data's start/end and the start/end on the base-data,
+ * or else Restrict-Range doesn't work due to RNA-property shadowing (T52009)
+ */
+ data->end_frame = value;
+ fcm->efra = value;
+}
+
static BezTriple *rna_FKeyframe_points_insert(FCurve *fcu, float frame, float value, int keyframe_type, int flag)
{
int index = insert_vert_fcurve(fcu, frame, value, (char)keyframe_type, flag | INSERTKEY_NO_USERPREF);
@@ -1284,13 +1316,13 @@ static void rna_def_fmodifier_stepped(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "start_frame");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierStepped_start_frame_range");
+ RNA_def_property_float_funcs(prop, NULL, "rna_FModifierStepped_frame_start_set", "rna_FModifierStepped_start_frame_range");
RNA_def_property_ui_text(prop, "Start Frame", "Frame that modifier's influence starts (if applicable)");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update");
prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "end_frame");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierStepped_end_frame_range");
+ RNA_def_property_float_funcs(prop, NULL, "rna_FModifierStepped_frame_end_set", "rna_FModifierStepped_end_frame_range");
RNA_def_property_ui_text(prop, "End Frame", "Frame that modifier's influence ends (if applicable)");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update");
}
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 6e0d6ad2bcd..79e1e95b27a 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -74,7 +74,7 @@ static void rna_GPencil_editmode_update(Main *UNUSED(bmain), Scene *UNUSED(scene
{
/* Notify all places where GPencil data lives that the editing state is different */
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
- WM_main_add_notifier(NC_SCENE | ND_MODE, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NC_MOVIECLIP, NULL);
}
static void rna_GPencil_onion_skinning_update(Main *bmain, Scene *scene, PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index b6e84cf8ac3..5ca7e624d88 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -192,6 +192,8 @@ static char *rna_ImageUser_path(PointerRNA *ptr)
{
return rna_Node_ImageUser_path(ptr);
}
+ default:
+ break;
}
}
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 344c1781b46..5c706d9d8db 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -291,7 +291,7 @@ static void rna_Image_filepath_from_user(Image *image, ImageUser *image_user, ch
static void rna_Image_buffers_free(Image *image)
{
- BKE_image_free_buffers(image);
+ BKE_image_free_buffers_ex(image, true);
}
#else
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index df591659fdb..a470c807091 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -413,6 +413,11 @@ struct StructRNA {
struct BlenderRNA {
ListBase structs;
+ /* A map of structs: {StructRNA.identifier -> StructRNA}
+ * These are ensured to have unique names (with STRUCT_PUBLIC_NAMESPACE enabled). */
+ struct GHash *structs_map;
+ /* Needed because types with an empty identifier aren't included in 'structs_map'. */
+ unsigned int structs_len;
};
#define CONTAINER_RNA_ID(cont) (*(const char **)(((ContainerRNA *)(cont))+1))
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index a5abc8a3be2..b960890457b 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -178,6 +178,8 @@ static Mesh *rna_KeyBlock_normals_get_mesh(PointerRNA *ptr, ID *id)
return ob->data;
}
}
+ default:
+ break;
}
}
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index 1199cccc4e6..a163d9764c1 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -1620,6 +1620,7 @@ static void rna_def_linestyle(BlenderRNA *brna)
prop = RNA_def_property(srna, "panel", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "panel");
RNA_def_property_enum_items(prop, panel_items);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Panel", "Select the property panel to be shown");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index cb133aa683c..766ed5432af 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -46,6 +46,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_types.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
diff --git a/source/blender/makesrna/intern/rna_meta_api.c b/source/blender/makesrna/intern/rna_meta_api.c
index 3d8f375fd88..4c3fa787b94 100644
--- a/source/blender/makesrna/intern/rna_meta_api.c
+++ b/source/blender/makesrna/intern/rna_meta_api.c
@@ -45,7 +45,7 @@
#ifdef RNA_RUNTIME
static void rna_Meta_transform(struct MetaBall *mb, float *mat)
{
- BKE_mball_transform(mb, (float (*)[4])mat);
+ BKE_mball_transform(mb, (float (*)[4])mat, true);
DAG_id_tag_update(&mb->id, 0);
}
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 1a8dd05a7b5..e53237ae2c1 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -3413,6 +3413,13 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Screw", "Offset the revolution along its axis");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "merge_dist");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0, 1, 1, 4);
+ RNA_def_property_ui_text(prop, "Merge Distance", "Limit below which to merge vertices");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "use_normal_flip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SCREW_NORMAL_FLIP);
RNA_def_property_ui_text(prop, "Flip", "Flip normals of lathed faces");
@@ -3428,6 +3435,12 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Object Screw", "Use the distance between the objects to make a screw");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ /* Vertex merging parameters */
+ prop = RNA_def_property(srna, "use_merge_vertices", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SCREW_MERGE);
+ RNA_def_property_ui_text(prop, "Merge Vertices", "Merge adjacent vertices (screw offset must be zero)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "use_smooth_shade", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SCREW_SMOOTH_SHADING);
RNA_def_property_ui_text(prop, "Smooth Shading", "Output faces with smooth shading rather than flat shaded");
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index e44a6420045..d72c858a5d5 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -659,7 +659,10 @@ static void rna_def_nlastrip(BlenderRNA *brna)
prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Influence", "Amount the strip contributes to the current result");
- RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update");
+ /* XXX: Update temporarily disabled so that the property can be edited at all!
+ * Even autokey only applies after the curves have been re-evaluated, causing the unkeyed values to be lost
+ */
+ RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, /*"rna_NlaStrip_update"*/ NULL);
prop = RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 22d07d739cd..ee4608b550f 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -73,6 +73,13 @@ EnumPropertyItem rna_enum_node_socket_in_out_items[] = {
};
#ifndef RNA_RUNTIME
+static EnumPropertyItem rna_enum_node_socket_draw_shape_items[] = {
+ {SOCK_DRAW_SHAPE_CIRCLE, "CIRCLE", 0, "Circle", ""},
+ {SOCK_DRAW_SHAPE_SQUARE, "SQUARE", 0, "Square", ""},
+ {SOCK_DRAW_SHAPE_DIAMOND, "DIAMOND", 0, "Diamond", ""},
+ {0, NULL, 0, NULL, NULL }
+};
+
static EnumPropertyItem node_socket_type_items[] = {
{SOCK_CUSTOM, "CUSTOM", 0, "Custom", ""},
{SOCK_FLOAT, "VALUE", 0, "Value", ""},
@@ -238,10 +245,10 @@ bNodeTreeType *rna_node_tree_type_from_enum(int value)
EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, bNodeTreeType *), bool *r_free)
{
- EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem tmp = {0};
EnumPropertyItem *item = NULL;
int totitem = 0, i = 0;
-
+
NODE_TREE_TYPES_BEGIN (nt)
{
if (poll && !poll(data, nt)) {
@@ -261,9 +268,14 @@ EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, b
}
NODE_TREE_TYPES_END;
+ if (totitem == 0) {
+ *r_free = false;
+ return DummyRNA_NULL_items;
+ }
+
RNA_enum_item_end(&item, &totitem);
*r_free = true;
-
+
return item;
}
@@ -310,9 +322,9 @@ bNodeType *rna_node_type_from_enum(int value)
EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, bNodeType *), bool *r_free)
{
EnumPropertyItem *item = NULL;
- EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem tmp = {0};
int totitem = 0, i = 0;
-
+
NODE_TYPES_BEGIN(ntype)
if (poll && !poll(data, ntype)) {
++i;
@@ -329,9 +341,15 @@ EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, bNodeT
++i;
NODE_TYPES_END
+
+ if (totitem == 0) {
+ *r_free = false;
+ return DummyRNA_NULL_items;
+ }
+
RNA_enum_item_end(&item, &totitem);
*r_free = true;
-
+
return item;
}
@@ -378,10 +396,10 @@ bNodeSocketType *rna_node_socket_type_from_enum(int value)
EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data, bNodeSocketType *), bool *r_free)
{
EnumPropertyItem *item = NULL;
- EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem tmp = {0};
int totitem = 0, i = 0;
StructRNA *srna;
-
+
NODE_SOCKET_TYPES_BEGIN(stype)
if (poll && !poll(data, stype)) {
++i;
@@ -399,9 +417,15 @@ EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data,
++i;
NODE_SOCKET_TYPES_END
+
+ if (totitem == 0) {
+ *r_free = false;
+ return DummyRNA_NULL_items;
+ }
+
RNA_enum_item_end(&item, &totitem);
*r_free = true;
-
+
return item;
}
@@ -410,25 +434,25 @@ static EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), Pointer
EnumPropertyItem *item = NULL;
EnumPropertyItem tmp;
int totitem = 0;
-
+
/* hack, don't want to add include path to RNA just for this, since in the future RNA types
* for nodes should be defined locally at runtime anyway ...
*/
-
+
tmp.value = NODE_CUSTOM;
tmp.identifier = "CUSTOM";
tmp.name = "Custom";
tmp.description = "Custom Node";
tmp.icon = ICON_NONE;
RNA_enum_item_add(&item, &totitem, &tmp);
-
+
tmp.value = NODE_UNDEFINED;
tmp.identifier = "UNDEFINED";
tmp.name = "UNDEFINED";
tmp.description = "";
tmp.icon = ICON_NONE;
RNA_enum_item_add(&item, &totitem, &tmp);
-
+
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
if (STREQ(#Category, "Node")) { \
tmp.value = ID; \
@@ -440,7 +464,7 @@ static EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), Pointer
}
#include "../../nodes/NOD_static_types.h"
#undef DefNode
-
+
if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
if (STREQ(#Category, "ShaderNode")) { \
@@ -468,7 +492,7 @@ static EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), Pointer
#include "../../nodes/NOD_static_types.h"
#undef DefNode
}
-
+
if (RNA_struct_is_a(ptr->type, &RNA_TextureNode)) {
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
if (STREQ(#Category, "TextureNode")) { \
@@ -485,7 +509,7 @@ static EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), Pointer
RNA_enum_item_end(&item, &totitem);
*r_free = true;
-
+
return item;
}
@@ -578,11 +602,10 @@ static void rna_NodeTree_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &nt->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
ntreeTypeFreeLink(nt);
- RNA_struct_free(&BLENDER_RNA, type);
-
/* update while blender is running */
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
}
@@ -614,9 +637,10 @@ static StructRNA *rna_NodeTree_register(
/* check if we have registered this tree type before, and remove it */
nt = ntreeTypeFind(dummynt.idname);
- if (nt)
+ if (nt) {
rna_NodeTree_unregister(bmain, nt->ext.srna);
-
+ }
+
/* create a new node tree type */
nt = MEM_callocN(sizeof(bNodeTreeType), "node tree type");
memcpy(nt, &dummynt, sizeof(dummynt));
@@ -1331,11 +1355,11 @@ static void rna_Node_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &nt->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
/* this also frees the allocated nt pointer, no MEM_free call needed! */
nodeUnregisterType(nt);
- RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
@@ -1376,8 +1400,9 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc
/* check if we have registered this node type before, and remove it */
nt = nodeTypeFind(dummynt.idname);
- if (nt)
+ if (nt) {
rna_Node_unregister(bmain, nt->ext.srna);
+ }
/* create a new node type */
nt = MEM_callocN(sizeof(bNodeType), "node type");
@@ -1793,10 +1818,10 @@ static void rna_NodeSocket_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &st->ext_socket);
+ RNA_struct_free(&BLENDER_RNA, type);
nodeUnregisterSocketType(st);
- RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
@@ -2617,9 +2642,9 @@ static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *p
static EnumPropertyItem *renderresult_layers_add_enum(RenderLayer *rl)
{
EnumPropertyItem *item = NULL;
- EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem tmp = {0};
int i = 0, totitem = 0;
-
+
while (rl) {
tmp.identifier = rl->name;
/* little trick: using space char instead empty string makes the item selectable in the dropdown */
@@ -2631,7 +2656,7 @@ static EnumPropertyItem *renderresult_layers_add_enum(RenderLayer *rl)
RNA_enum_item_add(&item, &totitem, &tmp);
rl = rl->next;
}
-
+
RNA_enum_item_end(&item, &totitem);
return item;
@@ -2644,18 +2669,17 @@ static EnumPropertyItem *rna_Node_image_layer_itemf(bContext *UNUSED(C), Pointer
Image *ima = (Image *)node->id;
EnumPropertyItem *item = NULL;
RenderLayer *rl;
-
- if (ima && ima->rr) {
- rl = ima->rr->layers.first;
- item = renderresult_layers_add_enum(rl);
- }
- else {
- int totitem = 0;
- RNA_enum_item_end(&item, &totitem);
+
+ if (ima == NULL || ima->rr == NULL) {
+ *r_free = false;
+ return DummyRNA_NULL_items;
}
-
+
+ rl = ima->rr->layers.first;
+ item = renderresult_layers_add_enum(rl);
+
*r_free = true;
-
+
return item;
}
@@ -2706,19 +2730,22 @@ static EnumPropertyItem *renderresult_views_add_enum(RenderView *rv)
}
static EnumPropertyItem *rna_Node_image_view_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), bool *free)
+ PropertyRNA *UNUSED(prop), bool *r_free)
{
bNode *node = (bNode *)ptr->data;
Image *ima = (Image *)node->id;
EnumPropertyItem *item = NULL;
RenderView *rv;
- if (!ima || !(ima->rr)) return NULL;
+ if (ima == NULL || ima->rr == NULL) {
+ *r_free = false;
+ return DummyRNA_NULL_items;
+ }
rv = ima->rr->views.first;
item = renderresult_views_add_enum(rv);
- *free = true;
+ *r_free = true;
return item;
}
@@ -2730,18 +2757,17 @@ static EnumPropertyItem *rna_Node_scene_layer_itemf(bContext *UNUSED(C), Pointer
Scene *sce = (Scene *)node->id;
EnumPropertyItem *item = NULL;
RenderLayer *rl;
-
- if (sce) {
- rl = sce->r.layers.first;
- item = renderresult_layers_add_enum(rl);
- }
- else {
- int totitem = 0;
- RNA_enum_item_end(&item, &totitem);
+
+ if (sce == NULL) {
+ *r_free = false;
+ return DummyRNA_NULL_items;
}
-
+
+ rl = sce->r.layers.first;
+ item = renderresult_layers_add_enum(rl);
+
*r_free = true;
-
+
return item;
}
@@ -2758,7 +2784,7 @@ static EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), PointerRNA
{
bNode *node = (bNode *)ptr->data;
EnumPropertyItem *item = NULL;
- EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem tmp = {0};
int totitem = 0;
switch (node->custom1) {
@@ -2795,7 +2821,7 @@ static EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), PointerRNA
RNA_enum_item_add(&item, &totitem, &tmp);
break;
default:
- break;
+ return DummyRNA_NULL_items;
}
RNA_enum_item_end(&item, &totitem);
@@ -3339,7 +3365,7 @@ static void def_frame(StructRNA *srna)
prop = RNA_def_property(srna, "text", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Text");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Text", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -3609,7 +3635,7 @@ static void def_sh_lamp(StructRNA *srna)
prop = RNA_def_property(srna, "lamp_object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Lamp_object_poll");
RNA_def_property_ui_text(prop, "Lamp Object", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -3983,7 +4009,7 @@ static void def_sh_tex_coord(StructRNA *srna)
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Object", "Use coordinates from this object (for object texture coordinates output)");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -4099,7 +4125,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Object", "Object to take point data from");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -4796,7 +4822,7 @@ static void def_cmp_render_layers(StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_scene_set", NULL, NULL);
RNA_def_property_struct_type(prop, "Scene");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Scene", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update");
@@ -5453,7 +5479,7 @@ static void def_cmp_defocus(StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_scene_set", NULL, NULL);
RNA_def_property_struct_type(prop, "Scene");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Scene", "Scene from which to select the active camera (render scene if undefined)");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -6320,14 +6346,8 @@ static void def_cmp_switch(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
-static void def_cmp_switch_view(StructRNA *srna)
+static void def_cmp_switch_view(StructRNA *UNUSED(srna))
{
- PropertyRNA *prop;
-
- prop = RNA_def_property(srna, "check", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "custom1", 0);
- RNA_def_property_ui_text(prop, "Switch", "Off: first socket, On: second socket");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_colorcorrection(StructRNA *srna)
@@ -6974,6 +6994,13 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Type", "Data type");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
+ prop = RNA_def_property(srna, "draw_shape", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "draw_shape");
+ RNA_def_property_enum_items(prop, rna_enum_node_socket_draw_shape_items);
+ RNA_def_property_enum_default(prop, SOCK_DRAW_SHAPE_CIRCLE);
+ RNA_def_property_ui_text(prop, "Shape", "Socket shape");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
+
/* registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 3c3d88c858f..00104b8667d 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -446,10 +446,12 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
int totpart;
int totchild = 0;
int totface;
+ int totvert;
int num = -1;
DM_ensure_tessface(modifier->dm_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
totface = modifier->dm_final->getNumTessFaces(modifier->dm_final);
+ totvert = modifier->dm_final->getNumVerts(modifier->dm_final);
/* 1. check that everything is ok & updated */
if (!particlesystem || !totface) {
@@ -484,13 +486,29 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
return num;
}
}
+ else if (part->from == PART_FROM_VERT) {
+ if (num != DMCACHE_NOTFOUND && num < totvert) {
+ MFace *mface = modifier->dm_final->getTessFaceDataArray(modifier->dm_final, CD_MFACE);
+
+ *r_fuv = &particle->fuv;
+
+ /* This finds the first face to contain the emitting vertex,
+ * this is not ideal, but is mostly fine as UV seams generally
+ * map to equal-colored parts of a texture */
+ for (int i = 0; i < totface; i++, mface++) {
+ if (ELEM(num, mface->v1, mface->v2, mface->v3, mface->v4)) {
+ return i;
+ }
+ }
+ }
+ }
}
else {
ChildParticle *cpa = particlesystem->child + particle_no - totpart;
num = cpa->num;
if (part->childtype == PART_CHILD_FACES) {
- if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME, PART_FROM_VERT)) {
if (num != DMCACHE_NOTFOUND && num < totface) {
*r_fuv = &cpa->fuv;
return num;
@@ -510,6 +528,22 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
return num;
}
}
+ else if (part->from == PART_FROM_VERT) {
+ if (num != DMCACHE_NOTFOUND && num < totvert) {
+ MFace *mface = modifier->dm_final->getTessFaceDataArray(modifier->dm_final, CD_MFACE);
+
+ *r_fuv = &parent->fuv;
+
+ /* This finds the first face to contain the emitting vertex,
+ * this is not ideal, but is mostly fine as UV seams generally
+ * map to equal-colored parts of a texture */
+ for (int i = 0; i < totface; i++, mface++) {
+ if (ELEM(num, mface->v1, mface->v2, mface->v3, mface->v4)) {
+ return i;
+ }
+ }
+ }
+ }
}
}
@@ -2095,7 +2129,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Even Distribution",
"Use even distribution from faces based on face areas or edge lengths");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
+
prop = RNA_def_property(srna, "use_die_on_collision", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_DIE_ON_COL);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 44dcb72264a..a66c160ed1a 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -33,6 +33,8 @@
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
+#include "BKE_scene.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -123,6 +125,11 @@ static int engine_support_display_space_shader(RenderEngine *UNUSED(engine), Sce
return IMB_colormanagement_support_glsl_draw(&scene->view_settings);
}
+static int engine_get_preview_pixel_size(RenderEngine *UNUSED(engine), Scene *scene)
+{
+ return BKE_render_preview_pixel_size(&scene->r);
+}
+
static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene)
{
IMB_colormanagement_setup_glsl_draw(&scene->view_settings,
@@ -279,8 +286,8 @@ static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &et->ext);
- BLI_freelinkN(&R_engines, et);
RNA_struct_free(&BLENDER_RNA, type);
+ BLI_freelinkN(&R_engines, et);
}
static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
@@ -647,6 +654,13 @@ static void rna_def_render_engine(BlenderRNA *brna)
parm = RNA_def_boolean(func, "supported", 0, "Supported", "");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "get_preview_pixel_size", "engine_get_preview_pixel_size");
+ RNA_def_function_ui_description(func, "Get the pixel size that should be used for preview rendering");
+ parm = RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_int(func, "pixel_size", 0, 1, 8, "Pixel Size", "", 1, 8);
+ RNA_def_function_return(func, parm);
+
RNA_define_verify_sdna(0);
prop = RNA_def_property(srna, "is_animation", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index abded187b33..b50ac7a61ef 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -983,21 +983,32 @@ static int rna_Function_use_self_type_get(PointerRNA *ptr)
/* Blender RNA */
+static int rna_struct_is_publc(CollectionPropertyIterator *UNUSED(iter), void *data)
+{
+ StructRNA *srna = data;
+
+ return !(srna->flag & STRUCT_PUBLIC_NAMESPACE);
+}
+
+
static void rna_BlenderRNA_structs_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- rna_iterator_listbase_begin(iter, &((BlenderRNA *)ptr->data)->structs, NULL);
+ BlenderRNA *brna = ptr->data;
+ rna_iterator_listbase_begin(iter, &brna->structs, rna_struct_is_publc);
}
/* optional, for faster lookups */
static int rna_BlenderRNA_structs_length(PointerRNA *ptr)
{
- return BLI_listbase_count(&((BlenderRNA *)ptr->data)->structs);
+ BlenderRNA *brna = ptr->data;
+ BLI_assert(brna->structs_len == BLI_listbase_count(&brna->structs));
+ return brna->structs_len;
}
static int rna_BlenderRNA_structs_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
{
- StructRNA *srna = BLI_findlink(&((BlenderRNA *)ptr->data)->structs, index);
-
- if (srna) {
+ BlenderRNA *brna = ptr->data;
+ StructRNA *srna = index < brna->structs_len ? BLI_findlink(&brna->structs, index) : NULL;
+ if (srna != NULL) {
RNA_pointer_create(NULL, &RNA_Struct, srna, r_ptr);
return true;
}
@@ -1007,12 +1018,11 @@ static int rna_BlenderRNA_structs_lookup_int(PointerRNA *ptr, int index, Pointer
}
static int rna_BlenderRNA_structs_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
{
- StructRNA *srna = ((BlenderRNA *)ptr->data)->structs.first;
- for (; srna; srna = srna->cont.next) {
- if (key[0] == srna->identifier[0] && STREQ(key, srna->identifier)) {
- RNA_pointer_create(NULL, &RNA_Struct, srna, r_ptr);
- return true;
- }
+ BlenderRNA *brna = ptr->data;
+ StructRNA *srna = BLI_ghash_lookup(brna->structs_map, (void *)key);
+ if (srna != NULL) {
+ RNA_pointer_create(NULL, &RNA_Struct, srna, r_ptr);
+ return true;
}
return false;
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 20c3ab89b8e..71350edeb94 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -94,13 +94,15 @@ EnumPropertyItem rna_enum_exr_codec_items[] = {
};
#endif
-EnumPropertyItem uv_sculpt_relaxation_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem uv_sculpt_relaxation_items[] = {
{UV_SCULPT_TOOL_RELAX_LAPLACIAN, "LAPLACIAN", 0, "Laplacian", "Use Laplacian method for relaxation"},
{UV_SCULPT_TOOL_RELAX_HC, "HC", 0, "HC", "Use HC method for relaxation"},
{0, NULL, 0, NULL, NULL}
};
+#endif
-EnumPropertyItem uv_sculpt_tool_items[] = {
+EnumPropertyItem rna_enum_uv_sculpt_tool_items[] = {
{UV_SCULPT_TOOL_PINCH, "PINCH", 0, "Pinch", "Pinch UVs"},
{UV_SCULPT_TOOL_RELAX, "RELAX", 0, "Relax", "Relax UVs"},
{UV_SCULPT_TOOL_GRAB, "GRAB", 0, "Grab", "Grab UVs"},
@@ -175,11 +177,13 @@ EnumPropertyItem rna_enum_snap_node_element_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem snap_uv_element_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem snap_uv_element_items[] = {
{SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"},
{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"},
{0, NULL, 0, NULL, NULL}
};
+#endif
EnumPropertyItem rna_enum_curve_fit_method_items[] = {
{CURVE_PAINT_FIT_METHOD_REFIT, "REFIT", 0, "Refit", "Incrementally re-fit the curve (high quality)"},
@@ -265,12 +269,14 @@ EnumPropertyItem rna_enum_curve_fit_method_items[] = {
R_IMF_ENUM_TIFF \
-EnumPropertyItem image_only_type_items[] = {
+#ifdef RNA_RUNTIME
+static EnumPropertyItem image_only_type_items[] = {
IMAGE_TYPE_ITEMS_IMAGE_ONLY
{0, NULL, 0, NULL, NULL}
};
+#endif
EnumPropertyItem rna_enum_image_type_items[] = {
{0, "", 0, N_("Image"), NULL},
@@ -408,7 +414,8 @@ EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
/* interpolation */
{0, "", 0, N_("Interpolation"), "Standard transitions between keyframes"},
{GP_IPO_LINEAR, "LINEAR", ICON_IPO_LINEAR, "Linear", "Straight-line interpolation between A and B (i.e. no ease in/out)"},
@@ -431,6 +438,7 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#endif
#ifdef RNA_RUNTIME
@@ -1838,6 +1846,13 @@ static void rna_Scene_simplify_update(Main *bmain, Scene *UNUSED(scene), Pointer
rna_Scene_use_simplify_update(bmain, sce, ptr);
}
+static void rna_SceneRenderData_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Scene *sce = ptr->id.data;
+
+ DAG_id_tag_update(&sce->id, 0);
+}
+
static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *sce = ptr->id.data;
@@ -2665,7 +2680,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "uv_sculpt_tool", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "uv_sculpt_tool");
- RNA_def_property_enum_items(prop, uv_sculpt_tool_items);
+ RNA_def_property_enum_items(prop, rna_enum_uv_sculpt_tool_items);
RNA_def_property_ui_text(prop, "UV Sculpt Tools", "Select Tools for the UV sculpt brushes");
prop = RNA_def_property(srna, "uv_relax_method", PROP_ENUM, PROP_NONE);
@@ -5887,6 +5902,15 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem pixel_size_items[] = {
+ {0, "AUTO", 0, "Automatic", "Automatic pixel size, depends on the UI scale"},
+ {1, "1", 0, "1x", "Render at full resolution"},
+ {2, "2", 0, "2x", "Render at 50% resolution"},
+ {4, "4", 0, "4x", "Render at 25% resolution"},
+ {8, "8", 0, "8x", "Render at 12.5% resolution"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
static EnumPropertyItem octree_resolution_items[] = {
{64, "64", 0, "64", ""},
{128, "128", 0, "128", ""},
@@ -6010,6 +6034,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
"progressively increasing it to the full viewport size");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ prop = RNA_def_property(srna, "preview_pixel_size", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "preview_pixel_size");
+ RNA_def_property_enum_items(prop, pixel_size_items);
+ RNA_def_property_ui_text(prop, "Pixel Size", "Pixel size for viewport rendering");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderData_update");
+
prop = RNA_def_property(srna, "pixel_aspect_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xasp");
RNA_def_property_flag(prop, PROP_PROPORTIONAL);
@@ -6242,8 +6272,8 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "blurfac");
RNA_def_property_ui_range(prop, 0.01f, 2.0f, 1, 2);
- RNA_def_property_ui_text(prop, "Shutter", "Time taken in frames between shutter open and close");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Shutter", "Time taken in frames between shutter open and close "
+ "(NOTE: Blender Internal does not support animated shutter)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "motion_blur_shutter_curve", PROP_POINTER, PROP_NONE);
@@ -6605,11 +6635,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
/* sequencer draw options */
- prop = RNA_def_property(srna, "use_sequencer_gl_preview", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_GL_PREV);
- RNA_def_property_ui_text(prop, "Sequencer OpenGL", "");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
-
#if 0 /* see R_SEQ_GL_REND comment */
prop = RNA_def_property(srna, "use_sequencer_gl_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_GL_REND);
@@ -6622,10 +6647,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sequencer Preview Shading", "Method to draw in the sequencer view");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
+#if 0 /* UNUSED, see R_SEQ_GL_REND comment */
prop = RNA_def_property(srna, "sequencer_gl_render", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "seq_rend_type");
RNA_def_property_enum_items(prop, rna_enum_viewport_shade_items);
+ /* XXX Label and tooltips are obviously wrong! */
RNA_def_property_ui_text(prop, "Sequencer Preview Shading", "Method to draw in the sequencer view");
+#endif
prop = RNA_def_property(srna, "use_sequencer_gl_textured_solid", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_SOLID_TEX);
@@ -6988,7 +7016,7 @@ static void rna_def_display_safe_areas(BlenderRNA *brna)
RNA_def_property_array(prop, 2);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_array_default(prop, default_title);
- RNA_def_property_ui_text(prop, "Title Safe margins", "Safe area for text and graphics");
+ RNA_def_property_ui_text(prop, "Title Safe Margins", "Safe area for text and graphics");
RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL);
prop = RNA_def_property(srna, "action", PROP_FLOAT, PROP_XYZ);
@@ -6999,7 +7027,6 @@ static void rna_def_display_safe_areas(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Action Safe Margins", "Safe area for general elements");
RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL);
-
prop = RNA_def_property(srna, "title_center", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "title_center");
RNA_def_property_array(prop, 2);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index a80e4c60127..16d91a4964b 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -164,7 +164,6 @@ static void rna_Scene_ray_cast(
bool ret = ED_transform_snap_object_project_ray_ex(
sctx,
- SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
},
@@ -280,8 +279,7 @@ static void rna_Scene_collada_export(
int include_shapekeys,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ int export_texture_type,
int use_texture_copies,
int triangulate,
int use_object_instantiation,
@@ -305,8 +303,7 @@ static void rna_Scene_collada_export(
deform_bones_only,
active_uv_only,
- include_uv_textures,
- include_material_textures,
+ export_texture_type,
use_texture_copies,
triangulate,
@@ -403,11 +400,8 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map");
- RNA_def_boolean(func, "include_uv_textures", false,
- "Include UV Textures", "Export textures assigned to the object UV Maps");
-
- RNA_def_boolean(func, "include_material_textures", false,
- "Include Material Textures", "Export textures assigned to the object Materials");
+ RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
+ "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
RNA_def_boolean(func, "use_texture_copies", true,
"Copy", "Copy textures to same folder where the .dae file is exported");
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 207ef182346..f775997b947 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -28,6 +28,7 @@
#include <stdlib.h>
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -75,13 +76,15 @@ EnumPropertyItem rna_enum_gpencil_sculpt_brush_items[] = {
{ 0, NULL, 0, NULL, NULL }
};
-EnumPropertyItem rna_enum_gpencil_lockaxis_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem rna_enum_gpencil_lockaxis_items[] = {
{ GP_LOCKAXIS_NONE, "GP_LOCKAXIS_NONE", 0, "None", "" },
{ GP_LOCKAXIS_X, "GP_LOCKAXIS_X", 0, "X", "Project strokes to plane locked to X" },
{ GP_LOCKAXIS_Y, "GP_LOCKAXIS_Y", 0, "Y", "Project strokes to plane locked to Y" },
{ GP_LOCKAXIS_Z, "GP_LOCKAXIS_Z", 0, "Z", "Project strokes to plane locked to Z" },
{ 0, NULL, 0, NULL, NULL }
};
+#endif
EnumPropertyItem rna_enum_symmetrize_direction_items[] = {
{BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""},
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 84b62721999..f628c5f14d9 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -341,7 +341,7 @@ static void rna_Sequence_use_translation_set(PointerRNA *ptr, int value)
}
}
else {
- seq->flag ^= SEQ_USE_TRANSFORM;
+ seq->flag &= ~SEQ_USE_TRANSFORM;
}
}
@@ -355,7 +355,7 @@ static void rna_Sequence_use_crop_set(PointerRNA *ptr, int value)
}
}
else {
- seq->flag ^= SEQ_USE_CROP;
+ seq->flag &= ~SEQ_USE_CROP;
}
}
@@ -1126,7 +1126,7 @@ static void rna_def_strip_crop(BlenderRNA *brna)
prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "bottom");
- RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the buttom");
+ RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the bottom");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
@@ -2338,7 +2338,7 @@ static void rna_def_text(StructRNA *srna)
prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "shadow_color");
- RNA_def_property_ui_text(prop, "Shadow Color", "Shadow color");
+ RNA_def_property_ui_text(prop, "Shadow Color", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index f2e856bf1ba..2fd471a66ef 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1045,6 +1045,8 @@ static void rna_SpaceProperties_pin_id_update(Main *UNUSED(bmain), Scene *UNUSED
case ID_LA:
WM_main_add_notifier(NC_LAMP, NULL);
break;
+ default:
+ break;
}
}
@@ -4605,7 +4607,7 @@ static void rna_def_space_clip(BlenderRNA *brna)
/* path length */
prop = RNA_def_property(srna, "path_length", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "path_length");
- RNA_def_property_range(prop, 0, 50);
+ RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop, "Path Length", "Length of displaying path, in frames");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 1e88585a286..4ad2832b953 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -267,6 +267,8 @@ void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
break;
}
+ default:
+ break;
}
}
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 54b82fc89d6..12af5dc8287 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -177,9 +177,9 @@ static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &pt->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
BLI_freelinkN(&art->paneltypes, pt);
- RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
@@ -229,6 +229,12 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat
break;
}
}
+ if (!RNA_struct_available_or_report(reports, dummypt.idname)) {
+ return NULL;
+ }
+ if (!RNA_struct_bl_idname_ok_or_report(reports, dummypt.idname, "_PT_")) {
+ return NULL;
+ }
/* create a new panel type */
pt = MEM_callocN(sizeof(PanelType), "python buttons panel");
@@ -455,11 +461,10 @@ static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &ult->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
WM_uilisttype_freelink(ult);
- RNA_struct_free(&BLENDER_RNA, type);
-
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
}
@@ -489,8 +494,15 @@ static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *da
/* check if we have registered this uilist type before, and remove it */
ult = WM_uilisttype_find(dummyult.idname, true);
- if (ult && ult->ext.srna)
+ if (ult && ult->ext.srna) {
rna_UIList_unregister(bmain, ult->ext.srna);
+ }
+ if (!RNA_struct_available_or_report(reports, dummyult.idname)) {
+ return NULL;
+ }
+ if (!RNA_struct_bl_idname_ok_or_report(reports, dummyult.idname, "_UL_")) {
+ return NULL;
+ }
/* create a new menu type */
ult = MEM_callocN(sizeof(uiListType) + over_alloc, "python uilist");
@@ -551,9 +563,9 @@ static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &ht->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
BLI_freelinkN(&art->headertypes, ht);
- RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
@@ -593,6 +605,12 @@ static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *da
break;
}
}
+ if (!RNA_struct_available_or_report(reports, dummyht.idname)) {
+ return NULL;
+ }
+ if (!RNA_struct_bl_idname_ok_or_report(reports, dummyht.idname, "_HT_")) {
+ return NULL;
+ }
/* create a new header type */
ht = MEM_callocN(sizeof(HeaderType), "python buttons header");
@@ -673,11 +691,10 @@ static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &mt->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
WM_menutype_freelink(mt);
- RNA_struct_free(&BLENDER_RNA, type);
-
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
}
@@ -714,8 +731,15 @@ static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data
/* check if we have registered this menu type before, and remove it */
mt = WM_menutype_find(dummymt.idname, true);
- if (mt && mt->ext.srna)
+ if (mt && mt->ext.srna) {
rna_Menu_unregister(bmain, mt->ext.srna);
+ }
+ if (!RNA_struct_available_or_report(reports, dummymt.idname)) {
+ return NULL;
+ }
+ if (!RNA_struct_bl_idname_ok_or_report(reports, dummymt.idname, "_MT_")) {
+ return NULL;
+ }
/* create a new menu type */
if (_menu_descr[0]) {
@@ -937,6 +961,7 @@ static void rna_def_panel(BlenderRNA *brna)
RNA_def_struct_refine_func(srna, "rna_Panel_refine");
RNA_def_struct_register_funcs(srna, "rna_Panel_register", "rna_Panel_unregister", NULL);
RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
/* poll */
func = RNA_def_function(srna, "poll", NULL);
@@ -1039,7 +1064,7 @@ static void rna_def_uilist(BlenderRNA *brna)
RNA_def_struct_refine_func(srna, "rna_UIList_refine");
RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL);
RNA_def_struct_idprops_func(srna, "rna_UIList_idprops");
- RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES);
+ RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_PUBLIC_NAMESPACE_INHERIT);
/* Registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
@@ -1161,6 +1186,7 @@ static void rna_def_header(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "Header");
RNA_def_struct_refine_func(srna, "rna_Header_refine");
RNA_def_struct_register_funcs(srna, "rna_Header_register", "rna_Header_unregister", NULL);
+ RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
/* draw */
func = RNA_def_function(srna, "draw", NULL);
@@ -1208,6 +1234,7 @@ static void rna_def_menu(BlenderRNA *brna)
RNA_def_struct_refine_func(srna, "rna_Menu_refine");
RNA_def_struct_register_funcs(srna, "rna_Menu_register", "rna_Menu_unregister", NULL);
RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
/* poll */
func = RNA_def_function(srna, "poll", NULL);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 46775af21db..7d8d24670a7 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -557,8 +557,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text");
parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item");
- parm = RNA_def_pointer(func, "properties", "OperatorProperties", "",
- "Operator properties to fill in, return when 'properties' is set to true");
+ parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", "Operator properties to fill in");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_function_return(func, parm);
RNA_def_function_ui_description(func, "Item. Places a button into the layout to call an Operator");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index d1e89ea18d0..358d790e555 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -606,9 +606,9 @@ static void rna_AddonPref_unregister(Main *UNUSED(bmain), StructRNA *type)
return;
RNA_struct_free_extension(type, &apt->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
BKE_addon_pref_type_remove(apt);
- RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
@@ -638,10 +638,8 @@ static StructRNA *rna_AddonPref_register(Main *bmain, ReportList *reports, void
/* check if we have registered this header type before, and remove it */
apt = BKE_addon_pref_type_find(dummyaddon.module, true);
- if (apt) {
- if (apt->ext.srna) {
- rna_AddonPref_unregister(bmain, apt->ext.srna);
- }
+ if (apt && apt->ext.srna) {
+ rna_AddonPref_unregister(bmain, apt->ext.srna);
}
/* create a new header type */
@@ -3304,6 +3302,13 @@ static void rna_def_userdef_view(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem line_width[] = {
+ {-1, "THIN", 0, "Thin", "Thinner lines than the default"},
+ { 0, "AUTO", 0, "Auto", "Automatic line width based on UI scale"},
+ { 1, "THICK", 0, "Thick", "Thicker lines than the default"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
PropertyRNA *prop;
StructRNA *srna;
@@ -3317,10 +3322,16 @@ static void rna_def_userdef_view(BlenderRNA *brna)
prop = RNA_def_property(srna, "ui_scale", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_ui_text(prop, "UI Scale", "Changes the size of the fonts and buttons in the interface");
RNA_def_property_range(prop, 0.25f, 4.0f);
- RNA_def_property_ui_range(prop, 0.5f, 2.0f, 1, 1);
+ RNA_def_property_ui_range(prop, 0.5f, 2.0f, 1, 2);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
+ prop = RNA_def_property(srna, "ui_line_width", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, line_width);
+ RNA_def_property_ui_text(prop, "UI Line Width",
+ "Changes the thickness of lines and points in the interface");
+ RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
+
/* display */
prop = RNA_def_property(srna, "show_tooltips", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TOOLTIPS);
@@ -3445,6 +3456,11 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cursor Depth",
"Use the depth under the mouse when placing the cursor");
+ prop = RNA_def_property(srna, "use_cursor_lock_adjust", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_LOCK_CURSOR_ADJUST);
+ RNA_def_property_ui_text(prop, "Cursor Lock Adjust",
+ "Place the cursor without 'jumping' to the new location (when lock-to-cursor is used)");
+
prop = RNA_def_property(srna, "use_camera_lock_parent", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_CAM_LOCK_NO_PARENT);
RNA_def_property_ui_text(prop, "Camera Parent Lock",
@@ -3926,12 +3942,18 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display");
+ RNA_def_property_ui_text(prop, "DPI",
+ "DPI for add-ons to use when drawing custom user interface elements, controlled by "
+ "operating system settings and Blender UI scale, with a reference value of 72 DPI "
+ "(note that since this value includes a user defined scale, it is not always the "
+ "actual monitor DPI)");
prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_sdna(prop, NULL, "pixelsize");
- RNA_def_property_ui_text(prop, "Pixel Size", "");
+ RNA_def_property_ui_text(prop, "Pixel Size",
+ "Suggested line thickness and point size in pixels, for add-ons drawing custom user "
+ "interface elements, controlled by operating system settings and Blender UI scale");
prop = RNA_def_property(srna, "font_path_ui", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, NULL, "font_path_ui");
@@ -3979,11 +4001,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Translate New Names", "Translate new data names (when adding/creating some)");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "use_textured_fonts", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_USETEXTUREFONT);
- RNA_def_property_ui_text(prop, "Textured Fonts", "Use textures for drawing international fonts");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
/* System & OpenGL */
prop = RNA_def_property(srna, "solid_lights", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index b458b2e69d5..df3eae4f221 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -32,6 +32,7 @@
#include "DNA_windowmanager_types.h"
#include "BLI_utildefines.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
@@ -939,35 +940,8 @@ static void rna_wmClipboard_set(PointerRNA *UNUSED(ptr), const char *value)
}
#ifdef WITH_PYTHON
-static void rna_Operator_unregister(struct Main *bmain, StructRNA *type)
-{
- const char *idname;
- wmOperatorType *ot = RNA_struct_blender_type_get(type);
- wmWindowManager *wm;
-
- if (!ot)
- return;
-
- /* update while blender is running */
- wm = bmain->wm.first;
- if (wm) {
- WM_operator_stack_clear(wm);
-
- WM_operator_handlers_clear(wm, ot);
- }
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
-
- RNA_struct_free_extension(type, &ot->ext);
-
- idname = ot->idname;
- WM_operatortype_remove_ptr(ot);
- MEM_freeN((void *)idname);
- /* not to be confused with the RNA_struct_free that WM_operatortype_remove calls, they are 2 different srna's */
- RNA_struct_free(&BLENDER_RNA, type);
-}
-
-static int operator_poll(bContext *C, wmOperatorType *ot)
+static int rna_operator_poll_cb(bContext *C, wmOperatorType *ot)
{
extern FunctionRNA rna_Operator_poll_func;
@@ -992,7 +966,7 @@ static int operator_poll(bContext *C, wmOperatorType *ot)
return visible;
}
-static int operator_execute(bContext *C, wmOperator *op)
+static int rna_operator_execute_cb(bContext *C, wmOperator *op)
{
extern FunctionRNA rna_Operator_execute_func;
@@ -1018,7 +992,7 @@ static int operator_execute(bContext *C, wmOperator *op)
}
/* same as execute() but no return value */
-static bool operator_check(bContext *C, wmOperator *op)
+static bool rna_operator_check_cb(bContext *C, wmOperator *op)
{
extern FunctionRNA rna_Operator_check_func;
@@ -1043,7 +1017,7 @@ static bool operator_check(bContext *C, wmOperator *op)
return result;
}
-static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int rna_operator_invoke_cb(bContext *C, wmOperator *op, const wmEvent *event)
{
extern FunctionRNA rna_Operator_invoke_func;
@@ -1070,7 +1044,7 @@ static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
/* same as invoke */
-static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event)
+static int rna_operator_modal_cb(bContext *C, wmOperator *op, const wmEvent *event)
{
extern FunctionRNA rna_Operator_modal_func;
@@ -1096,7 +1070,7 @@ static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event)
return result;
}
-static void operator_draw(bContext *C, wmOperator *op)
+static void rna_operator_draw_cb(bContext *C, wmOperator *op)
{
extern FunctionRNA rna_Operator_draw_func;
@@ -1115,7 +1089,7 @@ static void operator_draw(bContext *C, wmOperator *op)
}
/* same as exec(), but call cancel */
-static void operator_cancel(bContext *C, wmOperator *op)
+static void rna_operator_cancel_cb(bContext *C, wmOperator *op)
{
extern FunctionRNA rna_Operator_cancel_func;
@@ -1133,112 +1107,84 @@ static void operator_cancel(bContext *C, wmOperator *op)
RNA_parameter_list_free(&list);
}
-void operator_wrapper(wmOperatorType *ot, void *userdata);
-void macro_wrapper(wmOperatorType *ot, void *userdata);
+static void rna_Operator_unregister(struct Main *bmain, StructRNA *type);
+
+/* bpy_operator_wrap.c */
+extern void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata);
+extern void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata);
-static char _operator_idname[OP_MAX_TYPENAME];
-static char _operator_name[OP_MAX_TYPENAME];
-static char _operator_descr[RNA_DYN_DESCR_MAX];
-static char _operator_ctxt[RNA_DYN_DESCR_MAX];
-static char _operator_undo_group[OP_MAX_TYPENAME];
-static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_Operator_register(
+ Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
wmOperatorType dummyot = {NULL};
wmOperator dummyop = {NULL};
PointerRNA dummyotr;
int have_function[7];
+ struct {
+ char idname[OP_MAX_TYPENAME];
+ char name[OP_MAX_TYPENAME];
+ char description[RNA_DYN_DESCR_MAX];
+ char translation_context[RNA_DYN_DESCR_MAX];
+ char undo_group[OP_MAX_TYPENAME];
+ } temp_buffers;
+
/* setup dummy operator & operator type to store static properties in */
dummyop.type = &dummyot;
- dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */
- dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */
- dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */
- dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */
- dummyot.undo_group = _operator_undo_group; /* only assigne the pointer, string is NULL'd */
+ dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */
+ dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */
+ dummyot.description = temp_buffers.description; /* only assigne the pointer, string is NULL'd */
+ dummyot.translation_context = temp_buffers.translation_context; /* only assigne the pointer, string is NULL'd */
+ dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */
RNA_pointer_create(NULL, &RNA_Operator, &dummyop, &dummyotr);
/* clear in case they are left unset */
- _operator_idname[0] = _operator_name[0] = _operator_descr[0] = _operator_undo_group[0] = '\0';
+ temp_buffers.idname[0] = temp_buffers.name[0] = temp_buffers.description[0] = temp_buffers.undo_group[0] = '\0';
/* We have to set default op context! */
- strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ strcpy(temp_buffers.translation_context, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
/* validate the python class */
if (validate(&dummyotr, data, have_function) != 0)
return NULL;
- { /* convert foo.bar to FOO_OT_bar
- * allocate the description and the idname in 1 go */
-
- /* inconveniently long name sanity check */
- {
- char *ch = _operator_idname;
- int i;
- int dot = 0;
- for (i = 0; *ch; i++) {
- if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
- /* pass */
- }
- else if (*ch == '.') {
- dot++;
- }
- else {
- BKE_reportf(reports, RPT_ERROR,
- "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
- identifier, _operator_idname, i);
- return NULL;
- }
+ /* check if we have registered this operator type before, and remove it */
+ {
+ wmOperatorType *ot = WM_operatortype_find(dummyot.idname, true);
+ if (ot && ot->ext.srna)
+ rna_Operator_unregister(bmain, ot->ext.srna);
+ }
- ch++;
- }
+ if (!WM_operator_py_idname_ok_or_report(reports, identifier, dummyot.idname)) {
+ return NULL;
+ }
- if (i > ((int)sizeof(dummyop.idname)) - 3) {
- BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', "
- "is too long, maximum length is %d", identifier, _operator_idname,
- (int)sizeof(dummyop.idname) - 3);
- return NULL;
- }
+ char idname_conv[sizeof(dummyop.idname)];
+ WM_operator_bl_idname(idname_conv, dummyot.idname); /* convert the idname from python */
- if (dot != 1) {
- BKE_reportf(reports, RPT_ERROR,
- "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
- identifier, _operator_idname);
- return NULL;
- }
- }
- /* end sanity check */
-
- {
- int idlen = strlen(_operator_idname) + 4;
- int namelen = strlen(_operator_name) + 1;
- int desclen = strlen(_operator_descr) + 1;
- int ctxtlen = strlen(_operator_ctxt) + 1;
- int ugrouplen = strlen(_operator_undo_group) + 1;
- char *ch;
- /* 2 terminators and 3 to convert a.b -> A_OT_b */
- ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen + ugrouplen), "_operator_idname");
- WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
- dummyot.idname = ch;
- ch += idlen;
- strcpy(ch, _operator_name);
- dummyot.name = ch;
- ch += namelen;
- strcpy(ch, _operator_descr);
- dummyot.description = ch;
- ch += desclen;
- strcpy(ch, _operator_ctxt);
- dummyot.translation_context = ch;
- ch += ctxtlen;
- strcpy(ch, _operator_undo_group);
- dummyot.undo_group = ch;
- }
+ if (!RNA_struct_available_or_report(reports, idname_conv)) {
+ return NULL;
}
- /* check if we have registered this operator type before, and remove it */
+ /* Convert foo.bar to FOO_OT_bar
+ * allocate all strings at once. */
{
- wmOperatorType *ot = WM_operatortype_find(dummyot.idname, true);
- if (ot && ot->ext.srna)
- rna_Operator_unregister(bmain, ot->ext.srna);
+ const char *strings[] = {
+ idname_conv,
+ temp_buffers.name,
+ temp_buffers.description,
+ temp_buffers.translation_context,
+ temp_buffers.undo_group,
+ };
+ char *strings_table[ARRAY_SIZE(strings)];
+ BLI_string_join_array_by_sep_char_with_tableN('\0', strings_table, strings, ARRAY_SIZE(strings));
+
+ dummyot.idname = strings_table[0]; /* allocated string stored here */
+ dummyot.name = strings_table[1];
+ dummyot.description = strings_table[2];
+ dummyot.translation_context = strings_table[3];
+ dummyot.undo_group = strings_table[4];
+ BLI_assert(ARRAY_SIZE(strings) == 5);
}
/* XXX, this doubles up with the operator name [#29666]
@@ -1252,14 +1198,14 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
dummyot.ext.call = call;
dummyot.ext.free = free;
- dummyot.pyop_poll = (have_function[0]) ? operator_poll : NULL;
- dummyot.exec = (have_function[1]) ? operator_execute : NULL;
- dummyot.check = (have_function[2]) ? operator_check : NULL;
- dummyot.invoke = (have_function[3]) ? operator_invoke : NULL;
- dummyot.modal = (have_function[4]) ? operator_modal : NULL;
- dummyot.ui = (have_function[5]) ? operator_draw : NULL;
- dummyot.cancel = (have_function[6]) ? operator_cancel : NULL;
- WM_operatortype_append_ptr(operator_wrapper, (void *)&dummyot);
+ dummyot.pyop_poll = (have_function[0]) ? rna_operator_poll_cb : NULL;
+ dummyot.exec = (have_function[1]) ? rna_operator_execute_cb : NULL;
+ dummyot.check = (have_function[2]) ? rna_operator_check_cb : NULL;
+ dummyot.invoke = (have_function[3]) ? rna_operator_invoke_cb : NULL;
+ dummyot.modal = (have_function[4]) ? rna_operator_modal_cb : NULL;
+ dummyot.ui = (have_function[5]) ? rna_operator_draw_cb : NULL;
+ dummyot.cancel = (have_function[6]) ? rna_operator_cancel_cb : NULL;
+ WM_operatortype_append_ptr(BPY_RNA_operator_wrapper, (void *)&dummyot);
/* update while blender is running */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
@@ -1267,64 +1213,76 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
return dummyot.ext.srna;
}
+static void rna_Operator_unregister(struct Main *bmain, StructRNA *type)
+{
+ const char *idname;
+ wmOperatorType *ot = RNA_struct_blender_type_get(type);
+ wmWindowManager *wm;
+
+ if (!ot)
+ return;
+
+ /* update while blender is running */
+ wm = bmain->wm.first;
+ if (wm) {
+ WM_operator_stack_clear(wm);
+
+ WM_operator_handlers_clear(wm, ot);
+ }
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+
+ RNA_struct_free_extension(type, &ot->ext);
+
+ idname = ot->idname;
+ WM_operatortype_remove_ptr(ot);
+
+ /* not to be confused with the RNA_struct_free that WM_operatortype_remove calls, they are 2 different srna's */
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ MEM_freeN((void *)idname);
+}
+
static void **rna_Operator_instance(PointerRNA *ptr)
{
wmOperator *op = ptr->data;
return &op->py_instance;
}
-static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_MacroOperator_register(
+ Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
wmOperatorType dummyot = {NULL};
wmOperator dummyop = {NULL};
PointerRNA dummyotr;
int have_function[4];
+ struct {
+ char idname[OP_MAX_TYPENAME];
+ char name[OP_MAX_TYPENAME];
+ char description[RNA_DYN_DESCR_MAX];
+ char translation_context[RNA_DYN_DESCR_MAX];
+ char undo_group[OP_MAX_TYPENAME];
+ } temp_buffers;
+
/* setup dummy operator & operator type to store static properties in */
dummyop.type = &dummyot;
- dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */
- dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */
- dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */
- dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */
- dummyot.undo_group = _operator_undo_group; /* only assigne the pointer, string is NULL'd */
+ dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */
+ dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */
+ dummyot.description = temp_buffers.description; /* only assigne the pointer, string is NULL'd */
+ dummyot.translation_context = temp_buffers.translation_context; /* only assigne the pointer, string is NULL'd */
+ dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */
RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr);
/* clear in case they are left unset */
- _operator_idname[0] = _operator_name[0] = _operator_descr[0] = _operator_undo_group[0] = '\0';
+ temp_buffers.idname[0] = temp_buffers.name[0] = temp_buffers.description[0] = temp_buffers.undo_group[0] = '\0';
/* We have to set default op context! */
- strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ strcpy(temp_buffers.translation_context, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
/* validate the python class */
if (validate(&dummyotr, data, have_function) != 0)
return NULL;
- { /* convert foo.bar to FOO_OT_bar
- * allocate the description and the idname in 1 go */
- int idlen = strlen(_operator_idname) + 4;
- int namelen = strlen(_operator_name) + 1;
- int desclen = strlen(_operator_descr) + 1;
- int ctxtlen = strlen(_operator_ctxt) + 1;
- int ugrouplen = strlen(_operator_undo_group) + 1;
- char *ch;
- /* 2 terminators and 3 to convert a.b -> A_OT_b */
- ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen + ugrouplen), "_operator_idname");
- WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
- dummyot.idname = ch;
- ch += idlen;
- strcpy(ch, _operator_name);
- dummyot.name = ch;
- ch += namelen;
- strcpy(ch, _operator_descr);
- dummyot.description = ch;
- ch += desclen;
- strcpy(ch, _operator_ctxt);
- dummyot.translation_context = ch;
- ch += ctxtlen;
- strcpy(ch, _operator_undo_group);
- dummyot.undo_group = ch;
- }
-
if (strlen(identifier) >= sizeof(dummyop.idname)) {
BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s' is too long, maximum length is %d",
identifier, (int)sizeof(dummyop.idname));
@@ -1338,6 +1296,38 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
rna_Operator_unregister(bmain, ot->ext.srna);
}
+ if (!WM_operator_py_idname_ok_or_report(reports, identifier, dummyot.idname)) {
+ return NULL;
+ }
+
+ char idname_conv[sizeof(dummyop.idname)];
+ WM_operator_bl_idname(idname_conv, dummyot.idname); /* convert the idname from python */
+
+ if (!RNA_struct_available_or_report(reports, idname_conv)) {
+ return NULL;
+ }
+
+ /* Convert foo.bar to FOO_OT_bar
+ * allocate all strings at once. */
+ {
+ const char *strings[] = {
+ idname_conv,
+ temp_buffers.name,
+ temp_buffers.description,
+ temp_buffers.translation_context,
+ temp_buffers.undo_group,
+ };
+ char *strings_table[ARRAY_SIZE(strings)];
+ BLI_string_join_array_by_sep_char_with_tableN('\0', strings_table, strings, ARRAY_SIZE(strings));
+
+ dummyot.idname = strings_table[0]; /* allocated string stored here */
+ dummyot.name = strings_table[1];
+ dummyot.description = strings_table[2];
+ dummyot.translation_context = strings_table[3];
+ dummyot.undo_group = strings_table[4];
+ BLI_assert(ARRAY_SIZE(strings) == 5);
+ }
+
/* XXX, this doubles up with the operator name [#29666]
* for now just remove from dir(bpy.types) */
@@ -1348,10 +1338,10 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
dummyot.ext.call = call;
dummyot.ext.free = free;
- dummyot.pyop_poll = (have_function[0]) ? operator_poll : NULL;
- dummyot.ui = (have_function[3]) ? operator_draw : NULL;
+ dummyot.pyop_poll = (have_function[0]) ? rna_operator_poll_cb : NULL;
+ dummyot.ui = (have_function[3]) ? rna_operator_draw_cb : NULL;
- WM_operatortype_append_macro_ptr(macro_wrapper, (void *)&dummyot);
+ WM_operatortype_append_macro_ptr(BPY_RNA_operator_macro_wrapper, (void *)&dummyot);
/* update while blender is running */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
@@ -1471,6 +1461,7 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_struct_register_funcs(srna, "rna_Operator_register", "rna_Operator_unregister", "rna_Operator_instance");
#endif
RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1574,6 +1565,7 @@ static void rna_def_macro_operator(BlenderRNA *brna)
"rna_Operator_instance");
#endif
RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 2400dbcb898..f2f76f13883 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -64,13 +64,13 @@ static void initData(ModifierData *md)
static void copyData(ModifierData *md, ModifierData *target)
{
+#if 0
ArmatureModifierData *amd = (ArmatureModifierData *) md;
+#endif
ArmatureModifierData *tamd = (ArmatureModifierData *) target;
- tamd->object = amd->object;
- tamd->deformflag = amd->deformflag;
- tamd->multi = amd->multi;
- BLI_strncpy(tamd->defgrp_name, amd->defgrp_name, sizeof(tamd->defgrp_name));
+ modifier_copyData_generic(md, target);
+ tamd->prevCos = NULL;
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 2b739dc0093..874ac34b613 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -50,6 +50,7 @@
#include "BKE_curve.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
+#include "BKE_mesh.h"
#include "MOD_util.h"
@@ -137,7 +138,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
- struct Scene *scene,
+ struct Scene *UNUSED(scene),
Object *UNUSED(ob),
struct DepsNodeHandle *node)
{
@@ -149,33 +150,15 @@ static void updateDepsgraph(ModifierData *md,
DEG_add_object_relation(node, amd->end_cap, DEG_OB_COMP_TRANSFORM, "Array Modifier End Cap");
}
if (amd->curve_ob) {
+ struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node);
DEG_add_object_relation(node, amd->curve_ob, DEG_OB_COMP_GEOMETRY, "Array Modifier Curve");
- DEG_add_special_eval_flag(scene->depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH);
+ DEG_add_special_eval_flag(depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH);
}
if (amd->offset_ob != NULL) {
DEG_add_object_relation(node, amd->offset_ob, DEG_OB_COMP_TRANSFORM, "Array Modifier Offset");
}
}
-static float vertarray_size(const MVert *mvert, int numVerts, int axis)
-{
- int i;
- float min_co, max_co;
-
- /* if there are no vertices, width is 0 */
- if (numVerts == 0) return 0;
-
- /* find the minimum and maximum coordinates on the desired axis */
- min_co = max_co = mvert->co[axis];
- mvert++;
- for (i = 1; i < numVerts; ++i, ++mvert) {
- if (mvert->co[axis] < min_co) min_co = mvert->co[axis];
- if (mvert->co[axis] > max_co) max_co = mvert->co[axis];
- }
-
- return max_co - min_co;
-}
-
BLI_INLINE float sum_v3(const float v[3])
{
return v[0] + v[1] + v[2];
@@ -472,12 +455,22 @@ static DerivedMesh *arrayModifier_doArray(
unit_m4(offset);
src_mvert = dm->getVertArray(dm);
- if (amd->offset_type & MOD_ARR_OFF_CONST)
- add_v3_v3v3(offset[3], offset[3], amd->offset);
+ if (amd->offset_type & MOD_ARR_OFF_CONST) {
+ add_v3_v3(offset[3], amd->offset);
+ }
if (amd->offset_type & MOD_ARR_OFF_RELATIVE) {
- for (j = 0; j < 3; j++)
- offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j);
+ float min[3], max[3];
+ const MVert *src_mv;
+
+ INIT_MINMAX(min, max);
+ for (src_mv = src_mvert, j = chunk_nverts; j--; src_mv++) {
+ minmax_v3v3_v3(min, max, src_mv->co);
+ }
+
+ for (j = 3; j--; ) {
+ offset[3][j] += amd->scale[j] * (max[j] - min[j]);
+ }
}
if (use_offset_ob) {
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 5874029ae08..93dc0203f83 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -65,19 +65,11 @@ static void initData(ModifierData *md)
static void copyData(ModifierData *md, ModifierData *target)
{
+#if 0
BevelModifierData *bmd = (BevelModifierData *) md;
BevelModifierData *tbmd = (BevelModifierData *) target;
-
- tbmd->value = bmd->value;
- tbmd->res = bmd->res;
- tbmd->flags = bmd->flags;
- tbmd->val_flags = bmd->val_flags;
- tbmd->lim_flags = bmd->lim_flags;
- tbmd->e_flags = bmd->e_flags;
- tbmd->mat = bmd->mat;
- tbmd->profile = bmd->profile;
- tbmd->bevel_angle = bmd->bevel_angle;
- BLI_strncpy(tbmd->defgrp_name, bmd->defgrp_name, sizeof(tbmd->defgrp_name));
+#endif
+ modifier_copyData_generic(md, target);
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
index 061b1198f7e..49010664aa8 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.c
+++ b/source/blender/modifiers/intern/MOD_boolean_util.c
@@ -390,6 +390,9 @@ static void exporter_InitGeomArrays(ExportMeshData *export_data,
* the operand. Data for those layers will not be allocated or initialized.
*/
+ CustomData_merge(&dm_left->vertData, &dm->vertData, merge_mask, CD_DEFAULT, num_verts);
+ CustomData_merge(&dm_right->vertData, &dm->vertData, merge_mask, CD_DEFAULT, num_verts);
+
CustomData_merge(&dm_left->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
CustomData_merge(&dm_right->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index a364eef2974..56a274b9ac9 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -47,6 +47,8 @@
#include "BKE_particle.h"
#include "BKE_scene.h"
+
+
#ifdef _OPENMP
# include "BKE_mesh.h" /* BKE_MESH_OMP_LIMIT */
#endif
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index e7ff0a90fbc..74e49dda074 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -40,7 +40,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-
#include "BKE_collision.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
@@ -48,6 +47,8 @@
#include "BKE_pointcache.h"
#include "BKE_scene.h"
+#include "MOD_modifiertypes.h"
+
static void initData(ModifierData *md)
{
CollisionModifierData *collmd = (CollisionModifierData *) md;
@@ -152,8 +153,6 @@ static void deformVerts(ModifierData *md, Object *ob,
collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
collmd->mvert_num = mvert_num;
-
- DM_ensure_looptri(dm);
collmd->tri_num = dm->getNumLoopTri(dm);
{
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 09444476bfe..c9a910d769b 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -39,7 +39,6 @@
#include "BLI_utildefines.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
#include "BKE_library_query.h"
@@ -48,6 +47,7 @@
#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
+#include "MOD_modifiertypes.h"
static void initData(ModifierData *md)
{
@@ -111,7 +111,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
- struct Scene *scene,
+ struct Scene *UNUSED(scene),
Object *object,
struct DepsNodeHandle *node)
{
@@ -123,8 +123,9 @@ static void updateDepsgraph(ModifierData *md,
/* TODO(sergey): Currently path is evaluated as a part of modifier stack,
* might be changed in the future.
*/
+ struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node);
DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier");
- DEG_add_special_eval_flag(scene->depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH);
+ DEG_add_special_eval_flag(depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH);
}
DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Curve Modifier");
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 18f60bab490..fb8c0dd05a5 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -75,14 +75,10 @@ static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
DisplaceModifierData *dmd = (DisplaceModifierData *) md;
-#endif
DisplaceModifierData *tdmd = (DisplaceModifierData *) target;
+#endif
modifier_copyData_generic(md, target);
-
- if (tdmd->texture) {
- id_us_plus(&tdmd->texture->id);
- }
}
static void freeData(ModifierData *md)
@@ -384,6 +380,7 @@ static void displaceModifier_do(
data.vert_clnors = vert_clnors;
if (dmd->texture != NULL) {
data.pool = BKE_image_pool_new();
+ BKE_texture_fetch_images_for_pool(dmd->texture, data.pool);
}
BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512);
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index bb75d655802..eec97828091 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -36,12 +36,14 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_dynamicpaint.h"
+#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
+#include "MOD_modifiertypes.h"
static void initData(ModifierData *md)
{
@@ -58,6 +60,15 @@ static void copyData(ModifierData *md, ModifierData *target)
DynamicPaintModifierData *tpmd = (DynamicPaintModifierData *)target;
dynamicPaint_Modifier_copy(pmd, tpmd);
+
+ if (tpmd->canvas) {
+ for (DynamicPaintSurface *surface = tpmd->canvas->surfaces.first; surface; surface = surface->next) {
+ id_us_plus((ID *)surface->init_texture);
+ }
+ }
+ if (tpmd->brush) {
+ id_us_plus((ID *)tpmd->brush->mat);
+ }
}
static void freeData(ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index 4441edb299b..a17870f2bf4 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -48,6 +48,7 @@
#include "DNA_object_types.h"
+#include "MOD_modifiertypes.h"
static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd)
{
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index ca7b3ce8039..72bc046b440 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -51,9 +51,9 @@
#include "BKE_particle.h"
#include "BKE_scene.h"
-
#include "MEM_guardedalloc.h"
+#include "MOD_modifiertypes.h"
static void initData(ModifierData *md)
{
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index c202c5e1cb4..53f955b15f0 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -47,6 +47,8 @@
#include "DEG_depsgraph_build.h"
#include "MOD_fluidsim_util.h"
+#include "MOD_modifiertypes.h"
+
#include "MEM_guardedalloc.h"
/* Fluidsim */
@@ -68,12 +70,13 @@ static void copyData(ModifierData *md, ModifierData *target)
FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
FluidsimModifierData *tfluidmd = (FluidsimModifierData *) target;
- if (tfluidmd->fss)
- MEM_freeN(tfluidmd->fss);
-
- tfluidmd->fss = MEM_dupallocN(fluidmd->fss);
- if (tfluidmd->fss && (tfluidmd->fss->meshVelocities != NULL)) {
- tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities);
+ fluidsim_free(tfluidmd);
+
+ if (fluidmd->fss) {
+ tfluidmd->fss = MEM_dupallocN(fluidmd->fss);
+ if (tfluidmd->fss && (tfluidmd->fss->meshVelocities != NULL)) {
+ tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities);
+ }
}
}
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c
index 2ecf06057db..3684e947fe0 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim_util.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c
@@ -150,9 +150,8 @@ void fluidsim_free(FluidsimModifierData *fluidmd)
if (fluidmd && fluidmd->fss) {
if (fluidmd->fss->meshVelocities) {
MEM_freeN(fluidmd->fss->meshVelocities);
- fluidmd->fss->meshVelocities = NULL;
}
- MEM_freeN(fluidmd->fss);
+ MEM_SAFE_FREE(fluidmd->fss);
}
return;
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index ce3fdc4bbe8..153670d327c 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -539,7 +539,7 @@ static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh
STACK_PUSH(index_anchors, i);
}
}
- DM_ensure_looptri(dm);
+
total_anchors = STACK_SIZE(index_anchors);
lmd->cache_system = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumLoopTri(dm),
total_anchors, lmd->anchor_grp_name, lmd->repeat);
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index dcc7fe4d4f1..18caf4a39f4 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -53,6 +53,8 @@
#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
+#include "MOD_modifiertypes.h"
+
#include "BLI_strict_flags.h"
static void copyData(ModifierData *md, ModifierData *target)
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
index 8360c8ffda7..4b2b3f17d18 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
@@ -146,7 +146,7 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
return false;
}
- if (fseek(fp, sizeof(float) * 3 * index * pc2_head.verts_tot , SEEK_CUR) != 0) {
+ if (fseek(fp, sizeof(float) * 3 * index * pc2_head.verts_tot, SEEK_CUR) != 0) {
*err_str = "Failed to seek frame";
return false;
}
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 406ce398ee0..b1938395a7b 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -83,7 +83,7 @@ static void copyData(ModifierData *md, ModifierData *target)
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
MeshDeformModifierData *tmmd = (MeshDeformModifierData *) target;
- *tmmd = *mmd;
+ modifier_copyData_generic(md, target);
if (mmd->bindinfluences) tmmd->bindinfluences = MEM_dupallocN(mmd->bindinfluences);
if (mmd->bindoffsets) tmmd->bindoffsets = MEM_dupallocN(mmd->bindoffsets);
@@ -91,8 +91,8 @@ static void copyData(ModifierData *md, ModifierData *target)
if (mmd->dyngrid) tmmd->dyngrid = MEM_dupallocN(mmd->dyngrid);
if (mmd->dyninfluences) tmmd->dyninfluences = MEM_dupallocN(mmd->dyninfluences);
if (mmd->dynverts) tmmd->dynverts = MEM_dupallocN(mmd->dynverts);
- if (mmd->bindweights) tmmd->dynverts = MEM_dupallocN(mmd->bindweights); /* deprecated */
- if (mmd->bindcos) tmmd->dynverts = MEM_dupallocN(mmd->bindcos); /* deprecated */
+ if (mmd->bindweights) tmmd->bindweights = MEM_dupallocN(mmd->bindweights); /* deprecated */
+ if (mmd->bindcos) tmmd->bindcos = MEM_dupallocN(mmd->bindcos); /* deprecated */
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index f0edcc31a10..5b059ef89d2 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -25,12 +25,14 @@
*/
#include "DNA_cachefile_types.h"
+#include "DNA_mesh_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_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -95,11 +97,15 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *dm,
- ModifierApplyFlag flag)
+ ModifierApplyFlag UNUSED(flag))
{
#ifdef WITH_ALEMBIC
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md;
+ /* Only used to check whether we are operating on org data or not... */
+ Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
+ DerivedMesh *org_dm = dm;
+
Scene *scene = md->scene;
const float frame = BKE_scene_frame_get(scene);
const float time = BKE_cachefile_time_offset(mcmd->cache_file, frame, FPS);
@@ -121,6 +127,16 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
}
+ if (me != NULL) {
+ MVert *mvert = dm->getVertArray(dm);
+ MEdge *medge = dm->getEdgeArray(dm);
+ MPoly *mpoly = dm->getPolyArray(dm);
+ if ((me->mvert == mvert) || (me->medge == medge) || (me->mpoly == mpoly)) {
+ /* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */
+ dm = CDDM_copy(dm);
+ }
+ }
+
DerivedMesh *result = ABC_read_mesh(mcmd->reader,
ob,
dm,
@@ -132,11 +148,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
modifier_setError(md, "%s", err_str);
}
+ if (!ELEM(result, NULL, dm) && (dm != org_dm)) {
+ dm->release(dm);
+ dm = org_dm;
+ }
+
return result ? result : dm;
- UNUSED_VARS(flag);
#else
return dm;
- UNUSED_VARS(md, ob, flag);
+ UNUSED_VARS(md, ob);
#endif
}
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 9705edc580c..7b71e616627 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -48,6 +48,8 @@
#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
+#include "MOD_modifiertypes.h"
+
static void initData(ModifierData *md)
{
MirrorModifierData *mmd = (MirrorModifierData *) md;
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index 90ad1bdfdc2..f9f17b88fa4 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -46,6 +46,8 @@
#include "BKE_modifier.h"
#include "BKE_subsurf.h"
+#include "MOD_modifiertypes.h"
+
static void initData(ModifierData *md)
{
MultiresModifierData *mmd = (MultiresModifierData *)md;
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index e77cc655c16..8d8565e7e62 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -44,6 +44,8 @@
#include "BKE_modifier.h"
#include "BKE_ocean.h"
+#include "MOD_modifiertypes.h"
+
#ifdef WITH_OCEANSIM
static void init_cache_data(Object *ob, struct OceanModifierData *omd)
{
@@ -160,40 +162,19 @@ static void freeData(ModifierData *md)
static void copyData(ModifierData *md, ModifierData *target)
{
#ifdef WITH_OCEANSIM
+#if 0
OceanModifierData *omd = (OceanModifierData *) md;
+#endif
OceanModifierData *tomd = (OceanModifierData *) target;
- tomd->geometry_mode = omd->geometry_mode;
- tomd->resolution = omd->resolution;
- tomd->spatial_size = omd->spatial_size;
-
- tomd->wind_velocity = omd->wind_velocity;
+ freeData(target);
- tomd->damp = omd->damp;
- tomd->smallest_wave = omd->smallest_wave;
- tomd->depth = omd->depth;
-
- tomd->wave_alignment = omd->wave_alignment;
- tomd->wave_direction = omd->wave_direction;
- tomd->wave_scale = omd->wave_scale;
-
- tomd->chop_amount = omd->chop_amount;
- tomd->foam_coverage = omd->foam_coverage;
- tomd->time = omd->time;
-
- tomd->seed = omd->seed;
- tomd->flag = omd->flag;
+ modifier_copyData_generic(md, target);
tomd->refresh = 0;
- tomd->size = omd->size;
- tomd->repeat_x = omd->repeat_x;
- tomd->repeat_y = omd->repeat_y;
-
/* XXX todo: copy cache runtime too */
tomd->cached = 0;
- tomd->bakestart = omd->bakestart;
- tomd->bakeend = omd->bakeend;
tomd->oceancache = NULL;
tomd->ocean = BKE_ocean_add();
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index fbf5a958254..0c91cb08da7 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -54,6 +54,8 @@
#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
+#include "MOD_modifiertypes.h"
+
static void initData(ModifierData *md)
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 87859cd240a..2c3d7f394bb 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -112,6 +112,56 @@ static void screwvert_iter_step(ScrewVertIter *iter)
}
}
+static DerivedMesh *dm_remove_doubles_on_axis(
+ DerivedMesh *result, MVert *mvert_new, const uint totvert, const uint step_tot,
+ const float axis_vec[3], const float axis_offset[3], const float merge_threshold)
+{
+ const float merge_threshold_sq = SQUARE(merge_threshold);
+ const bool use_offset = axis_offset != NULL;
+ uint tot_doubles = 0;
+ for (uint i = 0; i < totvert; i += 1) {
+ float axis_co[3];
+ if (use_offset) {
+ float offset_co[3];
+ sub_v3_v3v3(offset_co, mvert_new[i].co, axis_offset);
+ project_v3_v3v3_normalized(axis_co, offset_co, axis_vec);
+ add_v3_v3(axis_co, axis_offset);
+ }
+ else {
+ project_v3_v3v3_normalized(axis_co, mvert_new[i].co, axis_vec);
+ }
+ const float dist_sq = len_squared_v3v3(axis_co, mvert_new[i].co);
+ if (dist_sq <= merge_threshold_sq) {
+ mvert_new[i].flag |= ME_VERT_TMP_TAG;
+ tot_doubles += 1;
+ copy_v3_v3(mvert_new[i].co, axis_co);
+ }
+ }
+
+ if (tot_doubles != 0) {
+ uint tot = totvert * step_tot;
+ int *full_doubles_map = MEM_mallocN(sizeof(int) * tot, __func__);
+ copy_vn_i(full_doubles_map, (int)tot, -1);
+
+ uint tot_doubles_left = tot_doubles;
+ for (uint i = 0; i < totvert; i += 1) {
+ if (mvert_new[i].flag & ME_VERT_TMP_TAG) {
+ int *doubles_map = &full_doubles_map[totvert + i] ;
+ for (uint step = 1; step < step_tot; step += 1) {
+ *doubles_map = (int)i;
+ doubles_map += totvert;
+ }
+ tot_doubles_left -= 1;
+ if (tot_doubles_left == 0) {
+ break;
+ }
+ }
+ }
+ result = CDDM_merge_verts(result, full_doubles_map, (int)(tot_doubles * (step_tot - 1)), CDDM_MERGE_VERTS_DUMP_IF_MAPPED);
+ MEM_freeN(full_doubles_map);
+ }
+ return result;
+}
static void initData(ModifierData *md)
{
@@ -123,6 +173,7 @@ static void initData(ModifierData *md)
ltmd->steps = 16;
ltmd->render_steps = 16;
ltmd->iter = 1;
+ ltmd->merge_dist = 0.01f;
}
static void copyData(ModifierData *md, ModifierData *target)
@@ -1050,6 +1101,16 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
MEM_freeN(vert_loop_map);
}
+ if ((ltmd->flag & MOD_SCREW_MERGE) && (screw_ofs == 0.0f)) {
+ DerivedMesh *result_prev = result;
+ result = dm_remove_doubles_on_axis(
+ result, mvert_new, totvert, step_tot,
+ axis_vec, ltmd->ob_axis ? mtx_tx[3] : NULL, ltmd->merge_dist);
+ if (result != result_prev) {
+ result->dirty |= DM_DIRTY_NORMALS;
+ }
+ }
+
if ((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) {
result->dirty |= DM_DIRTY_NORMALS;
}
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 8ed623734be..ad1e4badd3e 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -77,6 +77,8 @@
#include "BKE_mesh_mapping.h"
#include "BKE_modifier.h"
+#include "MOD_modifiertypes.h"
+
#include "bmesh.h"
typedef struct {
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index c105a3ab3a7..7f2d9e42fe6 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -45,7 +45,6 @@
#include "BLI_utildefines.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -56,6 +55,8 @@
#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
+#include "MOD_modifiertypes.h"
+
static void initData(ModifierData *md)
{
SmokeModifierData *smd = (SmokeModifierData *) md;
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 79e3eb5f3df..b692137b604 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -138,7 +138,9 @@ static void copyData(ModifierData *md, ModifierData *target)
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target;
- *tsmd = *smd;
+ freeData(target);
+
+ modifier_copyData_generic(md, target);
if (smd->verts) {
tsmd->verts = MEM_dupallocN(smd->verts);
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index 6fad2756f82..b057d6d5a86 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -35,6 +35,8 @@
#include "bmesh.h"
#include "bmesh_tools.h"
+#include "MOD_modifiertypes.h"
+
static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int quad_method, const int ngon_method)
{
DerivedMesh *result;
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 78dc1ea8bcb..01468c1143a 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -45,6 +45,7 @@
#include "BKE_camera.h"
+#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_DerivedMesh.h"
@@ -70,9 +71,12 @@ static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
UVProjectModifierData *umd = (UVProjectModifierData *) md;
- UVProjectModifierData *tumd = (UVProjectModifierData *) target;
#endif
+ UVProjectModifierData *tumd = (UVProjectModifierData *) target;
+
modifier_copyData_generic(md, target);
+
+ id_us_plus((ID *)tumd->image);
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index f0c4940816e..b4990c5250e 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -90,14 +90,10 @@ static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
WaveModifierData *wmd = (WaveModifierData *) md;
-#endif
WaveModifierData *twmd = (WaveModifierData *) target;
+#endif
modifier_copyData_generic(md, target);
-
- if (twmd->texture) {
- id_us_plus(&twmd->texture->id);
- }
}
static bool dependsOnTime(ModifierData *UNUSED(md))
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index cd30b54350c..13a97c1c13d 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -50,7 +50,9 @@
#include "DEG_depsgraph_build.h"
#include "MEM_guardedalloc.h"
+
#include "MOD_weightvg_util.h"
+#include "MOD_modifiertypes.h"
/**************************************
* Modifiers functions. *
@@ -91,10 +93,6 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
twmd->cmap_curve = curvemapping_copy(wmd->cmap_curve);
-
- if (twmd->mask_texture) {
- id_us_plus(&twmd->mask_texture->id);
- }
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 1b3188c83b3..392f42040b0 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -47,7 +47,9 @@
#include "DEG_depsgraph_build.h"
#include "MEM_guardedalloc.h"
+
#include "MOD_weightvg_util.h"
+#include "MOD_modifiertypes.h"
/**
@@ -136,14 +138,10 @@ static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
-#endif
WeightVGMixModifierData *twmd = (WeightVGMixModifierData *) target;
+#endif
modifier_copyData_generic(md, target);
-
- if (twmd->mask_texture) {
- id_us_plus(&twmd->mask_texture->id);
- }
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 2c87838aeab..2ca380ba5c2 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -51,7 +51,9 @@
#include "DEG_depsgraph_build.h"
#include "MEM_guardedalloc.h"
+
#include "MOD_weightvg_util.h"
+#include "MOD_modifiertypes.h"
//#define USE_TIMEIT
@@ -286,14 +288,10 @@ static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
-#endif
WeightVGProximityModifierData *twmd = (WeightVGProximityModifierData *) target;
+#endif
modifier_copyData_generic(md, target);
-
- if (twmd->mask_texture) {
- id_us_plus(&twmd->mask_texture->id);
- }
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index e958ab9a3dc..a95c3233132 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -116,6 +116,10 @@ static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node,
}
else {
sock = BLI_findlink(&node->outputs, sock_index);
+ NodeImageLayer *sockdata = sock->storage;
+ if (sockdata) {
+ BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name));
+ }
}
BLI_linklist_append(available_sockets, sock);
@@ -158,14 +162,11 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node, LinkNod
else
type = SOCK_RGBA;
+ cmp_node_image_add_pass_output(ntree, node, rpass->name, rpass->name, -1, type, false, available_sockets, &prev_index);
/* Special handling for the Combined pass to ensure compatibility. */
if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
- cmp_node_image_add_pass_output(ntree, node, "Image", rpass->name, -1, type, false, available_sockets, &prev_index);
cmp_node_image_add_pass_output(ntree, node, "Alpha", rpass->name, -1, SOCK_FLOAT, false, available_sockets, &prev_index);
}
- else {
- cmp_node_image_add_pass_output(ntree, node, rpass->name, rpass->name, -1, type, false, available_sockets, &prev_index);
- }
}
BKE_image_release_ibuf(ima, ibuf, NULL);
return;
@@ -173,12 +174,12 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node, LinkNod
}
}
- cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, false, available_sockets, &prev_index);
- cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, false, available_sockets, &prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, -1, SOCK_RGBA, false, available_sockets, &prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, -1, SOCK_FLOAT, false, available_sockets, &prev_index);
if (ima) {
if (!ima->rr) {
- cmp_node_image_add_pass_output(ntree, node, RE_PASSNAME_Z, RE_PASSNAME_Z, RRES_OUT_Z, SOCK_FLOAT, false, available_sockets, &prev_index);
+ cmp_node_image_add_pass_output(ntree, node, RE_PASSNAME_Z, RE_PASSNAME_Z, -1, SOCK_FLOAT, false, available_sockets, &prev_index);
}
BKE_image_release_ibuf(ima, ibuf, NULL);
}
@@ -276,7 +277,7 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rl
for (link = ntree->links.first; link; link = link->next) {
if (link->fromsock == sock) break;
}
- if (!link && sock_index > 30) {
+ if (!link && (!rlayer || sock_index > 30)) {
MEM_freeN(sock->storage);
nodeRemoveSocket(ntree, node, sock);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c
index d805cf4d87f..e0d9fa33f13 100644
--- a/source/blender/nodes/composite/nodes/node_composite_switchview.c
+++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c
@@ -137,7 +137,6 @@ static void init_switch_view(const bContext *C, PointerRNA *ptr)
cmp_node_switch_view_sanitycheck(ntree, node);
}
-/* custom1 = mix type */
void register_node_type_cmp_switch_view(void)
{
static bNodeType ntype;
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 2347564c696..0cf131adbdc 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -78,7 +78,8 @@ void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack
static void node_init_input_index(bNodeSocket *sock, int *index)
{
- if (sock->link && sock->link->fromsock) {
+ /* Only consider existing link if from socket is valid! */
+ if (sock->link && sock->link->fromsock && sock->link->fromsock->stack_index >= 0) {
sock->stack_index = sock->link->fromsock->stack_index;
}
else {
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 9bd43f331fb..5bc97f13b41 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -142,28 +142,40 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
{
memset(gs, 0, sizeof(*gs));
- nodestack_get_vec(gs->vec, type, ns);
- gs->link = ns->data;
-
- if (type == SOCK_FLOAT)
- gs->type = GPU_FLOAT;
- else if (type == SOCK_VECTOR)
- gs->type = GPU_VEC3;
- else if (type == SOCK_RGBA)
- gs->type = GPU_VEC4;
- else if (type == SOCK_SHADER)
- gs->type = GPU_VEC4;
- else
+ if (ns == NULL) {
+ /* node_get_stack() will generate NULL bNodeStack pointers for unknown/unsuported types of sockets... */
+ zero_v4(gs->vec);
+ gs->link = NULL;
gs->type = GPU_NONE;
+ gs->name = "";
+ gs->hasinput = false;
+ gs->hasoutput = false;
+ gs->sockettype = type;
+ }
+ else {
+ nodestack_get_vec(gs->vec, type, ns);
+ gs->link = ns->data;
- gs->name = "";
- gs->hasinput = ns->hasinput && ns->data;
- /* XXX Commented out the ns->data check here, as it seems it's not always set,
- * even though there *is* a valid connection/output... But that might need
- * further investigation.
- */
- gs->hasoutput = ns->hasoutput /*&& ns->data*/;
- gs->sockettype = ns->sockettype;
+ if (type == SOCK_FLOAT)
+ gs->type = GPU_FLOAT;
+ else if (type == SOCK_VECTOR)
+ gs->type = GPU_VEC3;
+ else if (type == SOCK_RGBA)
+ gs->type = GPU_VEC4;
+ else if (type == SOCK_SHADER)
+ gs->type = GPU_VEC4;
+ else
+ gs->type = GPU_NONE;
+
+ gs->name = "";
+ gs->hasinput = ns->hasinput && ns->data;
+ /* XXX Commented out the ns->data check here, as it seems it's not always set,
+ * even though there *is* a valid connection/output... But that might need
+ * further investigation.
+ */
+ gs->hasoutput = ns->hasoutput /*&& ns->data*/;
+ gs->sockettype = ns->sockettype;
+ }
}
void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs)
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
index 44288db182a..e0330d110ca 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_bsdf_principled_in[] = {
{ SOCK_FLOAT, 1, N_("Sheen"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Sheen Tint"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Clearcoat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
- { SOCK_FLOAT, 1, N_("Clearcoat Gloss"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Clearcoat Roughness"), 0.03f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
{ SOCK_FLOAT, 1, N_("Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Transmission Roughness"),0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
index 5a9e33a4053..8262b70fc44 100644
--- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c
+++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
@@ -51,14 +51,23 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeE
return GPU_stack_link(mat, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
-static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
ShadeInput *shi = ((ShaderCallData *)data)->shi;
- float eta = max_ff(in[0]->vec[0], 0.00001);
+
+ /* Compute IOR. */
+ float eta;
+ nodestack_get_vec(&eta, SOCK_FLOAT, in[0]);
+ eta = max_ff(eta, 0.00001);
+ eta = shi->flippednor ? 1 / eta : eta;
+
+ /* Get normal from socket, but only if linked. */
+ bNodeSocket *sock_normal = node->inputs.first;
+ sock_normal = sock_normal->next;
float n[3];
- if (in[1]->hasinput) {
- copy_v3_v3(n, in[1]->vec);
+ if (sock_normal->link) {
+ nodestack_get_vec(n, SOCK_VECTOR, in[1]);
}
else {
copy_v3_v3(n, shi->vn);
@@ -68,7 +77,7 @@ static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUS
mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n);
}
- out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? 1 / eta : eta);
+ out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, eta);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
index a0b2408a7bb..998e1a5687e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
+++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
@@ -52,24 +52,33 @@ static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *UNUSED(node), b
return GPU_stack_link(mat, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
-static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
ShadeInput *shi = ((ShaderCallData *)data)->shi;
- float blend = in[0]->vec[0];
+
+ /* Compute IOR. */
+ float blend;
+ nodestack_get_vec(&blend, SOCK_FLOAT, in[0]);
float eta = max_ff(1 - blend, 0.00001);
+ eta = shi->flippednor ? eta : 1 / eta;
+
+ /* Get normal from socket, but only if linked. */
+ bNodeSocket *sock_normal = node->inputs.first;
+ sock_normal = sock_normal->next;
float n[3];
- if (in[1]->hasinput) {
- copy_v3_v3(n, in[1]->vec);
+ if (sock_normal->link) {
+ nodestack_get_vec(n, SOCK_VECTOR, in[1]);
}
else {
copy_v3_v3(n, shi->vn);
}
+
if (shi->use_world_space_shading)
mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n);
- out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? eta : 1 / eta);
+ out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, eta);
float facing = fabs(dot_v3v3(shi->view, n));
if (blend != 0.5) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index e0bf34f42e4..36d7522e3e6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -46,8 +46,10 @@ static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = attr;
}
-static void node_shader_exec_normal_map(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
- {
+static void node_shader_exec_normal_map(
+ void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata),
+ bNodeStack **in, bNodeStack **out)
+{
if (data) {
ShadeInput *shi = ((ShaderCallData *)data)->shi;
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index 8f287918a4a..6598d402f72 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -44,6 +44,7 @@
#include "bmesh_py_types.h"
#include "../generic/python_utildefines.h"
+#include "../generic/py_capi_utils.h"
static int bpy_bm_op_as_py_error(BMesh *bm)
{
@@ -152,11 +153,9 @@ static int bpy_slot_from_py(
switch (slot->slot_type) {
case BMO_OP_SLOT_BOOL:
{
- int param;
+ const int param = PyC_Long_AsBool(value);
- param = PyLong_AsLong(value);
-
- if (param < 0) {
+ if (param == -1) {
PyErr_Format(PyExc_TypeError,
"%.200s: keyword \"%.200s\" expected True/False or 0/1, not %.200s",
opname, slot_name, Py_TYPE(value)->tp_name);
@@ -170,23 +169,16 @@ static int bpy_slot_from_py(
}
case BMO_OP_SLOT_INT:
{
- int overflow;
- long param = PyLong_AsLongAndOverflow(value, &overflow);
- if (overflow || (param > INT_MAX) || (param < INT_MIN)) {
- PyErr_Format(PyExc_ValueError,
- "%.200s: keyword \"%.200s\" value not in 'int' range "
- "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")",
- opname, slot_name, Py_TYPE(value)->tp_name);
- return -1;
- }
- else if (param == -1 && PyErr_Occurred()) {
+ const int param = PyC_Long_AsI32(value);
+
+ if (param == -1 && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"%.200s: keyword \"%.200s\" expected an int, not %.200s",
opname, slot_name, Py_TYPE(value)->tp_name);
return -1;
}
else {
- BMO_SLOT_AS_INT(slot) = (int)param;
+ BMO_SLOT_AS_INT(slot) = param;
}
break;
}
@@ -208,26 +200,19 @@ static int bpy_slot_from_py(
{
/* XXX - BMesh operator design is crappy here, operator slot should define matrix size,
* not the caller! */
- unsigned short size;
- if (!MatrixObject_Check(value)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s: keyword \"%.200s\" expected a Matrix, not %.200s",
- opname, slot_name, Py_TYPE(value)->tp_name);
+ MatrixObject *pymat;
+ if (!Matrix_ParseAny(value, &pymat)) {
return -1;
}
- else if (BaseMath_ReadCallback((MatrixObject *)value) == -1) {
- return -1;
- }
- else if (((size = ((MatrixObject *)value)->num_col) != ((MatrixObject *)value)->num_row) ||
- (ELEM(size, 3, 4) == false))
- {
+ const ushort size = pymat->num_col;
+ if ((size != pymat->num_row) || (!ELEM(size, 3, 4))) {
PyErr_Format(PyExc_TypeError,
"%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix Matrix",
opname, slot_name);
return -1;
}
- BMO_slot_mat_set(bmop, bmop->slots_in, slot_name, ((MatrixObject *)value)->matrix, size);
+ BMO_slot_mat_set(bmop, bmop->slots_in, slot_name, pymat->matrix, size);
break;
}
case BMO_OP_SLOT_VEC:
@@ -436,7 +421,7 @@ static int bpy_slot_from_py(
return -1; /* error is set in bpy_slot_from_py_elem_check() */
}
- value_i = PyLong_AsLong(arg_value);
+ value_i = PyC_Long_AsI32(arg_value);
if (value_i == -1 && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
@@ -466,7 +451,7 @@ static int bpy_slot_from_py(
return -1; /* error is set in bpy_slot_from_py_elem_check() */
}
- value_i = PyLong_AsLong(arg_value);
+ value_i = PyC_Long_AsI32(arg_value);
if (value_i == -1 && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index b20c03bee28..52ca475297d 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -124,25 +124,19 @@ static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
BPY_BM_CHECK_INT(self);
- param = PyLong_AsLong(value);
-
- if ((unsigned int)param <= 1) {
- if (hflag == BM_ELEM_SELECT)
- BM_elem_select_set(self->bm, self->ele, param);
- else
- BM_elem_flag_set(self->ele, hflag, param);
+ if ((param = PyC_Long_AsBool(value)) == -1) {
+ return -1;
+ }
- return 0;
+ if (hflag == BM_ELEM_SELECT) {
+ BM_elem_select_set(self->bm, self->ele, param);
}
else {
- PyErr_Format(PyExc_TypeError,
- "expected True/False or 0/1, not %.200s",
- Py_TYPE(value)->tp_name);
- return -1;
+ BM_elem_flag_set(self->ele, hflag, param);
}
+ return 0;
}
-
PyDoc_STRVAR(bpy_bm_elem_index_doc,
"Index of this element.\n"
"\n"
@@ -169,21 +163,17 @@ static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED
BPY_BM_CHECK_INT(self);
- param = PyLong_AsLong(value);
-
- if (param == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError,
- "expected an int type");
+ if (((param = PyC_Long_AsI32(value)) == -1) && PyErr_Occurred()) {
+ /* error is set */
return -1;
}
- else {
- BM_elem_index_set(self->ele, param); /* set_dirty! */
- /* when setting the index assume its set invalid */
- self->bm->elem_index_dirty |= self->ele->head.htype;
+ BM_elem_index_set(self->ele, param); /* set_dirty! */
- return 0;
- }
+ /* when setting the index assume its set invalid */
+ self->bm->elem_index_dirty |= self->ele->head.htype;
+
+ return 0;
}
/* type specific get/sets
@@ -506,14 +496,12 @@ static int bpy_bmface_material_index_set(BPy_BMFace *self, PyObject *value)
BPY_BM_CHECK_INT(self);
- param = PyLong_AsLong(value);
-
- if (param == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError,
- "expected an int type");
+ if (((param = PyC_Long_AsI32(value)) == -1) && PyErr_Occurred()) {
+ /* error is set */
return -1;
}
- else if ((param < 0) || (param > MAXMAT)) {
+
+ if ((param < 0) || (param > MAXMAT)) {
/* normally we clamp but in this case raise an error */
PyErr_SetString(PyExc_ValueError,
"material index outside of usable range (0 - 32766)");
@@ -1049,6 +1037,13 @@ PyDoc_STRVAR(bpy_bmesh_from_mesh_doc,
" :type use_shape_key: boolean\n"
" :arg shape_key_index: The shape key index to use.\n"
" :type shape_key_index: int\n"
+"\n"
+" .. note::\n"
+"\n"
+" Multiple calls can be used to join multiple meshes.\n"
+"\n"
+" Custom-data layers are only copied from ``mesh`` on initialization.\n"
+" Further calls will copy custom-data to matching layers, layers missing on the target mesh wont be added.\n"
);
static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *kw)
{
@@ -1113,15 +1108,16 @@ static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
BPY_BM_CHECK_OBJ(self);
- param = PyLong_AsLong(value);
- if (param != false && param != true) {
- PyErr_SetString(PyExc_TypeError,
- "expected a boolean type 0/1");
+ if ((param = PyC_Long_AsBool(value)) == -1) {
return NULL;
}
- if (param) BM_mesh_select_flush(self->bm);
- else BM_mesh_deselect_flush(self->bm);
+ if (param) {
+ BM_mesh_select_flush(self->bm);
+ }
+ else {
+ BM_mesh_deselect_flush(self->bm);
+ }
Py_RETURN_NONE;
}
@@ -1301,10 +1297,7 @@ static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
BPY_BM_CHECK_OBJ(self);
- param = PyLong_AsLong(value);
- if (param != false && param != true) {
- PyErr_SetString(PyExc_TypeError,
- "expected a boolean type 0/1");
+ if ((param = PyC_Long_AsBool(value)) == -1) {
return NULL;
}
@@ -1329,10 +1322,7 @@ static PyObject *bpy_bm_elem_hide_set(BPy_BMElem *self, PyObject *value)
BPY_BM_CHECK_OBJ(self);
- param = PyLong_AsLong(value);
- if (param != false && param != true) {
- PyErr_SetString(PyExc_TypeError,
- "expected a boolean type 0/1");
+ if ((param = PyC_Long_AsBool(value)) == -1) {
return NULL;
}
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index 908f6b5a734..cb95ded4f0d 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -43,6 +43,7 @@
#include "../mathutils/mathutils.h"
#include "../generic/python_utildefines.h"
+#include "../generic/py_capi_utils.h"
#include "BKE_customdata.h"
@@ -1074,9 +1075,9 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
}
case CD_PROP_INT:
{
- int tmp_val = PyLong_AsLong(py_value);
+ int tmp_val = PyC_Long_AsI32(py_value);
if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
- PyErr_Format(PyExc_TypeError, "expected an int, not a %.200s", Py_TYPE(py_value)->tp_name);
+ /* error is set */
ret = -1;
}
else {
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index 92c11a03433..b01d3f89d4e 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -45,6 +45,7 @@
#include "bmesh_py_types_meshdata.h"
+#include "../generic/py_capi_utils.h"
#include "../generic/python_utildefines.h"
@@ -188,7 +189,7 @@ static int bpy_bmloopuv_flag_set(BPy_BMLoopUV *self, PyObject *value, void *flag
{
const int flag = GET_INT_FROM_POINTER(flag_p);
- switch (PyLong_AsLong(value)) {
+ switch (PyC_Long_AsBool(value)) {
case true:
self->data->flag |= flag;
return 0;
@@ -196,8 +197,7 @@ static int bpy_bmloopuv_flag_set(BPy_BMLoopUV *self, PyObject *value, void *flag
self->data->flag &= ~flag;
return 0;
default:
- PyErr_SetString(PyExc_TypeError,
- "expected a boolean type 0/1");
+ /* error is set */
return -1;
}
}
@@ -297,7 +297,7 @@ static int bpy_bmvertskin_flag_set(BPy_BMVertSkin *self, PyObject *value, void *
{
const int flag = GET_INT_FROM_POINTER(flag_p);
- switch (PyLong_AsLong(value)) {
+ switch (PyC_Long_AsBool(value)) {
case true:
self->data->flag |= flag;
return 0;
@@ -305,8 +305,7 @@ static int bpy_bmvertskin_flag_set(BPy_BMVertSkin *self, PyObject *value, void *
self->data->flag &= ~flag;
return 0;
default:
- PyErr_SetString(PyExc_TypeError,
- "expected a boolean type 0/1");
+ /* error is set */
return -1;
}
}
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index ed2752d8372..7ab6447d21a 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -248,8 +248,17 @@ PyObject *bpy_text_reimport(PyObject *module, int *found)
if ((name = PyModule_GetName(module)) == NULL)
return NULL;
- if ((filepath = (char *)PyModule_GetFilename(module)) == NULL)
- return NULL;
+ {
+ PyObject *module_file = PyModule_GetFilenameObject(module);
+ if (module_file == NULL) {
+ return NULL;
+ }
+ filepath = (char *)_PyUnicode_AsString(module_file);
+ Py_DECREF(module_file);
+ if (filepath == NULL) {
+ return NULL;
+ }
+ }
/* look up the text object */
text = BLI_findstring(&maggie->text, BLI_path_basename(filepath), offsetof(ID, name) + 2);
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index 5d6a7c578a2..1153e0176df 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -386,7 +386,7 @@ static IDProperty *idp_from_PyFloat(const char *name, PyObject *ob)
static IDProperty *idp_from_PyLong(const char *name, PyObject *ob)
{
IDPropertyTemplate val = {0};
- val.i = _PyLong_AsInt(ob);
+ val.i = PyC_Long_AsI32(ob);
if (val.i == -1 && PyErr_Occurred()) {
return NULL;
}
@@ -499,7 +499,7 @@ static IDProperty *idp_from_PySequence_Fast(const char *name, PyObject *ob)
prop_data = IDP_Array(prop);
for (i = 0; i < val.array.len; i++) {
item = ob_seq_fast_items[i];
- if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) {
+ if (((prop_data[i] = PyC_Long_AsI32(item)) == -1) && PyErr_Occurred()) {
return NULL;
}
}
@@ -1337,7 +1337,7 @@ static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value)
}
case IDP_INT:
{
- const int i = _PyLong_AsInt(value);
+ const int i = PyC_Long_AsI32(value);
if (i == -1 && PyErr_Occurred()) {
return -1;
}
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 2e789d6d4b3..d49f9514b8c 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -85,7 +85,7 @@ int PyC_AsArray_FAST(
/* could use is_double for 'long int' but no use now */
int *array_int = array;
for (i = 0; i < length; i++) {
- array_int[i] = PyLong_AsLong(value_fast_items[i]);
+ array_int[i] = PyC_Long_AsI32(value_fast_items[i]);
}
}
else if (type == &PyBool_Type) {
@@ -127,54 +127,52 @@ int PyC_AsArray(
return ret;
}
+/* -------------------------------------------------------------------- */
+/** \name Typed Tuple Packing
+ *
+ * \note See #PyC_Tuple_Pack_* macros that take multiple arguments.
+ *
+ * \{ */
+
/* array utility function */
-PyObject *PyC_FromArray(const void *array, int length, const PyTypeObject *type,
- const bool is_double, const char *error_prefix)
+PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len)
{
- PyObject *tuple;
- int i;
-
- tuple = PyTuple_New(length);
-
- /* for each type */
- if (type == &PyFloat_Type) {
- if (is_double) {
- const double *array_double = array;
- for (i = 0; i < length; ++i) {
- PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array_double[i]));
- }
- }
- else {
- const float *array_float = array;
- for (i = 0; i < length; ++i) {
- PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array_float[i]));
- }
- }
- }
- else if (type == &PyLong_Type) {
- /* could use is_double for 'long int' but no use now */
- const int *array_int = array;
- for (i = 0; i < length; ++i) {
- PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(array_int[i]));
- }
+ PyObject *tuple = PyTuple_New(len);
+ for (uint i = 0; i < len; i++) {
+ PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array[i]));
}
- else if (type == &PyBool_Type) {
- const int *array_bool = array;
- for (i = 0; i < length; ++i) {
- PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array_bool[i]));
- }
+ return tuple;
+}
+
+PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len)
+{
+ PyObject *tuple = PyTuple_New(len);
+ for (uint i = 0; i < len; i++) {
+ PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(array[i]));
}
- else {
- Py_DECREF(tuple);
- PyErr_Format(PyExc_TypeError,
- "%s: internal error %s is invalid",
- error_prefix, type->tp_name);
- return NULL;
+ return tuple;
+}
+
+PyObject *PyC_Tuple_PackArray_I32FromBool(const int *array, uint len)
+{
+ PyObject *tuple = PyTuple_New(len);
+ for (uint i = 0; i < len; i++) {
+ PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array[i]));
}
+ return tuple;
+}
+PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len)
+{
+ PyObject *tuple = PyTuple_New(len);
+ for (uint i = 0; i < len; i++) {
+ PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array[i]));
+ }
return tuple;
}
+/** \} */
+
/**
* Caller needs to ensure tuple is uninitialized.
* Handy for filling a tuple with None for eg.
@@ -203,6 +201,8 @@ void PyC_List_Fill(PyObject *list, PyObject *value)
/**
* Use with PyArg_ParseTuple's "O&" formatting.
+ *
+ * \see #PyC_Long_AsBool for a similar function to use outside of argument parsing.
*/
int PyC_ParseBool(PyObject *o, void *p)
{
@@ -300,7 +300,14 @@ void PyC_FileAndNum(const char **filename, int *lineno)
if (mod_name) {
PyObject *mod = PyDict_GetItem(PyImport_GetModuleDict(), mod_name);
if (mod) {
- *filename = PyModule_GetFilename(mod);
+ PyObject *mod_file = PyModule_GetFilenameObject(mod);
+ if (mod_file) {
+ *filename = _PyUnicode_AsString(mod_name);
+ Py_DECREF(mod_file);
+ }
+ else {
+ PyErr_Clear();
+ }
}
/* unlikely, fallback */
@@ -1108,3 +1115,101 @@ bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_val
}
#endif /* #ifndef MATH_STANDALONE */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Int Conversion
+ *
+ * \note Python doesn't provide overflow checks for specific bit-widths.
+ *
+ * \{ */
+
+/* Compiler optimizes out redundant checks. */
+#ifdef __GNUC__
+# pragma warning(push)
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+/**
+ * Don't use `bool` return type, so -1 can be used as an error value.
+ */
+int PyC_Long_AsBool(PyObject *value)
+{
+ int test = _PyLong_AsInt(value);
+ if (UNLIKELY((uint)test > 1)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Python number not a bool (0/1)");
+ return -1;
+ }
+ return test;
+}
+
+int8_t PyC_Long_AsI8(PyObject *value)
+{
+ int test = _PyLong_AsInt(value);
+ if (UNLIKELY(test < INT8_MIN || test > INT8_MAX)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C int8");
+ return -1;
+ }
+ return (int8_t)test;
+}
+
+int16_t PyC_Long_AsI16(PyObject *value)
+{
+ int test = _PyLong_AsInt(value);
+ if (UNLIKELY(test < INT16_MIN || test > INT16_MAX)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C int16");
+ return -1;
+ }
+ return (int16_t)test;
+}
+
+/* Inlined in header:
+ * PyC_Long_AsI32
+ * PyC_Long_AsI64
+ */
+
+uint8_t PyC_Long_AsU8(PyObject *value)
+{
+ ulong test = PyLong_AsUnsignedLong(value);
+ if (UNLIKELY(test > UINT8_MAX)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C uint8");
+ return (uint8_t)-1;
+ }
+ return (uint8_t)test;
+}
+
+uint16_t PyC_Long_AsU16(PyObject *value)
+{
+ ulong test = PyLong_AsUnsignedLong(value);
+ if (UNLIKELY(test > UINT16_MAX)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C uint16");
+ return (uint16_t)-1;
+ }
+ return (uint16_t)test;
+}
+
+uint32_t PyC_Long_AsU32(PyObject *value)
+{
+ ulong test = PyLong_AsUnsignedLong(value);
+ if (UNLIKELY(test > UINT32_MAX)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C uint32");
+ return (uint32_t)-1;
+ }
+ return (uint32_t)test;
+}
+
+/* Inlined in header:
+ * PyC_Long_AsU64
+ */
+
+#ifdef __GNUC__
+# pragma warning(pop)
+#endif
+
+/** \} */
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 3f89e1d82a0..053250a2a95 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -24,10 +24,12 @@
* \ingroup pygen
*/
-
#ifndef __PY_CAPI_UTILS_H__
#define __PY_CAPI_UTILS_H__
+#include "BLI_sys_types.h"
+#include "BLI_variadic_defines.h"
+
void PyC_ObSpit(const char *name, PyObject *var);
void PyC_LineSpit(void);
void PyC_StackSpit(void);
@@ -44,8 +46,21 @@ int PyC_AsArray_FAST(
int PyC_AsArray(
void *array, PyObject *value, const Py_ssize_t length,
const PyTypeObject *type, const bool is_double, const char *error_prefix);
-PyObject * PyC_FromArray(const void *array, int length, const PyTypeObject *type,
- const bool is_double, const char *error_prefix);
+
+PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len);
+PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len);
+PyObject *PyC_Tuple_PackArray_I32FromBool(const int *array, uint len);
+PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len);
+
+#define PyC_Tuple_Pack_F32(...) \
+ PyC_Tuple_PackArray_F32(((const float []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+#define PyC_Tuple_Pack_I32(...) \
+ PyC_Tuple_PackArray_I32(((const int []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+#define PyC_Tuple_Pack_I32FromBool(...) \
+ PyC_Tuple_PackArray_I32FromBool(((const int []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+#define PyC_Tuple_Pack_Bool(...) \
+ PyC_Tuple_PackArray_Bool(((const bool []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value);
void PyC_List_Fill(PyObject *list, PyObject *value);
@@ -85,4 +100,26 @@ bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_val
int PyC_ParseBool(PyObject *o, void *p);
+
+/* Integer parsing (with overflow checks), -1 on error. */
+int PyC_Long_AsBool(PyObject *value);
+int8_t PyC_Long_AsI8(PyObject *value);
+int16_t PyC_Long_AsI16(PyObject *value);
+#if 0 /* inline */
+int32_t PyC_Long_AsI32(PyObject *value);
+int64_t PyC_Long_AsI64(PyObject *value);
+#endif
+
+uint8_t PyC_Long_AsU8(PyObject *value);
+uint16_t PyC_Long_AsU16(PyObject *value);
+uint32_t PyC_Long_AsU32(PyObject *value);
+#if 0 /* inline */
+uint64_t PyC_Long_AsU64(PyObject *value);
+#endif
+
+/* inline so type signatures match as expected */
+Py_LOCAL_INLINE(int32_t) PyC_Long_AsI32(PyObject *value) { return (int32_t)_PyLong_AsInt(value); }
+Py_LOCAL_INLINE(int64_t) PyC_Long_AsI64(PyObject *value) { return (int64_t)PyLong_AsLongLong(value); }
+Py_LOCAL_INLINE(uint64_t) PyC_Long_AsU64(PyObject *value) { return (uint64_t)PyLong_AsUnsignedLongLong(value); }
+
#endif /* __PY_CAPI_UTILS_H__ */
diff --git a/source/blender/python/generic/python_utildefines.h b/source/blender/python/generic/python_utildefines.h
index f7d3e7a8b4a..2d2d19c05f5 100644
--- a/source/blender/python/generic/python_utildefines.h
+++ b/source/blender/python/generic/python_utildefines.h
@@ -36,16 +36,16 @@ extern "C" {
PyTupleObject *op = (PyTupleObject *)op_arg; \
PyObject **ob_items = op->ob_item; \
CHECK_TYPE_ANY(op_arg, PyObject *, PyTupleObject *); \
- BLI_assert(_VA_NARGS_COUNT(__VA_ARGS__) == PyTuple_GET_SIZE(op)); \
+ BLI_assert(VA_NARGS_COUNT(__VA_ARGS__) == PyTuple_GET_SIZE(op)); \
ARRAY_SET_ITEMS(ob_items, __VA_ARGS__); \
} (void)0
/* wrap Py_INCREF & return the result,
* use sparingly to avoid comma operator or temp var assignment */
-BLI_INLINE PyObject *Py_INCREF_RET(PyObject *op) { Py_INCREF(op); return op; }
+Py_LOCAL_INLINE(PyObject *)Py_INCREF_RET(PyObject *op) { Py_INCREF(op); return op; }
/* append & transfer ownership to the list, avoids inline Py_DECREF all over (which is quite a large macro) */
-BLI_INLINE int PyList_APPEND(PyObject *op, PyObject *v)
+Py_LOCAL_INLINE(int) PyList_APPEND(PyObject *op, PyObject *v)
{
int ret = PyList_Append(op, v);
Py_DecRef(v);
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 038c1e7eb10..be4db6477fe 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -55,6 +55,7 @@ set(SRC
bpy_app_handlers.c
bpy_app_ocio.c
bpy_app_oiio.c
+ bpy_app_opensubdiv.c
bpy_app_openvdb.c
bpy_app_sdl.c
bpy_app_translations.c
@@ -89,6 +90,7 @@ set(SRC
bpy_app_handlers.h
bpy_app_ocio.h
bpy_app_oiio.h
+ bpy_app_opensubdiv.h
bpy_app_openvdb.h
bpy_app_sdl.h
bpy_app_translations.h
@@ -295,6 +297,13 @@ if(WITH_OPENIMAGEIO)
)
endif()
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+ list(APPEND INC
+ ../../../../intern/opensubdiv
+ )
+endif()
+
if(WITH_PLAYER)
add_definitions(-DWITH_PLAYER)
endif()
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index ed7cec2f2d5..f44401afd7d 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -37,6 +37,7 @@
#include "bpy_app_ffmpeg.h"
#include "bpy_app_ocio.h"
#include "bpy_app_oiio.h"
+#include "bpy_app_opensubdiv.h"
#include "bpy_app_openvdb.h"
#include "bpy_app_sdl.h"
#include "bpy_app_build_options.h"
@@ -88,6 +89,7 @@ static PyStructSequence_Field app_info_fields[] = {
{(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"},
{(char *)"binary_path", (char *)"The location of blenders executable, useful for utilities that spawn new instances"},
{(char *)"background", (char *)"Boolean, True when blender is running without a user interface (started with -b)"},
+ {(char *)"factory_startup", (char *)"Boolean, True when blender is running with --factory-startup)"},
/* buildinfo */
{(char *)"build_date", (char *)"The date this blender instance was built"},
@@ -109,6 +111,7 @@ static PyStructSequence_Field app_info_fields[] = {
{(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
{(char *)"ocio", (char *)"OpenColorIO library information backend"},
{(char *)"oiio", (char *)"OpenImageIO library information backend"},
+ {(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"},
{(char *)"openvdb", (char *)"OpenVDB library information backend"},
{(char *)"sdl", (char *)"SDL library information backend"},
{(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
@@ -117,9 +120,21 @@ static PyStructSequence_Field app_info_fields[] = {
{NULL},
};
+PyDoc_STRVAR(bpy_app_doc,
+"This module contains application values that remain unchanged during runtime.\n"
+"\n"
+"Submodules:\n"
+"\n"
+".. toctree::\n"
+" :maxdepth: 1\n"
+"\n"
+" bpy.app.handlers.rst\n"
+" bpy.app.translations.rst\n"
+);
+
static PyStructSequence_Desc app_info_desc = {
(char *)"bpy.app", /* name */
- (char *)"This module contains application values that remain unchanged during runtime.", /* doc */
+ bpy_app_doc, /* doc */
app_info_fields, /* fields */
ARRAY_SIZE(app_info_fields) - 1
};
@@ -142,8 +157,7 @@ static PyObject *make_app_info(void)
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(app_info, pos++, obj)
- SetObjItem(Py_BuildValue("(iii)",
- BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
+ SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
SetObjItem(PyUnicode_FromFormat("%d.%02d (sub %d)",
BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
@@ -151,6 +165,7 @@ static PyObject *make_app_info(void)
SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
SetStrItem(BKE_appdir_program_path());
SetObjItem(PyBool_FromLong(G.background));
+ SetObjItem(PyBool_FromLong(G.factory_startup));
/* build info, use bytes since we can't assume _any_ encoding:
* see patch [#30154] for issue */
@@ -188,6 +203,7 @@ static PyObject *make_app_info(void)
SetObjItem(BPY_app_ffmpeg_struct());
SetObjItem(BPY_app_ocio_struct());
SetObjItem(BPY_app_oiio_struct());
+ SetObjItem(BPY_app_opensubdiv_struct());
SetObjItem(BPY_app_openvdb_struct());
SetObjItem(BPY_app_sdl_struct());
SetObjItem(BPY_app_build_options_struct());
@@ -275,7 +291,7 @@ static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(cl
static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
{
- int param = PyLong_AsLong(value);
+ int param = PyC_Long_AsI32(value);
if (param == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "bpy.app.debug_value can only be set to a whole number");
diff --git a/source/blender/python/intern/bpy_app_alembic.c b/source/blender/python/intern/bpy_app_alembic.c
index 90e6a02b418..2a1a031a629 100644
--- a/source/blender/python/intern/bpy_app_alembic.c
+++ b/source/blender/python/intern/bpy_app_alembic.c
@@ -34,6 +34,8 @@
#include "bpy_app_alembic.h"
+#include "../generic/py_capi_utils.h"
+
#ifdef WITH_ALEMBIC
# include "ABC_alembic.h"
#endif
@@ -79,11 +81,11 @@ static PyObject *make_alembic_info(void)
const int patch = curversion - ((curversion / 100 ) * 100);
SetObjItem(PyBool_FromLong(1));
- SetObjItem(Py_BuildValue("(iii)", major, minor, patch));
+ SetObjItem(PyC_Tuple_Pack_I32(major, minor, patch));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", major, minor, patch));
#else
SetObjItem(PyBool_FromLong(0));
- SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c
index fd516e4547f..9f8355db72b 100644
--- a/source/blender/python/intern/bpy_app_ffmpeg.c
+++ b/source/blender/python/intern/bpy_app_ffmpeg.c
@@ -29,6 +29,8 @@
#include "bpy_app_ffmpeg.h"
+#include "../generic/py_capi_utils.h"
+
#ifdef WITH_FFMPEG
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
@@ -91,8 +93,7 @@ static PyObject *make_ffmpeg_info(void)
#ifdef WITH_FFMPEG
# define FFMPEG_LIB_VERSION(lib) { \
curversion = lib ## _version(); \
- SetObjItem(Py_BuildValue("(iii)", \
- curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \
+ SetObjItem(PyC_Tuple_Pack_I32(curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", \
curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \
} (void)0
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index fdc2371c259..90aa22de5bf 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -59,8 +59,12 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{(char *)"load_post", (char *)"on loading a new blend file (after)"},
{(char *)"save_pre", (char *)"on saving a blend file (before)"},
{(char *)"save_post", (char *)"on saving a blend file (after)"},
- {(char *)"scene_update_pre", (char *)"on updating the scenes data (before)"},
- {(char *)"scene_update_post", (char *)"on updating the scenes data (after)"},
+ {(char *)"scene_update_pre", (char *)"on every scene data update. Does not imply that anything changed in the "
+ "scene, just that the dependency graph is about to be reevaluated, and the "
+ "scene is about to be updated by Blender's animation system."},
+ {(char *)"scene_update_post", (char *)"on every scene data update. Does not imply that anything changed in the "
+ "scene, just that the dependency graph was reevaluated, and the scene was "
+ "possibly updated by Blender's animation system."},
{(char *)"game_pre", (char *)"on starting the game engine"},
{(char *)"game_post", (char *)"on ending the game engine"},
{(char *)"version_update", (char *)"on ending the versioning code"},
diff --git a/source/blender/python/intern/bpy_app_ocio.c b/source/blender/python/intern/bpy_app_ocio.c
index 02e4044219a..9997e6b87f1 100644
--- a/source/blender/python/intern/bpy_app_ocio.c
+++ b/source/blender/python/intern/bpy_app_ocio.c
@@ -29,6 +29,8 @@
#include "bpy_app_ocio.h"
+#include "../generic/py_capi_utils.h"
+
#ifdef WITH_OCIO
# include "ocio_capi.h"
#endif
@@ -74,13 +76,12 @@ static PyObject *make_ocio_info(void)
#ifdef WITH_OCIO
curversion = OCIO_getVersionHex();
SetObjItem(PyBool_FromLong(1));
- SetObjItem(Py_BuildValue("(iii)",
- curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
+ SetObjItem(PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
#else
SetObjItem(PyBool_FromLong(0));
- SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
diff --git a/source/blender/python/intern/bpy_app_oiio.c b/source/blender/python/intern/bpy_app_oiio.c
index 60daf3ddd8b..e14b48ff7cf 100644
--- a/source/blender/python/intern/bpy_app_oiio.c
+++ b/source/blender/python/intern/bpy_app_oiio.c
@@ -29,6 +29,8 @@
#include "bpy_app_oiio.h"
+#include "../generic/py_capi_utils.h"
+
#ifdef WITH_OPENIMAGEIO
# include "openimageio_api.h"
#endif
@@ -74,13 +76,12 @@ static PyObject *make_oiio_info(void)
#ifdef WITH_OPENIMAGEIO
curversion = OIIO_getVersionHex();
SetObjItem(PyBool_FromLong(1));
- SetObjItem(Py_BuildValue("(iii)",
- curversion / 10000, (curversion / 100) % 100, curversion % 100));
+ SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
curversion / 10000, (curversion / 100) % 100, curversion % 100));
#else
SetObjItem(PyBool_FromLong(0));
- SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
diff --git a/source/blender/python/intern/bpy_app_opensubdiv.c b/source/blender/python/intern/bpy_app_opensubdiv.c
new file mode 100644
index 00000000000..096374794c9
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_opensubdiv.c
@@ -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): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_opensubdiv.c
+ * \ingroup pythonintern
+ */
+
+#include <Python.h>
+#include "BLI_utildefines.h"
+
+#include "bpy_app_opensubdiv.h"
+
+#include "../generic/py_capi_utils.h"
+
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_capi.h"
+#endif
+
+static PyTypeObject BlenderAppOpenSubdivType;
+
+static PyStructSequence_Field app_opensubdiv_info_fields[] = {
+ {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenSubdiv support")},
+ {(char *)("version"), (char *)("The OpenSubdiv version as a tuple of 3 numbers")},
+ {(char *)("version_string"), (char *)("The OpenSubdiv version formatted as a string")},
+ {NULL}
+};
+
+static PyStructSequence_Desc app_opensubdiv_info_desc = {
+ (char *)"bpy.app.opensubdiv", /* name */
+ (char *)"This module contains information about OpenSubdiv blender is linked against", /* doc */
+ app_opensubdiv_info_fields, /* fields */
+ ARRAY_SIZE(app_opensubdiv_info_fields) - 1
+};
+
+static PyObject *make_opensubdiv_info(void)
+{
+ PyObject *opensubdiv_info;
+ int pos = 0;
+
+ opensubdiv_info = PyStructSequence_New(&BlenderAppOpenSubdivType);
+ if (opensubdiv_info == NULL) {
+ return NULL;
+ }
+
+#ifndef WITH_OPENSUBDIV
+#define SetStrItem(str) \
+ PyStructSequence_SET_ITEM(opensubdiv_info, pos++, PyUnicode_FromString(str))
+#endif
+
+#define SetObjItem(obj) \
+ PyStructSequence_SET_ITEM(opensubdiv_info, pos++, obj)
+
+#ifdef WITH_OPENSUBDIV
+ int curversion = openSubdiv_getVersionHex();
+ SetObjItem(PyBool_FromLong(1));
+ SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100));
+ SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
+#else
+ SetObjItem(PyBool_FromLong(0));
+ SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
+ SetStrItem("Unknown");
+#endif
+
+ if (PyErr_Occurred()) {
+ Py_CLEAR(opensubdiv_info);
+ return NULL;
+ }
+
+#undef SetStrItem
+#undef SetObjItem
+
+ return opensubdiv_info;
+}
+
+PyObject *BPY_app_opensubdiv_struct(void)
+{
+ PyObject *ret;
+
+ PyStructSequence_InitType(&BlenderAppOpenSubdivType, &app_opensubdiv_info_desc);
+
+ ret = make_opensubdiv_info();
+
+ /* prevent user from creating new instances */
+ BlenderAppOpenSubdivType.tp_init = NULL;
+ BlenderAppOpenSubdivType.tp_new = NULL;
+ /* without this we can't do set(sys.modules) [#29635] */
+ BlenderAppOpenSubdivType.tp_hash = (hashfunc)_Py_HashPointer;
+
+ return ret;
+}
diff --git a/source/blender/python/intern/bpy_app_opensubdiv.h b/source/blender/python/intern/bpy_app_opensubdiv.h
new file mode 100644
index 00000000000..b1da218b168
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_opensubdiv.h
@@ -0,0 +1,32 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_opensubdiv.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_APP_OPENSUBDIV_H__
+#define __BPY_APP_OPENSUBDIV_H__
+
+PyObject *BPY_app_opensubdiv_struct(void);
+
+#endif /* __BPY_APP_OPENSUBDIV_H__ */
diff --git a/source/blender/python/intern/bpy_app_openvdb.c b/source/blender/python/intern/bpy_app_openvdb.c
index 8a24aaf0555..0b385206d7b 100644
--- a/source/blender/python/intern/bpy_app_openvdb.c
+++ b/source/blender/python/intern/bpy_app_openvdb.c
@@ -34,6 +34,8 @@
#include "bpy_app_openvdb.h"
+#include "../generic/py_capi_utils.h"
+
#ifdef WITH_OPENVDB
# include "openvdb_capi.h"
#endif
@@ -79,13 +81,12 @@ static PyObject *make_openvdb_info(void)
#ifdef WITH_OPENVDB
curversion = OpenVDB_getVersionHex();
SetObjItem(PyBool_FromLong(1));
- SetObjItem(Py_BuildValue("(iii)",
- curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
+ SetObjItem(PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
#else
SetObjItem(PyBool_FromLong(0));
- SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
diff --git a/source/blender/python/intern/bpy_app_sdl.c b/source/blender/python/intern/bpy_app_sdl.c
index 2f4d8e6c325..816ad2833cc 100644
--- a/source/blender/python/intern/bpy_app_sdl.c
+++ b/source/blender/python/intern/bpy_app_sdl.c
@@ -29,6 +29,8 @@
#include "bpy_app_sdl.h"
+#include "../generic/py_capi_utils.h"
+
#ifdef WITH_SDL
/* SDL force defines __SSE__ and __SSE2__ flags, which generates warnings
* because we pass those defines via command line as well. For until there's
@@ -56,7 +58,7 @@ static PyStructSequence_Field app_sdl_info_fields[] = {
{(char *)"available", (char *)("Boolean, True when SDL is available. This is False when "
"either *supported* is False, or *dynload* is True and "
"Blender cannot find the correct library.")},
- {NULL}
+ {NULL}
};
static PyStructSequence_Desc app_sdl_info_desc = {
@@ -103,7 +105,7 @@ static PyObject *make_sdl_info(void)
# endif
# endif
- SetObjItem(Py_BuildValue("(iii)", version.major, version.minor, version.patch));
+ SetObjItem(PyC_Tuple_Pack_I32(version.major, version.minor, version.patch));
if (sdl_available) {
SetObjItem(PyUnicode_FromFormat("%d.%d.%d", version.major, version.minor, version.patch));
}
@@ -114,7 +116,7 @@ static PyObject *make_sdl_info(void)
#else // WITH_SDL=OFF
SetObjItem(PyBool_FromLong(0));
- SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
SetObjItem(PyBool_FromLong(0));
#endif
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 7b0daa91523..20cfd364a0c 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -869,6 +869,7 @@ static void bpy_module_delay_init(PyObject *bpy_proxy)
BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs));
BLI_path_cwd(filename_abs, sizeof(filename_abs));
+ Py_DECREF(filename_obj);
argv[0] = filename_abs;
argv[1] = NULL;
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index 15f3c665fcf..cb6a7147368 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -73,7 +73,7 @@ typedef struct {
} BPy_Library;
static PyObject *bpy_lib_load(PyObject *self, PyObject *args, PyObject *kwds);
-static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *args);
+static PyObject *bpy_lib_enter(BPy_Library *self);
static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *args);
static PyObject *bpy_lib_dir(BPy_Library *self);
@@ -237,7 +237,7 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype)
return list;
}
-static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args))
+static PyObject *bpy_lib_enter(BPy_Library *self)
{
PyObject *ret;
BPy_Library *self_from;
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index 11e27ca3e3c..9d57adca946 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -48,10 +48,12 @@ static void operator_properties_init(wmOperatorType *ot)
PyTypeObject *py_class = ot->ext.data;
RNA_struct_blender_type_set(ot->ext.srna, ot);
- /* only call this so pyrna_deferred_register_class gives a useful error
- * WM_operatortype_append_ptr will call RNA_def_struct_identifier
- * later */
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ /* Only call this so pyrna_deferred_register_class gives a useful error
+ * WM_operatortype_append_ptr will call RNA_def_struct_identifier later.
+ *
+ * Note the 'no_struct_map' function is used since the actual struct name is already used by the operator.
+ */
+ RNA_def_struct_identifier_no_struct_map(ot->srna, ot->idname);
if (pyrna_deferred_register_class(ot->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
@@ -118,7 +120,7 @@ static void operator_properties_init(wmOperatorType *ot)
}
-void operator_wrapper(wmOperatorType *ot, void *userdata)
+void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata)
{
/* take care not to overwrite anything set in
* WM_operatortype_append_ptr before opfunc() is called */
@@ -134,7 +136,7 @@ void operator_wrapper(wmOperatorType *ot, void *userdata)
operator_properties_init(ot);
}
-void macro_wrapper(wmOperatorType *ot, void *userdata)
+void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata)
{
wmOperatorType *data = (wmOperatorType *)userdata;
diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h
index 05a566a1485..0828c58e2bd 100644
--- a/source/blender/python/intern/bpy_operator_wrap.h
+++ b/source/blender/python/intern/bpy_operator_wrap.h
@@ -33,7 +33,7 @@ struct wmOperatorType;
PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args);
/* exposed to rna/wm api */
-void operator_wrapper(struct wmOperatorType *ot, void *userdata);
-void macro_wrapper(struct wmOperatorType *ot, void *userdata);
+void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata);
+void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata);
#endif
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 2656e612b18..9ef8f9aa046 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -320,7 +320,7 @@ static int bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p
value = false;
}
else {
- value = PyLong_AsLong(ret);
+ value = PyC_Long_AsI32(ret);
if (value == -1 && PyErr_Occurred()) {
printf_func_error(py_func);
@@ -530,12 +530,8 @@ static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, struct Propert
self = pyrna_struct_as_instance(ptr);
PyTuple_SET_ITEM(args, 0, self);
- py_values = PyC_FromArray(values, len, &PyBool_Type, false, "BoolVectorProperty set");
- if (!py_values) {
- printf_func_error(py_func);
- }
- else
- PyTuple_SET_ITEM(args, 1, py_values);
+ py_values = PyC_Tuple_PackArray_I32FromBool(values, len);
+ PyTuple_SET_ITEM(args, 1, py_values);
ret = PyObject_CallObject(py_func, args);
@@ -599,7 +595,7 @@ static int bpy_prop_int_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
value = 0.0f;
}
else {
- value = PyLong_AsLong(ret);
+ value = PyC_Long_AsI32(ret);
if (value == -1 && PyErr_Occurred()) {
printf_func_error(py_func);
@@ -764,12 +760,8 @@ static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA
self = pyrna_struct_as_instance(ptr);
PyTuple_SET_ITEM(args, 0, self);
- py_values = PyC_FromArray(values, len, &PyLong_Type, false, "IntVectorProperty set");
- if (!py_values) {
- printf_func_error(py_func);
- }
- else
- PyTuple_SET_ITEM(args, 1, py_values);
+ py_values = PyC_Tuple_PackArray_I32(values, len);
+ PyTuple_SET_ITEM(args, 1, py_values);
ret = PyObject_CallObject(py_func, args);
@@ -998,12 +990,8 @@ static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, struct PropertyR
self = pyrna_struct_as_instance(ptr);
PyTuple_SET_ITEM(args, 0, self);
- py_values = PyC_FromArray(values, len, &PyFloat_Type, false, "FloatVectorProperty set");
- if (!py_values) {
- printf_func_error(py_func);
- }
- else
- PyTuple_SET_ITEM(args, 1, py_values);
+ py_values = PyC_Tuple_PackArray_F32(values, len);
+ PyTuple_SET_ITEM(args, 1, py_values);
ret = PyObject_CallObject(py_func, args);
@@ -1249,7 +1237,7 @@ static int bpy_prop_enum_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop
value = RNA_property_enum_get_default(ptr, prop);
}
else {
- value = PyLong_AsLong(ret);
+ value = PyC_Long_AsI32(ret);
if (value == -1 && PyErr_Occurred()) {
printf_func_error(py_func);
@@ -2697,7 +2685,8 @@ PyDoc_STRVAR(BPy_EnumProperty_doc,
" :icon: An icon string identifier or integer icon value\n"
" (e.g. returned by :class:`bpy.types.UILayout.icon`)\n"
" :number: Unique value used as the identifier for this item (stored in file data).\n"
-" Use when the identifier may need to change.\n"
+" Use when the identifier may need to change. If the *ENUM_FLAG* option is used,\n"
+" the values are bitmasks and should be powers of two.\n"
"\n"
" When an item only contains 4 items they define ``(identifier, name, description, number)``.\n"
"\n"
@@ -2862,8 +2851,8 @@ PyDoc_STRVAR(BPy_PointerProperty_doc,
"name=\"\", "
"description=\"\", "
"options={'ANIMATABLE'}, "
- "update=None,\n"
- "poll=None)\n"
+ "poll=None, "
+ "update=None)\n"
"\n"
" Returns a new pointer property definition.\n"
"\n"
@@ -2891,7 +2880,7 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
PyObject *update_cb = NULL, *poll_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#O|ssO!OOO:PointerProperty",
+ "s#O|ssO!OO:PointerProperty",
(char **)kwlist, &id, &id_len,
&type, &name, &description,
&PySet_Type, &pyopts,
@@ -3001,7 +2990,7 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
}
PyDoc_STRVAR(BPy_RemoveProperty_doc,
-".. function:: RemoveProperty(cls, attr="")\n"
+".. function:: RemoveProperty(cls, attr)\n"
"\n"
" Removes a dynamically defined property.\n"
"\n"
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index a0b76bd67ee..398d2631f6c 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -70,6 +70,8 @@
#include "BKE_report.h"
#include "BKE_idprop.h"
+/* only for types */
+#include "BKE_node.h"
#include "../generic/idprop_py_api.h" /* for IDprop lookups */
#include "../generic/py_capi_utils.h"
@@ -1395,7 +1397,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
}
else {
EnumPropertyItem *enum_item;
- bool free = false;
+ bool free;
/* don't throw error here, can't trust blender 100% to give the
* right values, python code should not generate error for that */
@@ -1404,6 +1406,9 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
ret = PyUnicode_FromString(enum_item->identifier);
}
else {
+ if (free) {
+ MEM_freeN(enum_item);
+ }
RNA_property_enum_items(NULL, ptr, prop, &enum_item, NULL, &free);
/* Do not print warning in case of DummyRNA_NULL_items, this one will never match any value... */
@@ -1640,7 +1645,7 @@ static int pyrna_py_to_prop(
param = PyObject_IsTrue(value);
}
else {
- param = PyLong_AsLong(value);
+ param = PyC_Long_AsI32(value);
if (UNLIKELY(param & ~1)) { /* only accept 0/1 */
param = -1; /* error out below */
@@ -2076,10 +2081,10 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
{
- int param = PyLong_AsLong(value);
+ int param = PyC_Long_AsBool(value);
- if (param < 0 || param > 1) {
- PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1");
+ if (param == -1) {
+ /* error is set */
ret = -1;
}
else {
@@ -2089,7 +2094,7 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P
}
case PROP_INT:
{
- int param = PyLong_AsLong(value);
+ int param = PyC_Long_AsI32(value);
if (param == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected an int type");
ret = -1;
@@ -2709,7 +2714,7 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject
Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
- return pyrna_prop_array_subscript_int(self, PyLong_AsLong(key));
+ return pyrna_prop_array_subscript_int(self, i);
}
else if (PySlice_Check(key)) {
Py_ssize_t step = 1;
@@ -3704,6 +3709,110 @@ static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self)
return pyrna_struct_CreatePyObject(&r_ptr);
}
+/**
+ * \note Return value is borrowed, caller must incref.
+ */
+static PyObject *pyrna_struct_bl_rna_find_subclass_recursive(PyObject *cls, const char *id)
+{
+ PyObject *ret_test = NULL;
+ PyObject *subclasses = ((PyTypeObject *)cls)->tp_subclasses;
+ if (subclasses) {
+ /* Unfortunately we can't use the dict key because Python class names
+ * don't match the bl_idname used internally. */
+ BLI_assert(PyDict_CheckExact(subclasses));
+ PyObject *key = NULL;
+ Py_ssize_t pos = 0;
+ PyObject *value = NULL;
+ while (PyDict_Next(subclasses, &pos, &key, &value)) {
+ BLI_assert(PyWeakref_CheckRef(value));
+ PyObject *subcls = PyWeakref_GET_OBJECT(value);
+ if (subcls != Py_None) {
+ BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(
+ ((PyTypeObject *)subcls)->tp_dict, bpy_intern_str_bl_rna);
+ if (py_srna) {
+ StructRNA *srna = py_srna->ptr.data;
+ if (STREQ(id, RNA_struct_identifier(srna))) {
+ ret_test = subcls;
+ break;
+ }
+ }
+ ret_test = pyrna_struct_bl_rna_find_subclass_recursive(subcls, id);
+ if (ret_test) {
+ break;
+ }
+ }
+ }
+ }
+ return ret_test;
+}
+
+PyDoc_STRVAR(pyrna_struct_bl_rna_get_subclass_py_doc,
+".. classmethod:: bl_rna_get_subclass_py(id, default=None)\n"
+"\n"
+" :arg id: The RNA type identifier.\n"
+" :type id: string\n"
+" :return: The class or default when not found.\n"
+" :rtype: type\n"
+);
+static PyObject *pyrna_struct_bl_rna_get_subclass_py(PyObject *cls, PyObject *args)
+{
+ char *id;
+ PyObject *ret_default = Py_None;
+
+ if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass_py", &id, &ret_default)) {
+ return NULL;
+ }
+ PyObject *ret = pyrna_struct_bl_rna_find_subclass_recursive(cls, id);
+ if (ret == NULL) {
+ ret = ret_default;
+ }
+ return Py_INCREF_RET(ret);
+}
+
+PyDoc_STRVAR(pyrna_struct_bl_rna_get_subclass_doc,
+".. classmethod:: bl_rna_get_subclass(id, default=None)\n"
+"\n"
+" :arg id: The RNA type identifier.\n"
+" :type id: string\n"
+" :return: The RNA type or default when not found.\n"
+" :rtype: :class:`bpy.types.Struct` subclass\n"
+);
+static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args)
+{
+ char *id;
+ PyObject *ret_default = Py_None;
+
+ if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass", &id, &ret_default)) {
+ return NULL;
+ }
+
+
+ const BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)cls)->tp_dict, bpy_intern_str_bl_rna);
+ if (py_srna == NULL) {
+ PyErr_SetString(PyExc_ValueError, "Not a registered class");
+ return NULL;
+
+ }
+ const StructRNA *srna_base = py_srna->ptr.data;
+
+ PointerRNA ptr;
+ if (srna_base == &RNA_Node) {
+ bNodeType *nt = nodeTypeFind(id);
+ if (nt) {
+ RNA_pointer_create(NULL, &RNA_Struct, nt->ext.srna, &ptr);
+ return pyrna_struct_CreatePyObject(&ptr);
+ }
+ }
+ else {
+ /* TODO, panels, menus etc. */
+ PyErr_Format(PyExc_ValueError, "Class type \"%.200s\" not supported",
+ RNA_struct_identifier(srna_base));
+ return NULL;
+ }
+
+ return Py_INCREF_RET(ret_default);
+}
+
static void pyrna_dir_members_py__add_keys(PyObject *list, PyObject *dict)
{
PyObject *list_tmp;
@@ -5002,6 +5111,8 @@ static struct PyMethodDef pyrna_struct_methods[] = {
{"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc},
{"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc},
{"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc},
+ {"bl_rna_get_subclass_py", (PyCFunction) pyrna_struct_bl_rna_get_subclass_py, METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_py_doc},
+ {"bl_rna_get_subclass", (PyCFunction) pyrna_struct_bl_rna_get_subclass, METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_doc},
{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
/* experimental */
@@ -6924,15 +7035,7 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop)
{
StructRNA *srna = itemptr.data;
- StructRNA *srna_base = RNA_struct_base(itemptr.data);
- /* skip own operators, these double up [#29666] */
- if (srna_base == &RNA_Operator) {
- /* do nothing */
- }
- else {
- /* add to python list */
- PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna)));
- }
+ PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna)));
}
RNA_PROP_END;
@@ -7265,15 +7368,12 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
{
const ListBase *lb;
Link *link;
- FunctionRNA *func;
- PropertyRNA *prop;
const char *class_type = RNA_struct_identifier(srna);
StructRNA *srna_base = RNA_struct_base(srna);
PyObject *py_class = (PyObject *)py_data;
PyObject *base_class = RNA_struct_py_type_get(srna);
PyObject *item;
- int i, flag, arg_count, func_arg_count, func_arg_min_count = 0;
- bool is_staticmethod;
+ int i, arg_count, func_arg_count, func_arg_min_count = 0;
const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */
if (srna_base) {
@@ -7294,9 +7394,12 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
lb = RNA_struct_type_functions(srna);
i = 0;
for (link = lb->first; link; link = link->next) {
- func = (FunctionRNA *)link;
- flag = RNA_function_flag(func);
- is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
+ FunctionRNA *func = (FunctionRNA *)link;
+ const int flag = RNA_function_flag(func);
+ /* TODO(campbell): this is used for classmethod's too,
+ * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg.
+ * Keep this as-is since its working but we should be using 'FUNC_USE_SELF_TYPE' for many functions. */
+ const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
if (!(flag & FUNC_REGISTER))
continue;
@@ -7322,7 +7425,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
if (is_staticmethod) {
if (PyMethod_Check(item) == 0) {
PyErr_Format(PyExc_TypeError,
- "expected %.200s, %.200s class \"%.200s\" attribute to be a method, not a %.200s",
+ "expected %.200s, %.200s class \"%.200s\" "
+ "attribute to be a static/class method, not a %.200s",
class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name);
return -1;
}
@@ -7331,7 +7435,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
else {
if (PyFunction_Check(item) == 0) {
PyErr_Format(PyExc_TypeError,
- "expected %.200s, %.200s class \"%.200s\" attribute to be a function, not a %.200s",
+ "expected %.200s, %.200s class \"%.200s\" "
+ "attribute to be a function, not a %.200s",
class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name);
return -1;
}
@@ -7343,7 +7448,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
/* note, the number of args we check for and the number of args we give to
- * @staticmethods are different (quirk of python),
+ * '@staticmethods' are different (quirk of python),
* this is why rna_function_arg_count() doesn't return the value -1*/
if (is_staticmethod) {
func_arg_count++;
@@ -7374,8 +7479,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
lb = RNA_struct_type_properties(srna);
for (link = lb->first; link; link = link->next) {
const char *identifier;
- prop = (PropertyRNA *)link;
- flag = RNA_property_flag(prop);
+ PropertyRNA *prop = (PropertyRNA *)link;
+ const int flag = RNA_property_flag(prop);
if (!(flag & PROP_REGISTER))
continue;
diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c
index 38931cd85de..3e147d29c90 100644
--- a/source/blender/python/intern/bpy_rna_array.c
+++ b/source/blender/python/intern/bpy_rna_array.c
@@ -38,6 +38,8 @@
#include "RNA_access.h"
+#include "../generic/py_capi_utils.h"
+
#define USE_MATHUTILS
#ifdef USE_MATHUTILS
@@ -550,7 +552,7 @@ static void py_to_float(const struct ItemConvertArgData *arg, PyObject *py, char
static void py_to_int(const struct ItemConvertArgData *arg, PyObject *py, char *data)
{
const int *range = arg->int_data.range;
- int value = (int)PyLong_AsLong(py);
+ int value = PyC_Long_AsI32(py);
CLAMP(value, range[0], range[1]);
*(int *)data = value;
}
diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c
index b4c0de51c04..1135ba121e3 100644
--- a/source/blender/python/intern/bpy_rna_driver.c
+++ b/source/blender/python/intern/bpy_rna_driver.c
@@ -63,7 +63,15 @@ PyObject *pyrna_driver_get_variable_value(
}
else {
/* object & property */
- driver_arg = pyrna_prop_to_py(&ptr, prop);
+ PropertyType type = RNA_property_type(prop);
+ if (type == PROP_ENUM) {
+ /* Note that enum's are converted to strings by default,
+ * we want to avoid that, see: T52213 */
+ driver_arg = PyLong_FromLong(RNA_property_enum_get(&ptr, prop));
+ }
+ else {
+ driver_arg = pyrna_prop_to_py(&ptr, prop);
+ }
}
}
else {
diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c
index 7711ce18bd0..3c340d14e3f 100644
--- a/source/blender/python/intern/gpu_offscreen.c
+++ b/source/blender/python/intern/gpu_offscreen.c
@@ -144,36 +144,6 @@ static PyObject *pygpu_offscreen_unbind(BPy_GPUOffScreen *self, PyObject *args,
Py_RETURN_NONE;
}
-/**
- * Use with PyArg_ParseTuple's "O&" formatting.
- */
-static int pygpu_offscreen_check_matrix(PyObject *o, void *p)
-{
- MatrixObject **pymat_p = p;
- MatrixObject *pymat = (MatrixObject *)o;
-
- if (!MatrixObject_Check(pymat)) {
- PyErr_Format(PyExc_TypeError,
- "expected a mathutils.Matrix, not a %.200s",
- Py_TYPE(o)->tp_name);
- return 0;
- }
-
- if (BaseMath_ReadCallback(pymat) == -1) {
- return 0;
- }
-
- if ((pymat->num_col != 4) ||
- (pymat->num_row != 4))
- {
- PyErr_SetString(PyExc_ValueError, "matrix must be 4x4");
- return 0;
- }
-
- *pymat_p = pymat;
- return 1;
-}
-
PyDoc_STRVAR(pygpu_offscreen_draw_view3d_doc,
"draw_view3d(scene, view3d, region, modelview_matrix, projection_matrix)\n"
"\n"
@@ -209,8 +179,8 @@ static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *a
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "OOOO&O&:draw_view3d", (char **)(kwlist),
&py_scene, &py_view3d, &py_region,
- pygpu_offscreen_check_matrix, &py_mat_projection,
- pygpu_offscreen_check_matrix, &py_mat_modelview) ||
+ Matrix_Parse4x4, &py_mat_projection,
+ Matrix_Parse4x4, &py_mat_modelview) ||
(!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) ||
!(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) ||
!(ar = PyC_RNA_AsPointer(py_region, "Region"))))
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 5c505247a97..96ae0a9e50f 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -1,4 +1,4 @@
-/*
+/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -38,18 +38,31 @@
#endif
PyDoc_STRVAR(M_Mathutils_doc,
-"This module provides access to the math classes:\n"
+"This module provides access to math operations.\n"
+"\n"
+".. note::\n"
+"\n"
+" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
+" such as tuples, lists."
+"\n\n"
+"Submodules:\n"
+"\n"
+".. toctree::\n"
+" :maxdepth: 1\n"
+"\n"
+" mathutils.geometry.rst\n"
+" mathutils.bvhtree.rst\n"
+" mathutils.kdtree.rst\n"
+" mathutils.interpolate.rst\n"
+" mathutils.noise.rst\n"
+"\n"
+"The :mod:`mathutils` module provides the following classes:\n"
"\n"
"- :class:`Color`,\n"
"- :class:`Euler`,\n"
"- :class:`Matrix`,\n"
"- :class:`Quaternion`,\n"
"- :class:`Vector`,\n"
-"\n"
-".. note::\n"
-"\n"
-" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
-" such as tuples, lists."
);
static int mathutils_array_parse_fast(float *array,
int size,
@@ -219,7 +232,7 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
error_prefix, size, array_min);
return -1;
}
-
+
*array = PyMem_Malloc(size * sizeof(float));
memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float));
return size;
@@ -422,7 +435,7 @@ static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL};
unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb)
{
unsigned char i;
-
+
/* find the first free slot */
for (i = 0; mathutils_callbacks[i]; i++) {
if (mathutils_callbacks[i] == cb) /* already registered? */
@@ -541,8 +554,8 @@ char BaseMathObject_freeze_doc[] =
;
PyObject *BaseMathObject_freeze(BaseMathObject *self)
{
- if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
- PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped data");
+ if ((self->flag & BASE_MATH_FLAG_IS_WRAP) || (self->cb_user != NULL)) {
+ PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped/owned data");
return NULL;
}
@@ -625,14 +638,14 @@ PyMODINIT_FUNC PyInit_mathutils(void)
return NULL;
mod = PyModule_Create(&M_Mathutils_module_def);
-
+
/* each type has its own new() function */
PyModule_AddObject(mod, vector_Type.tp_name, (PyObject *)&vector_Type);
PyModule_AddObject(mod, matrix_Type.tp_name, (PyObject *)&matrix_Type);
PyModule_AddObject(mod, euler_Type.tp_name, (PyObject *)&euler_Type);
PyModule_AddObject(mod, quaternion_Type.tp_name, (PyObject *)&quaternion_Type);
PyModule_AddObject(mod, color_Type.tp_name, (PyObject *)&color_Type);
-
+
/* submodule */
PyModule_AddObject(mod, "geometry", (submodule = PyInit_mathutils_geometry()));
/* XXX, python doesnt do imports with this usefully yet
diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h
index 6ac75565c66..d1fb6dcdb82 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -41,9 +41,18 @@ extern char BaseMathObject_owner_doc[];
(struct_name *)((base_type ? (base_type)->tp_alloc(base_type, 0) : _PyObject_GC_New(&(root_type))));
-/* BaseMathObject.flag */
+/** BaseMathObject.flag */
enum {
+ /**
+ * Do not own the memory used in this vector,
+ * \note This is error prone if the memory may be freed while this vector is in use.
+ * Prefer using callbacks where possible, see: #Mathutils_RegisterCallback
+ */
BASE_MATH_FLAG_IS_WRAP = (1 << 0),
+ /**
+ * Prevent changes to the vector so it can be used as a set or dictionary key for example.
+ * (typical use cases for tuple).
+ */
BASE_MATH_FLAG_IS_FROZEN = (1 << 1),
};
#define BASE_MATH_FLAG_DEFAULT 0
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index e368e8871f3..2578b19d5ec 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -2914,6 +2914,73 @@ PyObject *Matrix_CreatePyObject_cb(PyObject *cb_user,
return (PyObject *) self;
}
+/**
+ * Use with PyArg_ParseTuple's "O&" formatting.
+ */
+static bool Matrix_ParseCheck(MatrixObject *pymat)
+{
+ if (!MatrixObject_Check(pymat)) {
+ PyErr_Format(PyExc_TypeError,
+ "expected a mathutils.Matrix, not a %.200s",
+ Py_TYPE(pymat)->tp_name);
+ return 0;
+ }
+ /* sets error */
+ if (BaseMath_ReadCallback(pymat) == -1) {
+ return 0;
+ }
+ return 1;
+}
+
+int Matrix_ParseAny(PyObject *o, void *p)
+{
+ MatrixObject **pymat_p = p;
+ MatrixObject *pymat = (MatrixObject *)o;
+
+ if (!Matrix_ParseCheck(pymat)) {
+ return 0;
+ }
+ *pymat_p = pymat;
+ return 1;
+}
+
+int Matrix_Parse3x3(PyObject *o, void *p)
+{
+ MatrixObject **pymat_p = p;
+ MatrixObject *pymat = (MatrixObject *)o;
+
+ if (!Matrix_ParseCheck(pymat)) {
+ return 0;
+ }
+ if ((pymat->num_col != 3) ||
+ (pymat->num_row != 3))
+ {
+ PyErr_SetString(PyExc_ValueError, "matrix must be 3x3");
+ return 0;
+ }
+
+ *pymat_p = pymat;
+ return 1;
+}
+
+int Matrix_Parse4x4(PyObject *o, void *p)
+{
+ MatrixObject **pymat_p = p;
+ MatrixObject *pymat = (MatrixObject *)o;
+
+ if (!Matrix_ParseCheck(pymat)) {
+ return 0;
+ }
+ if ((pymat->num_col != 4) ||
+ (pymat->num_row != 4))
+ {
+ PyErr_SetString(PyExc_ValueError, "matrix must be 4x4");
+ return 0;
+ }
+
+ *pymat_p = pymat;
+ return 1;
+}
/* ----------------------------------------------------------------------------
* special type for alternate access */
diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h
index 542a0e349c7..9c84716d307 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.h
+++ b/source/blender/python/mathutils/mathutils_Matrix.h
@@ -77,6 +77,11 @@ PyObject *Matrix_CreatePyObject_cb(
unsigned char cb_type, unsigned char cb_subtype
) ATTR_WARN_UNUSED_RESULT;
+/* PyArg_ParseTuple's "O&" formatting helpers. */
+int Matrix_ParseAny(PyObject *o, void *p);
+int Matrix_Parse3x3(PyObject *o, void *p);
+int Matrix_Parse4x4(PyObject *o, void *p);
+
extern unsigned char mathutils_matrix_row_cb_index; /* default */
extern unsigned char mathutils_matrix_col_cb_index;
extern unsigned char mathutils_matrix_translation_cb_index;
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index afc8a30a6b5..5d46dc284f4 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -32,10 +32,17 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/py_capi_utils.h"
+
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
#endif
+/**
+ * Higher dimensions are supported, for many common operations
+ * (dealing with vector/matrix multiply or handling as 3D locations)
+ * stack memory is used with a fixed size - defined here.
+ */
#define MAX_DIMENSIONS 4
/* Swizzle axes get packed into a single value that is used as a closure. Each
@@ -50,7 +57,8 @@ static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args);
static PyObject *Vector_to_tuple_ext(VectorObject *self, int ndigits);
static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject *vec, MatrixObject *mat);
-/* Supports 2D, 3D, and 4D vector objects both int and float values
+/**
+ * Supports 2D, 3D, and 4D vector objects both int and float values
* accepted. Mixed float and int values accepted. Ints are parsed to float
*/
static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -403,7 +411,7 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value)
return NULL;
}
- if ((size = PyLong_AsLong(value)) == -1) {
+ if ((size = PyC_Long_AsI32(value)) == -1) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize(size): "
"expected size argument to be an integer");
@@ -836,9 +844,11 @@ static PyObject *Vector_orthogonal(VectorObject *self)
}
-/*
- * Vector.reflect(mirror): return a reflected vector on the mirror normal
- * vec - ((2 * DotVecs(vec, mirror)) * mirror)
+/**
+ * Vector.reflect(mirror): return a reflected vector on the mirror normal.
+ * <pre>
+ * vec - ((2 * dot(vec, mirror)) * mirror)
+ * </pre>
*/
PyDoc_STRVAR(Vector_reflect_doc,
".. method:: reflect(mirror)\n"
@@ -1644,13 +1654,16 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2)
* multiplication */
-/* COLUMN VECTOR Multiplication (Matrix X Vector)
+/**
+ * column vector multiplication (Matrix * Vector)
+ * <pre>
* [1][4][7] [a]
* [2][5][8] * [b]
* [3][6][9] [c]
+ * </pre>
*
- * note: vector/matrix multiplication IS NOT COMMUTATIVE!!!!
- * note: assume read callbacks have been done first.
+ * \note Vector/Matrix multiplication is not commutative.
+ * \note Assume read callbacks have been done first.
*/
int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, MatrixObject *mat)
{
@@ -2199,9 +2212,67 @@ static PyObject *Vector_length_squared_get(VectorObject *self, void *UNUSED(clos
return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->size));
}
-/* Get a new Vector according to the provided swizzle. This function has little
- * error checking, as we are in control of the inputs: the closure is set by us
- * in Vector_createSwizzleGetSeter. */
+
+/**
+ * Python script used to make swizzle array:
+ *
+ * \code{.py}
+ * SWIZZLE_BITS_PER_AXIS = 3
+ * SWIZZLE_VALID_AXIS = 0x4
+ *
+ * axis_dict = {}
+ * axis_pos = {'x': 0, 'y': 1, 'z': 2, 'w': 3}
+ * axises = 'xyzw'
+ * while len(axises) >= 2:
+ * for axis_0 in axises:
+ * axis_0_pos = axis_pos[axis_0]
+ * for axis_1 in axises:
+ * axis_1_pos = axis_pos[axis_1]
+ * axis_dict[axis_0 + axis_1] = (
+ * '((%s | SWIZZLE_VALID_AXIS) | '
+ * '((%s | SWIZZLE_VALID_AXIS) << SWIZZLE_BITS_PER_AXIS))' %
+ * (axis_0_pos, axis_1_pos))
+ * if len(axises) > 2:
+ * for axis_2 in axises:
+ * axis_2_pos = axis_pos[axis_2]
+ * axis_dict[axis_0 + axis_1 + axis_2] = (
+ * '((%s | SWIZZLE_VALID_AXIS) | '
+ * '((%s | SWIZZLE_VALID_AXIS) << SWIZZLE_BITS_PER_AXIS) | '
+ * '((%s | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)))' %
+ * (axis_0_pos, axis_1_pos, axis_2_pos))
+ * if len(axises) > 3:
+ * for axis_3 in axises:
+ * axis_3_pos = axis_pos[axis_3]
+ * axis_dict[axis_0 + axis_1 + axis_2 + axis_3] = (
+ * '((%s | SWIZZLE_VALID_AXIS) | '
+ * '((%s | SWIZZLE_VALID_AXIS) << SWIZZLE_BITS_PER_AXIS) | '
+ * '((%s | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)) | '
+ * '((%s | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 3))) ' %
+ * (axis_0_pos, axis_1_pos, axis_2_pos, axis_3_pos))
+ *
+ * axises = axises[:-1]
+ *
+ *
+ * items = list(axis_dict.items())
+ * items.sort(key=lambda a: a[0].replace('x', '0').replace('y', '1').replace('z', '2').replace('w', '3'))
+ *
+ * unique = set()
+ * for key, val in items:
+ * num = eval(val)
+ * set_str = 'Vector_swizzle_set' if (len(set(key)) == len(key)) else 'NULL'
+ * key_args = ', '.join(["'%s'" % c for c in key.upper()])
+ * print('\t{(char *)"%s", %s(getter)Vector_swizzle_get, (setter)%s, NULL, SWIZZLE%d(%s)},' %
+ * (key, (' ' * (4 - len(key))), set_str, len(key), key_args))
+ * unique.add(num)
+ *
+ * if len(unique) != len(items):
+ * print("ERROR, duplicate values found")
+ * \endcode
+ */
+
+/**
+ * Get a new Vector according to the provided swizzle bits.
+ */
static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
{
size_t axis_to;
@@ -2232,7 +2303,8 @@ static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
return Vector_CreatePyObject(vec, axis_to, Py_TYPE(self));
}
-/* Set the items of this vector using a swizzle.
+/**
+ * Set the items of this vector using a swizzle.
* - If value is a vector or list this operates like an array copy, except that
* the destination is effectively re-ordered as defined by the swizzle. At
* most min(len(source), len(dest)) values will be copied.
@@ -2240,8 +2312,8 @@ static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
* - If an axis appears more than once in the swizzle, the final occurrence is
* the one that determines its value.
*
- * Returns 0 on success and -1 on failure. On failure, the vector will be
- * unchanged. */
+ * \return 0 on success and -1 on failure. On failure, the vector will be unchanged.
+ */
static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure)
{
size_t size_from;
@@ -2324,19 +2396,15 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure
return 0;
}
-/* XYZW -> 0123 */
-#define AXIS_FROM_CHAR(a) (((a) != 'W') ? ((a) - 'X') : 3)
-
-#define _VA_SWIZZLE_1(a) ( \
- ((AXIS_FROM_CHAR(a) | SWIZZLE_VALID_AXIS)))
-#define _VA_SWIZZLE_2(a, b) (_VA_SWIZZLE_1(a) | \
- ((AXIS_FROM_CHAR(b) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS)))
-#define _VA_SWIZZLE_3(a, b, c) (_VA_SWIZZLE_2(a, b) | \
- ((AXIS_FROM_CHAR(c) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)))
-#define _VA_SWIZZLE_4(a, b, c, d) (_VA_SWIZZLE_3(a, b, c) | \
- ((AXIS_FROM_CHAR(d) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 3)))
+#define _SWIZZLE1(a) ((a) | SWIZZLE_VALID_AXIS)
+#define _SWIZZLE2(a, b) (_SWIZZLE1(a) | (((b) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS)))
+#define _SWIZZLE3(a, b, c) (_SWIZZLE2(a, b) | (((c) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)))
+#define _SWIZZLE4(a, b, c, d) (_SWIZZLE3(a, b, c) | (((d) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 3)))
-#define SWIZZLE(...) SET_INT_IN_POINTER(VA_NARGS_CALL_OVERLOAD(_VA_SWIZZLE_, __VA_ARGS__))
+#define SWIZZLE1(a) SET_INT_IN_POINTER(_SWIZZLE1(a))
+#define SWIZZLE2(a, b) SET_INT_IN_POINTER(_SWIZZLE2(a, b))
+#define SWIZZLE3(a, b, c) SET_INT_IN_POINTER(_SWIZZLE3(a, b, c))
+#define SWIZZLE4(a, b, c, d) SET_INT_IN_POINTER(_SWIZZLE4(a, b, c, d))
/*****************************************************************************/
/* Python attributes get/set structure: */
@@ -2353,416 +2421,366 @@ static PyGetSetDef Vector_getseters[] = {
{(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
- /* autogenerated swizzle attrs, see python script below */
- {(char *)"xx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X')},
- {(char *)"xxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'X')},
- {(char *)"xxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'X', 'X')},
- {(char *)"xxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'X', 'Y')},
- {(char *)"xxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'X', 'Z')},
- {(char *)"xxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'X', 'W')},
- {(char *)"xxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Y')},
- {(char *)"xxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Y', 'X')},
- {(char *)"xxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Y', 'Y')},
- {(char *)"xxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Y', 'Z')},
- {(char *)"xxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Y', 'W')},
- {(char *)"xxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Z')},
- {(char *)"xxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Z', 'X')},
- {(char *)"xxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Z', 'Y')},
- {(char *)"xxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Z', 'Z')},
- {(char *)"xxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'Z', 'W')},
- {(char *)"xxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'W')},
- {(char *)"xxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'W', 'X')},
- {(char *)"xxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'W', 'Y')},
- {(char *)"xxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'W', 'Z')},
- {(char *)"xxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'X', 'W', 'W')},
- {(char *)"xy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Y')},
- {(char *)"xyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'X')},
- {(char *)"xyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'X', 'X')},
- {(char *)"xyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'X', 'Y')},
- {(char *)"xyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'X', 'Z')},
- {(char *)"xyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'X', 'W')},
- {(char *)"xyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'Y')},
- {(char *)"xyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'Y', 'X')},
- {(char *)"xyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'Y', 'Y')},
- {(char *)"xyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'Y', 'Z')},
- {(char *)"xyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'Y', 'W')},
- {(char *)"xyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Y', 'Z')},
- {(char *)"xyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'Z', 'X')},
- {(char *)"xyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'Z', 'Y')},
- {(char *)"xyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'Z', 'Z')},
- {(char *)"xyzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Y', 'Z', 'W')},
- {(char *)"xyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Y', 'W')},
- {(char *)"xywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'W', 'X')},
- {(char *)"xywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'W', 'Y')},
- {(char *)"xywz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Y', 'W', 'Z')},
- {(char *)"xyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Y', 'W', 'W')},
- {(char *)"xz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Z')},
- {(char *)"xzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'X')},
- {(char *)"xzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'X', 'X')},
- {(char *)"xzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'X', 'Y')},
- {(char *)"xzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'X', 'Z')},
- {(char *)"xzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'X', 'W')},
- {(char *)"xzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Z', 'Y')},
- {(char *)"xzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'Y', 'X')},
- {(char *)"xzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'Y', 'Y')},
- {(char *)"xzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'Y', 'Z')},
- {(char *)"xzyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Z', 'Y', 'W')},
- {(char *)"xzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'Z')},
- {(char *)"xzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'Z', 'X')},
- {(char *)"xzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'Z', 'Y')},
- {(char *)"xzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'Z', 'Z')},
- {(char *)"xzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'Z', 'W')},
- {(char *)"xzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Z', 'W')},
- {(char *)"xzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'W', 'X')},
- {(char *)"xzwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'Z', 'W', 'Y')},
- {(char *)"xzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'W', 'Z')},
- {(char *)"xzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'Z', 'W', 'W')},
- {(char *)"xw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'W')},
- {(char *)"xwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'X')},
- {(char *)"xwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'X', 'X')},
- {(char *)"xwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'X', 'Y')},
- {(char *)"xwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'X', 'Z')},
- {(char *)"xwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'X', 'W')},
- {(char *)"xwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'W', 'Y')},
- {(char *)"xwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'Y', 'X')},
- {(char *)"xwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'Y', 'Y')},
- {(char *)"xwyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'W', 'Y', 'Z')},
- {(char *)"xwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'Y', 'W')},
- {(char *)"xwz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'W', 'Z')},
- {(char *)"xwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'Z', 'X')},
- {(char *)"xwzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('X', 'W', 'Z', 'Y')},
- {(char *)"xwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'Z', 'Z')},
- {(char *)"xwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'Z', 'W')},
- {(char *)"xww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'W')},
- {(char *)"xwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'W', 'X')},
- {(char *)"xwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'W', 'Y')},
- {(char *)"xwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'W', 'Z')},
- {(char *)"xwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('X', 'W', 'W', 'W')},
- {(char *)"yx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'X')},
- {(char *)"yxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'X')},
- {(char *)"yxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'X', 'X')},
- {(char *)"yxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'X', 'Y')},
- {(char *)"yxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'X', 'Z')},
- {(char *)"yxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'X', 'W')},
- {(char *)"yxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'Y')},
- {(char *)"yxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'Y', 'X')},
- {(char *)"yxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'Y', 'Y')},
- {(char *)"yxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'Y', 'Z')},
- {(char *)"yxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'Y', 'W')},
- {(char *)"yxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'X', 'Z')},
- {(char *)"yxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'Z', 'X')},
- {(char *)"yxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'Z', 'Y')},
- {(char *)"yxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'Z', 'Z')},
- {(char *)"yxzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'X', 'Z', 'W')},
- {(char *)"yxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'X', 'W')},
- {(char *)"yxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'W', 'X')},
- {(char *)"yxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'W', 'Y')},
- {(char *)"yxwz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'X', 'W', 'Z')},
- {(char *)"yxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'X', 'W', 'W')},
- {(char *)"yy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y')},
- {(char *)"yyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'X')},
- {(char *)"yyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'X', 'X')},
- {(char *)"yyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'X', 'Y')},
- {(char *)"yyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'X', 'Z')},
- {(char *)"yyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'X', 'W')},
- {(char *)"yyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Y')},
- {(char *)"yyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Y', 'X')},
- {(char *)"yyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Y', 'Y')},
- {(char *)"yyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Y', 'Z')},
- {(char *)"yyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Y', 'W')},
- {(char *)"yyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Z')},
- {(char *)"yyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Z', 'X')},
- {(char *)"yyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Z', 'Y')},
- {(char *)"yyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Z', 'Z')},
- {(char *)"yyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'Z', 'W')},
- {(char *)"yyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'W')},
- {(char *)"yywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'W', 'X')},
- {(char *)"yywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'W', 'Y')},
- {(char *)"yywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'W', 'Z')},
- {(char *)"yyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Y', 'W', 'W')},
- {(char *)"yz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'Z')},
- {(char *)"yzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'Z', 'X')},
- {(char *)"yzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'X', 'X')},
- {(char *)"yzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'X', 'Y')},
- {(char *)"yzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'X', 'Z')},
- {(char *)"yzxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'Z', 'X', 'W')},
- {(char *)"yzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Y')},
- {(char *)"yzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Y', 'X')},
- {(char *)"yzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Y', 'Y')},
- {(char *)"yzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Y', 'Z')},
- {(char *)"yzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Y', 'W')},
- {(char *)"yzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Z')},
- {(char *)"yzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Z', 'X')},
- {(char *)"yzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Z', 'Y')},
- {(char *)"yzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Z', 'Z')},
- {(char *)"yzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'Z', 'W')},
- {(char *)"yzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'Z', 'W')},
- {(char *)"yzwx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'Z', 'W', 'X')},
- {(char *)"yzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'W', 'Y')},
- {(char *)"yzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'W', 'Z')},
- {(char *)"yzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'Z', 'W', 'W')},
- {(char *)"yw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'W')},
- {(char *)"ywx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'W', 'X')},
- {(char *)"ywxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'X', 'X')},
- {(char *)"ywxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'X', 'Y')},
- {(char *)"ywxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'W', 'X', 'Z')},
- {(char *)"ywxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'X', 'W')},
- {(char *)"ywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'Y')},
- {(char *)"ywyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'Y', 'X')},
- {(char *)"ywyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'Y', 'Y')},
- {(char *)"ywyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'Y', 'Z')},
- {(char *)"ywyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'Y', 'W')},
- {(char *)"ywz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'W', 'Z')},
- {(char *)"ywzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Y', 'W', 'Z', 'X')},
- {(char *)"ywzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'Z', 'Y')},
- {(char *)"ywzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'Z', 'Z')},
- {(char *)"ywzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'Z', 'W')},
- {(char *)"yww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'W')},
- {(char *)"ywwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'W', 'X')},
- {(char *)"ywwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'W', 'Y')},
- {(char *)"ywwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'W', 'Z')},
- {(char *)"ywww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Y', 'W', 'W', 'W')},
- {(char *)"zx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'X')},
- {(char *)"zxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'X')},
- {(char *)"zxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'X', 'X')},
- {(char *)"zxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'X', 'Y')},
- {(char *)"zxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'X', 'Z')},
- {(char *)"zxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'X', 'W')},
- {(char *)"zxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'X', 'Y')},
- {(char *)"zxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'Y', 'X')},
- {(char *)"zxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'Y', 'Y')},
- {(char *)"zxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'Y', 'Z')},
- {(char *)"zxyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'X', 'Y', 'W')},
- {(char *)"zxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'Z')},
- {(char *)"zxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'Z', 'X')},
- {(char *)"zxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'Z', 'Y')},
- {(char *)"zxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'Z', 'Z')},
- {(char *)"zxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'Z', 'W')},
- {(char *)"zxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'X', 'W')},
- {(char *)"zxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'W', 'X')},
- {(char *)"zxwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'X', 'W', 'Y')},
- {(char *)"zxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'W', 'Z')},
- {(char *)"zxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'X', 'W', 'W')},
- {(char *)"zy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'Y')},
- {(char *)"zyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'Y', 'X')},
- {(char *)"zyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'X', 'X')},
- {(char *)"zyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'X', 'Y')},
- {(char *)"zyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'X', 'Z')},
- {(char *)"zyxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'Y', 'X', 'W')},
- {(char *)"zyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Y')},
- {(char *)"zyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Y', 'X')},
- {(char *)"zyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Y', 'Y')},
- {(char *)"zyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Y', 'Z')},
- {(char *)"zyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Y', 'W')},
- {(char *)"zyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Z')},
- {(char *)"zyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Z', 'X')},
- {(char *)"zyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Z', 'Y')},
- {(char *)"zyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Z', 'Z')},
- {(char *)"zyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'Z', 'W')},
- {(char *)"zyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'Y', 'W')},
- {(char *)"zywx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'Y', 'W', 'X')},
- {(char *)"zywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'W', 'Y')},
- {(char *)"zywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'W', 'Z')},
- {(char *)"zyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Y', 'W', 'W')},
- {(char *)"zz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z')},
- {(char *)"zzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'X')},
- {(char *)"zzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'X', 'X')},
- {(char *)"zzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'X', 'Y')},
- {(char *)"zzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'X', 'Z')},
- {(char *)"zzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'X', 'W')},
- {(char *)"zzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Y')},
- {(char *)"zzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Y', 'X')},
- {(char *)"zzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Y', 'Y')},
- {(char *)"zzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Y', 'Z')},
- {(char *)"zzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Y', 'W')},
- {(char *)"zzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Z')},
- {(char *)"zzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Z', 'X')},
- {(char *)"zzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Z', 'Y')},
- {(char *)"zzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Z', 'Z')},
- {(char *)"zzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'Z', 'W')},
- {(char *)"zzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'W')},
- {(char *)"zzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'W', 'X')},
- {(char *)"zzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'W', 'Y')},
- {(char *)"zzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'W', 'Z')},
- {(char *)"zzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'Z', 'W', 'W')},
- {(char *)"zw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'W')},
- {(char *)"zwx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'W', 'X')},
- {(char *)"zwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'X', 'X')},
- {(char *)"zwxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'W', 'X', 'Y')},
- {(char *)"zwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'X', 'Z')},
- {(char *)"zwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'X', 'W')},
- {(char *)"zwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'W', 'Y')},
- {(char *)"zwyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('Z', 'W', 'Y', 'X')},
- {(char *)"zwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'Y', 'Y')},
- {(char *)"zwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'Y', 'Z')},
- {(char *)"zwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'Y', 'W')},
- {(char *)"zwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'Z')},
- {(char *)"zwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'Z', 'X')},
- {(char *)"zwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'Z', 'Y')},
- {(char *)"zwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'Z', 'Z')},
- {(char *)"zwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'Z', 'W')},
- {(char *)"zww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'W')},
- {(char *)"zwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'W', 'X')},
- {(char *)"zwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'W', 'Y')},
- {(char *)"zwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'W', 'Z')},
- {(char *)"zwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('Z', 'W', 'W', 'W')},
- {(char *)"wx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'X')},
- {(char *)"wxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'X')},
- {(char *)"wxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'X', 'X')},
- {(char *)"wxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'X', 'Y')},
- {(char *)"wxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'X', 'Z')},
- {(char *)"wxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'X', 'W')},
- {(char *)"wxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'X', 'Y')},
- {(char *)"wxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'Y', 'X')},
- {(char *)"wxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'Y', 'Y')},
- {(char *)"wxyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'X', 'Y', 'Z')},
- {(char *)"wxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'Y', 'W')},
- {(char *)"wxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'X', 'Z')},
- {(char *)"wxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'Z', 'X')},
- {(char *)"wxzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'X', 'Z', 'Y')},
- {(char *)"wxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'Z', 'Z')},
- {(char *)"wxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'Z', 'W')},
- {(char *)"wxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'W')},
- {(char *)"wxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'W', 'X')},
- {(char *)"wxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'W', 'Y')},
- {(char *)"wxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'W', 'Z')},
- {(char *)"wxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'X', 'W', 'W')},
- {(char *)"wy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Y')},
- {(char *)"wyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Y', 'X')},
- {(char *)"wyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'X', 'X')},
- {(char *)"wyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'X', 'Y')},
- {(char *)"wyxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Y', 'X', 'Z')},
- {(char *)"wyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'X', 'W')},
- {(char *)"wyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'Y')},
- {(char *)"wyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'Y', 'X')},
- {(char *)"wyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'Y', 'Y')},
- {(char *)"wyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'Y', 'Z')},
- {(char *)"wyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'Y', 'W')},
- {(char *)"wyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Y', 'Z')},
- {(char *)"wyzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Y', 'Z', 'X')},
- {(char *)"wyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'Z', 'Y')},
- {(char *)"wyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'Z', 'Z')},
- {(char *)"wyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'Z', 'W')},
- {(char *)"wyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'W')},
- {(char *)"wywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'W', 'X')},
- {(char *)"wywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'W', 'Y')},
- {(char *)"wywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'W', 'Z')},
- {(char *)"wyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Y', 'W', 'W')},
- {(char *)"wz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Z')},
- {(char *)"wzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Z', 'X')},
- {(char *)"wzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'X', 'X')},
- {(char *)"wzxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Z', 'X', 'Y')},
- {(char *)"wzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'X', 'Z')},
- {(char *)"wzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'X', 'W')},
- {(char *)"wzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Z', 'Y')},
- {(char *)"wzyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE('W', 'Z', 'Y', 'X')},
- {(char *)"wzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'Y', 'Y')},
- {(char *)"wzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'Y', 'Z')},
- {(char *)"wzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'Y', 'W')},
- {(char *)"wzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'Z')},
- {(char *)"wzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'Z', 'X')},
- {(char *)"wzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'Z', 'Y')},
- {(char *)"wzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'Z', 'Z')},
- {(char *)"wzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'Z', 'W')},
- {(char *)"wzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'W')},
- {(char *)"wzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'W', 'X')},
- {(char *)"wzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'W', 'Y')},
- {(char *)"wzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'W', 'Z')},
- {(char *)"wzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'Z', 'W', 'W')},
- {(char *)"ww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W')},
- {(char *)"wwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'X')},
- {(char *)"wwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'X', 'X')},
- {(char *)"wwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'X', 'Y')},
- {(char *)"wwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'X', 'Z')},
- {(char *)"wwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'X', 'W')},
- {(char *)"wwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Y')},
- {(char *)"wwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Y', 'X')},
- {(char *)"wwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Y', 'Y')},
- {(char *)"wwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Y', 'Z')},
- {(char *)"wwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Y', 'W')},
- {(char *)"wwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Z')},
- {(char *)"wwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Z', 'X')},
- {(char *)"wwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Z', 'Y')},
- {(char *)"wwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Z', 'Z')},
- {(char *)"wwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'Z', 'W')},
- {(char *)"www", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'W')},
- {(char *)"wwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'W', 'X')},
- {(char *)"wwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'W', 'Y')},
- {(char *)"wwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'W', 'Z')},
- {(char *)"wwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE('W', 'W', 'W', 'W')},
+ /* autogenerated swizzle attrs, see Python script above */
+ {(char *)"xx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(0, 0)},
+ {(char *)"xxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 0)},
+ {(char *)"xxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 0)},
+ {(char *)"xxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 1)},
+ {(char *)"xxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 2)},
+ {(char *)"xxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 3)},
+ {(char *)"xxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 1)},
+ {(char *)"xxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 0)},
+ {(char *)"xxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 1)},
+ {(char *)"xxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 2)},
+ {(char *)"xxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 3)},
+ {(char *)"xxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 2)},
+ {(char *)"xxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 0)},
+ {(char *)"xxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 1)},
+ {(char *)"xxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 2)},
+ {(char *)"xxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 3)},
+ {(char *)"xxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 3)},
+ {(char *)"xxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 0)},
+ {(char *)"xxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 1)},
+ {(char *)"xxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 2)},
+ {(char *)"xxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 3)},
+ {(char *)"xy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 1)},
+ {(char *)"xyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 0)},
+ {(char *)"xyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 0)},
+ {(char *)"xyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 1)},
+ {(char *)"xyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 2)},
+ {(char *)"xyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 3)},
+ {(char *)"xyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 1)},
+ {(char *)"xyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 0)},
+ {(char *)"xyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 1)},
+ {(char *)"xyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 2)},
+ {(char *)"xyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 3)},
+ {(char *)"xyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 1, 2)},
+ {(char *)"xyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 0)},
+ {(char *)"xyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 1)},
+ {(char *)"xyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 2)},
+ {(char *)"xyzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 1, 2, 3)},
+ {(char *)"xyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 1, 3)},
+ {(char *)"xywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 0)},
+ {(char *)"xywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 1)},
+ {(char *)"xywz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 1, 3, 2)},
+ {(char *)"xyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 3)},
+ {(char *)"xz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 2)},
+ {(char *)"xzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 0)},
+ {(char *)"xzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 0)},
+ {(char *)"xzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 1)},
+ {(char *)"xzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 2)},
+ {(char *)"xzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 3)},
+ {(char *)"xzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 2, 1)},
+ {(char *)"xzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 0)},
+ {(char *)"xzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 1)},
+ {(char *)"xzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 2)},
+ {(char *)"xzyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 2, 1, 3)},
+ {(char *)"xzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 2)},
+ {(char *)"xzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 0)},
+ {(char *)"xzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 1)},
+ {(char *)"xzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 2)},
+ {(char *)"xzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 3)},
+ {(char *)"xzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 2, 3)},
+ {(char *)"xzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 0)},
+ {(char *)"xzwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 2, 3, 1)},
+ {(char *)"xzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 2)},
+ {(char *)"xzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 3)},
+ {(char *)"xw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 3)},
+ {(char *)"xwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 0)},
+ {(char *)"xwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 0)},
+ {(char *)"xwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 1)},
+ {(char *)"xwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 2)},
+ {(char *)"xwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 3)},
+ {(char *)"xwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 3, 1)},
+ {(char *)"xwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 0)},
+ {(char *)"xwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 1)},
+ {(char *)"xwyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 3, 1, 2)},
+ {(char *)"xwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 3)},
+ {(char *)"xwz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 3, 2)},
+ {(char *)"xwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 0)},
+ {(char *)"xwzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 3, 2, 1)},
+ {(char *)"xwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 2)},
+ {(char *)"xwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 3)},
+ {(char *)"xww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 3)},
+ {(char *)"xwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 0)},
+ {(char *)"xwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 1)},
+ {(char *)"xwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 2)},
+ {(char *)"xwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 3)},
+ {(char *)"yx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 0)},
+ {(char *)"yxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 0)},
+ {(char *)"yxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 0)},
+ {(char *)"yxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 1)},
+ {(char *)"yxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 2)},
+ {(char *)"yxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 3)},
+ {(char *)"yxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 1)},
+ {(char *)"yxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 0)},
+ {(char *)"yxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 1)},
+ {(char *)"yxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 2)},
+ {(char *)"yxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 3)},
+ {(char *)"yxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 0, 2)},
+ {(char *)"yxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 0)},
+ {(char *)"yxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 1)},
+ {(char *)"yxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 2)},
+ {(char *)"yxzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 0, 2, 3)},
+ {(char *)"yxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 0, 3)},
+ {(char *)"yxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 0)},
+ {(char *)"yxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 1)},
+ {(char *)"yxwz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 0, 3, 2)},
+ {(char *)"yxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 3)},
+ {(char *)"yy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(1, 1)},
+ {(char *)"yyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 0)},
+ {(char *)"yyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 0)},
+ {(char *)"yyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 1)},
+ {(char *)"yyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 2)},
+ {(char *)"yyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 3)},
+ {(char *)"yyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 1)},
+ {(char *)"yyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 0)},
+ {(char *)"yyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 1)},
+ {(char *)"yyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 2)},
+ {(char *)"yyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 3)},
+ {(char *)"yyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 2)},
+ {(char *)"yyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 0)},
+ {(char *)"yyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 1)},
+ {(char *)"yyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 2)},
+ {(char *)"yyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 3)},
+ {(char *)"yyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 3)},
+ {(char *)"yywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 0)},
+ {(char *)"yywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 1)},
+ {(char *)"yywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 2)},
+ {(char *)"yyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 3)},
+ {(char *)"yz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 2)},
+ {(char *)"yzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 2, 0)},
+ {(char *)"yzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 0)},
+ {(char *)"yzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 1)},
+ {(char *)"yzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 2)},
+ {(char *)"yzxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 2, 0, 3)},
+ {(char *)"yzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 1)},
+ {(char *)"yzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 0)},
+ {(char *)"yzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 1)},
+ {(char *)"yzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 2)},
+ {(char *)"yzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 3)},
+ {(char *)"yzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 2)},
+ {(char *)"yzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 0)},
+ {(char *)"yzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 1)},
+ {(char *)"yzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 2)},
+ {(char *)"yzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 3)},
+ {(char *)"yzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 2, 3)},
+ {(char *)"yzwx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 2, 3, 0)},
+ {(char *)"yzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 1)},
+ {(char *)"yzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 2)},
+ {(char *)"yzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 3)},
+ {(char *)"yw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 3)},
+ {(char *)"ywx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 3, 0)},
+ {(char *)"ywxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 0)},
+ {(char *)"ywxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 1)},
+ {(char *)"ywxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 3, 0, 2)},
+ {(char *)"ywxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 3)},
+ {(char *)"ywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 1)},
+ {(char *)"ywyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 0)},
+ {(char *)"ywyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 1)},
+ {(char *)"ywyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 2)},
+ {(char *)"ywyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 3)},
+ {(char *)"ywz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 3, 2)},
+ {(char *)"ywzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 3, 2, 0)},
+ {(char *)"ywzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 1)},
+ {(char *)"ywzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 2)},
+ {(char *)"ywzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 3)},
+ {(char *)"yww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 3)},
+ {(char *)"ywwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 0)},
+ {(char *)"ywwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 1)},
+ {(char *)"ywwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 2)},
+ {(char *)"ywww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 3)},
+ {(char *)"zx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 0)},
+ {(char *)"zxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 0)},
+ {(char *)"zxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 0)},
+ {(char *)"zxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 1)},
+ {(char *)"zxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 2)},
+ {(char *)"zxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 3)},
+ {(char *)"zxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 0, 1)},
+ {(char *)"zxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 0)},
+ {(char *)"zxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 1)},
+ {(char *)"zxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 2)},
+ {(char *)"zxyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 0, 1, 3)},
+ {(char *)"zxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 2)},
+ {(char *)"zxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 0)},
+ {(char *)"zxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 1)},
+ {(char *)"zxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 2)},
+ {(char *)"zxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 3)},
+ {(char *)"zxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 0, 3)},
+ {(char *)"zxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 0)},
+ {(char *)"zxwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 0, 3, 1)},
+ {(char *)"zxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 2)},
+ {(char *)"zxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 3)},
+ {(char *)"zy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 1)},
+ {(char *)"zyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 1, 0)},
+ {(char *)"zyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 0)},
+ {(char *)"zyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 1)},
+ {(char *)"zyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 2)},
+ {(char *)"zyxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 1, 0, 3)},
+ {(char *)"zyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 1)},
+ {(char *)"zyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 0)},
+ {(char *)"zyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 1)},
+ {(char *)"zyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 2)},
+ {(char *)"zyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 3)},
+ {(char *)"zyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 2)},
+ {(char *)"zyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 0)},
+ {(char *)"zyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 1)},
+ {(char *)"zyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 2)},
+ {(char *)"zyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 3)},
+ {(char *)"zyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 1, 3)},
+ {(char *)"zywx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 1, 3, 0)},
+ {(char *)"zywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 1)},
+ {(char *)"zywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 2)},
+ {(char *)"zyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 3)},
+ {(char *)"zz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(2, 2)},
+ {(char *)"zzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 0)},
+ {(char *)"zzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 0)},
+ {(char *)"zzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 1)},
+ {(char *)"zzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 2)},
+ {(char *)"zzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 3)},
+ {(char *)"zzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 1)},
+ {(char *)"zzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 0)},
+ {(char *)"zzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 1)},
+ {(char *)"zzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 2)},
+ {(char *)"zzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 3)},
+ {(char *)"zzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 2)},
+ {(char *)"zzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 0)},
+ {(char *)"zzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 1)},
+ {(char *)"zzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 2)},
+ {(char *)"zzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 3)},
+ {(char *)"zzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 3)},
+ {(char *)"zzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 0)},
+ {(char *)"zzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 1)},
+ {(char *)"zzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 2)},
+ {(char *)"zzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 3)},
+ {(char *)"zw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 3)},
+ {(char *)"zwx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 3, 0)},
+ {(char *)"zwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 0)},
+ {(char *)"zwxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 3, 0, 1)},
+ {(char *)"zwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 2)},
+ {(char *)"zwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 3)},
+ {(char *)"zwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 3, 1)},
+ {(char *)"zwyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 3, 1, 0)},
+ {(char *)"zwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 1)},
+ {(char *)"zwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 2)},
+ {(char *)"zwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 3)},
+ {(char *)"zwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 2)},
+ {(char *)"zwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 0)},
+ {(char *)"zwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 1)},
+ {(char *)"zwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 2)},
+ {(char *)"zwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 3)},
+ {(char *)"zww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 3)},
+ {(char *)"zwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 0)},
+ {(char *)"zwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 1)},
+ {(char *)"zwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 2)},
+ {(char *)"zwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 3)},
+ {(char *)"wx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 0)},
+ {(char *)"wxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 0)},
+ {(char *)"wxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 0)},
+ {(char *)"wxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 1)},
+ {(char *)"wxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 2)},
+ {(char *)"wxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 3)},
+ {(char *)"wxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 0, 1)},
+ {(char *)"wxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 0)},
+ {(char *)"wxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 1)},
+ {(char *)"wxyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 0, 1, 2)},
+ {(char *)"wxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 3)},
+ {(char *)"wxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 0, 2)},
+ {(char *)"wxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 0)},
+ {(char *)"wxzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 0, 2, 1)},
+ {(char *)"wxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 2)},
+ {(char *)"wxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 3)},
+ {(char *)"wxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 3)},
+ {(char *)"wxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 0)},
+ {(char *)"wxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 1)},
+ {(char *)"wxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 2)},
+ {(char *)"wxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 3)},
+ {(char *)"wy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 1)},
+ {(char *)"wyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 1, 0)},
+ {(char *)"wyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 0)},
+ {(char *)"wyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 1)},
+ {(char *)"wyxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 1, 0, 2)},
+ {(char *)"wyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 3)},
+ {(char *)"wyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 1)},
+ {(char *)"wyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 0)},
+ {(char *)"wyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 1)},
+ {(char *)"wyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 2)},
+ {(char *)"wyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 3)},
+ {(char *)"wyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 1, 2)},
+ {(char *)"wyzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 1, 2, 0)},
+ {(char *)"wyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 1)},
+ {(char *)"wyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 2)},
+ {(char *)"wyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 3)},
+ {(char *)"wyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 3)},
+ {(char *)"wywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 0)},
+ {(char *)"wywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 1)},
+ {(char *)"wywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 2)},
+ {(char *)"wyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 3)},
+ {(char *)"wz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 2)},
+ {(char *)"wzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 2, 0)},
+ {(char *)"wzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 0)},
+ {(char *)"wzxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 2, 0, 1)},
+ {(char *)"wzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 2)},
+ {(char *)"wzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 3)},
+ {(char *)"wzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 2, 1)},
+ {(char *)"wzyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 2, 1, 0)},
+ {(char *)"wzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 1)},
+ {(char *)"wzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 2)},
+ {(char *)"wzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 3)},
+ {(char *)"wzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 2)},
+ {(char *)"wzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 0)},
+ {(char *)"wzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 1)},
+ {(char *)"wzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 2)},
+ {(char *)"wzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 3)},
+ {(char *)"wzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 3)},
+ {(char *)"wzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 0)},
+ {(char *)"wzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 1)},
+ {(char *)"wzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 2)},
+ {(char *)"wzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 3)},
+ {(char *)"ww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(3, 3)},
+ {(char *)"wwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 0)},
+ {(char *)"wwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 0)},
+ {(char *)"wwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 1)},
+ {(char *)"wwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 2)},
+ {(char *)"wwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 3)},
+ {(char *)"wwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 1)},
+ {(char *)"wwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 0)},
+ {(char *)"wwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 1)},
+ {(char *)"wwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 2)},
+ {(char *)"wwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 3)},
+ {(char *)"wwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 2)},
+ {(char *)"wwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 0)},
+ {(char *)"wwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 1)},
+ {(char *)"wwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 2)},
+ {(char *)"wwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 3)},
+ {(char *)"www", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 3)},
+ {(char *)"wwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 0)},
+ {(char *)"wwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 1)},
+ {(char *)"wwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 2)},
+ {(char *)"wwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 3)},
#undef AXIS_FROM_CHAR
-#undef SWIZZLE
-#undef _VA_SWIZZLE_1
-#undef _VA_SWIZZLE_2
-#undef _VA_SWIZZLE_3
-#undef _VA_SWIZZLE_4
+#undef SWIZZLE1
+#undef SWIZZLE2
+#undef SWIZZLE3
+#undef SWIZZLE4
+#undef _SWIZZLE1
+#undef _SWIZZLE2
+#undef _SWIZZLE3
+#undef _SWIZZLE4
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
/**
- * Python script used to make swizzle array:
- *
- * \code{.py}
- * SWIZZLE_BITS_PER_AXIS = 3
- * SWIZZLE_VALID_AXIS = 0x4
- *
- * axis_dict = {}
- * axis_pos = {'x': 0, 'y': 1, 'z': 2, 'w': 3}
- * axises = 'xyzw'
- * while len(axises) >= 2:
- * for axis_0 in axises:
- * axis_0_pos = axis_pos[axis_0]
- * for axis_1 in axises:
- * axis_1_pos = axis_pos[axis_1]
- * axis_dict[axis_0 + axis_1] = (
- * '((%s | SWIZZLE_VALID_AXIS) | '
- * '((%s | SWIZZLE_VALID_AXIS) << SWIZZLE_BITS_PER_AXIS))' %
- * (axis_0_pos, axis_1_pos))
- * if len(axises) > 2:
- * for axis_2 in axises:
- * axis_2_pos = axis_pos[axis_2]
- * axis_dict[axis_0 + axis_1 + axis_2] = (
- * '((%s | SWIZZLE_VALID_AXIS) | '
- * '((%s | SWIZZLE_VALID_AXIS) << SWIZZLE_BITS_PER_AXIS) | '
- * '((%s | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)))' %
- * (axis_0_pos, axis_1_pos, axis_2_pos))
- * if len(axises) > 3:
- * for axis_3 in axises:
- * axis_3_pos = axis_pos[axis_3]
- * axis_dict[axis_0 + axis_1 + axis_2 + axis_3] = (
- * '((%s | SWIZZLE_VALID_AXIS) | '
- * '((%s | SWIZZLE_VALID_AXIS) << SWIZZLE_BITS_PER_AXIS) | '
- * '((%s | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)) | '
- * '((%s | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 3))) ' %
- * (axis_0_pos, axis_1_pos, axis_2_pos, axis_3_pos))
- *
- * axises = axises[:-1]
- *
- *
- * items = list(axis_dict.items())
- * items.sort(key=lambda a: a[0].replace('x', '0').replace('y', '1').replace('z', '2').replace('w', '3'))
- *
- * unique = set()
- * for key, val in items:
- * num = eval(val)
- * set_str = 'Vector_swizzle_set' if (len(set(key)) == len(key)) else 'NULL'
- * key_args = ', '.join(["'%s'" % c for c in key.upper()])
- * print('\t{(char *)"%s", %s(getter)Vector_swizzle_get, (setter)%s, NULL, SWIZZLE(%s)},' %
- * (key, (' ' * (4 - len(key))), set_str, key_args))
- * unique.add(num)
- *
- * if len(unique) != len(items):
- * print("ERROR, duplicate values found")
- * \endcode
- */
-
-/* ROW VECTOR Multiplication - Vector X Matrix
+ * Row vector multiplication - (Vector * Matrix)
+ * <pre>
* [x][y][z] * [1][4][7]
* [2][5][8]
* [3][6][9]
- * vector/matrix multiplication IS NOT COMMUTATIVE!!!! */
+ * </pre>
+ * \note vector/matrix multiplication is not commutative.
+ */
static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, MatrixObject *mat)
{
float vec_cpy[MAX_DIMENSIONS];
@@ -2863,10 +2881,11 @@ static struct PyMethodDef Vector_methods[] = {
};
-/* Note
- * Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing
- * but this means for eg that
- * (vec * mat) and (mat * vec) both get sent to Vector_mul and it needs to sort out the order
+/**
+ * Note:
+ * #Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing
+ * but this means for eg that (vec * mat) and (mat * vec)
+ * both get sent to Vector_mul and it needs to sort out the order
*/
PyDoc_STRVAR(vector_doc,
@@ -3010,6 +3029,11 @@ PyObject *Vector_CreatePyObject(
return (PyObject *)self;
}
+/**
+ * Create a vector that wraps existing memory.
+ *
+ * \param vec: Use this vector in-place.
+ */
PyObject *Vector_CreatePyObject_wrap(
float *vec, const int size,
PyTypeObject *base_type)
@@ -3036,6 +3060,10 @@ PyObject *Vector_CreatePyObject_wrap(
return (PyObject *) self;
}
+/**
+ * Create a vector where the value is defined by registered callbacks,
+ * see: #Mathutils_RegisterCallback
+ */
PyObject *Vector_CreatePyObject_cb(
PyObject *cb_user, int size,
unsigned char cb_type, unsigned char cb_subtype)
@@ -3052,6 +3080,9 @@ PyObject *Vector_CreatePyObject_cb(
return (PyObject *)self;
}
+/**
+ * \param vec: Initialized vector value to use in-place, allocated with: PyMem_Malloc
+ */
PyObject *Vector_CreatePyObject_alloc(
float *vec, const int size,
PyTypeObject *base_type)
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 1eb8644a9a6..42771d93b4e 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -761,7 +761,7 @@ static PyObject *C_BVHTree_FromPolygons(PyObject *UNUSED(cls), PyObject *args, P
py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast);
for (j = 0; j < 3; j++) {
- tri[j] = (unsigned int)_PyLong_AsInt(py_tricoords_fast_items[j]);
+ tri[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]);
if (UNLIKELY(tri[j] >= (unsigned int)coords_len)) {
PyErr_Format(PyExc_ValueError,
"%s: index %d must be less than %d",
@@ -812,7 +812,7 @@ static PyObject *C_BVHTree_FromPolygons(PyObject *UNUSED(cls), PyObject *args, P
p_plink_prev = &plink->next;
for (j = 0; j < py_tricoords_len; j++) {
- plink->poly[j] = (unsigned int)_PyLong_AsInt(py_tricoords_fast_items[j]);
+ plink->poly[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]);
if (UNLIKELY(plink->poly[j] >= (unsigned int)coords_len)) {
PyErr_Format(PyExc_ValueError,
"%s: index %d must be less than %d",
@@ -1156,7 +1156,6 @@ static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyO
/* Get data for tessellation */
{
- DM_ensure_looptri(dm);
lt = dm->getLoopTriArray(dm);
tris_len = (unsigned int)dm->getNumLoopTri(dm);
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 868e4b38408..1dc18dbe509 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -1279,7 +1279,7 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject
index = 0;
dl_face = dl->index;
while (index < dl->parts) {
- PyList_SET_ITEM(tri_list, index, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2]));
+ PyList_SET_ITEM(tri_list, index, PyC_Tuple_Pack_I32(dl_face[0], dl_face[1], dl_face[2]));
dl_face += 3;
index++;
}
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index f0323340899..f9942bef61f 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -335,7 +335,7 @@ typedef struct ObjectRen {
char (*mcol)[MAX_CUSTOMDATA_LAYER_NAME];
int actmtface, actmcol, bakemtface;
- char tangent_mask; /* which tangent layer should be calculated */
+ short tangent_mask; /* which tangent layer should be calculated */
float obmat[4][4]; /* only used in convertblender.c, for instancing */
diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h
index 13f16ce0bd7..3ef6e9d7476 100644
--- a/source/blender/render/intern/include/shading.h
+++ b/source/blender/render/intern/include/shading.h
@@ -57,7 +57,7 @@ typedef struct ShadeSample {
void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr);
void shade_input_set_triangle_i(struct ShadeInput *shi, struct ObjectInstanceRen *obi, struct VlakRen *vlr, short i1, short i2, short i3);
-void shade_input_set_triangle(struct ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip);
+void shade_input_set_triangle(struct ShadeInput *shi, int obi, int facenr, int normal_flip);
void shade_input_copy_triangle(struct ShadeInput *shi, struct ShadeInput *from);
void shade_input_calc_viewco(struct ShadeInput *shi, float x, float y, float z, float view[3], float dxyview[2], float co[3], float dxco[3], float dyco[3]);
void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float sx, float sy, float z);
diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
index 81e41a20f2e..103fa3e6034 100644
--- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
@@ -59,6 +59,7 @@ static void rtbuild_init(RTBuilder *b)
b->primitives.begin = NULL;
b->primitives.end = NULL;
b->primitives.maxsize = 0;
+ b->depth = 0;
for (int i = 0; i < RTBUILD_MAX_CHILDS; i++)
b->child_offset[i] = 0;
@@ -178,6 +179,8 @@ RTBuilder *rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp)
{
rtbuild_init(tmp);
+ tmp->depth = b->depth + 1;
+
for (int i = 0; i < 3; i++)
if (b->sorted_begin[i]) {
tmp->sorted_begin[i] = b->sorted_begin[i] + b->child_offset[child];
@@ -336,6 +339,15 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds)
int baxis = -1, boffset = 0;
if (size > nchilds) {
+ if (b->depth > RTBUILD_MAX_SAH_DEPTH) {
+ // for degenerate cases we avoid running out of stack space
+ // by simply splitting the children in the middle
+ b->child_offset[0] = 0;
+ b->child_offset[1] = (size+1)/2;
+ b->child_offset[2] = size;
+ return 2;
+ }
+
float bcost = FLT_MAX;
baxis = -1;
boffset = size / 2;
diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.h b/source/blender/render/intern/raytrace/rayobject_rtbuild.h
index 9e296da144b..83042ef3d7e 100644
--- a/source/blender/render/intern/raytrace/rayobject_rtbuild.h
+++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.h
@@ -49,7 +49,8 @@ extern "C" {
* generate with simple calls, and then convert to the theirs
* specific structure on the fly.
*/
-#define RTBUILD_MAX_CHILDS 32
+#define RTBUILD_MAX_CHILDS 32
+#define RTBUILD_MAX_SAH_DEPTH 256
typedef struct RTBuilder {
@@ -79,6 +80,8 @@ typedef struct RTBuilder {
float bb[6];
+ /* current depth */
+ int depth;
} RTBuilder;
/* used during creation */
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index 73424a4e846..588c327ab91 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -684,6 +684,10 @@ void RE_bake_pixels_populate(
int mat_nr = mp->mat_nr;
int image_id = bake_images->lookup[mat_nr];
+ if (image_id < 0) {
+ continue;
+ }
+
bd.bk_image = &bake_images->data[image_id];
bd.primitive_id = ++p_id;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 41ff8e046e7..9633d95855e 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -3439,10 +3439,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if (need_nmap_tangent_concrete || need_tangent) {
int uv_start = CustomData_get_layer_index(&dm->faceData, CD_MTFACE);
int uv_index = CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, layer->name);
- BLI_assert(uv_start >= 0 && uv_index >= 0);
- if ((uv_start < 0 || uv_index < 0))
- continue;
- int n = uv_index - uv_start;
+
+ /* if there are no UVs, orco tangents are in first slot */
+ int n = (uv_start >= 0 && uv_index >= 0) ? uv_index - uv_start : 0;
const float *tangent = (const float *) layer->data;
float *ftang = RE_vlakren_get_nmap_tangent(obr, vlr, n, true);
@@ -4658,14 +4657,22 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
index= (dob)? dob->persistent_id[0]: 0;
+ /* It seems that we may generate psys->renderdata recursively in some nasty intricated cases of
+ * several levels of bupliobject (see T51524).
+ * For now, basic rule is, do not restore psys if it was already in 'render state'.
+ * Another, more robust solution could be to add some reference counting to that renderdata... */
+ bool psys_has_renderdata = false;
+
/* the emitter has to be processed first (render levels of modifiers) */
/* so here we only check if the emitter should be rendered */
if (ob->particlesystem.first) {
show_emitter= 0;
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
show_emitter += psys->part->draw & PART_DRAW_EMITTER;
- if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
+ if (!(re->r.scemode & R_VIEWPORT_PREVIEW)) {
+ psys_has_renderdata |= (psys->renderdata != NULL);
psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
+ }
}
/* if no psys has "show emitter" selected don't render emitter */
@@ -4701,12 +4708,6 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
if (ob->particlesystem.first) {
psysindex= 1;
for (psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) {
- /* It seems that we may generate psys->renderdata recursively in some nasty intricated cases of
- * several levels of bupliobject (see T51524).
- * For now, basic rule is, do not restore psys if it was already in 'render state'.
- * Another, more robust solution could be to add some reference counting to that renderdata... */
- const bool psys_has_renderdata = (psys->renderdata != NULL);
-
if (!psys_check_enabled(ob, psys, G.is_rendering))
continue;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 929eae495cf..e078365e1ed 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -723,6 +723,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
re->r.size = source->r.size;
}
+ re_init_resolution(re, source, winx, winy, disprect);
+
/* disable border if it's a full render anyway */
if (re->r.border.xmin == 0.0f && re->r.border.xmax == 1.0f &&
re->r.border.ymin == 0.0f && re->r.border.ymax == 1.0f)
@@ -730,8 +732,6 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
re->r.mode &= ~R_BORDER;
}
- re_init_resolution(re, source, winx, winy, disprect);
-
if (re->rectx < 1 || re->recty < 1 || (BKE_imtype_is_movie(rd->im_format.imtype) &&
(re->rectx < 16 || re->recty < 16) ))
{
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 59c7ea85c1d..77f399d08d1 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -464,48 +464,48 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
float *fp, *col= NULL;
int pixsize= 3;
- if(STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx);
}
- else if(STREQ(rpass->name, RE_PASSNAME_Z)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
fp = rpass->rect + offset;
*fp = shr->z;
}
- else if(STREQ(rpass->name, RE_PASSNAME_RGBA)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) {
col = shr->col;
pixsize = 4;
}
- else if(STREQ(rpass->name, RE_PASSNAME_EMIT)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) {
col = shr->emit;
}
- else if(STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
col = shr->diff;
}
- else if(STREQ(rpass->name, RE_PASSNAME_SPEC)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) {
col = shr->spec;
}
- else if(STREQ(rpass->name, RE_PASSNAME_SHADOW)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) {
col = shr->shad;
}
- else if(STREQ(rpass->name, RE_PASSNAME_AO)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_AO)) {
col = shr->ao;
}
- else if(STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) {
col = shr->env;
}
- else if(STREQ(rpass->name, RE_PASSNAME_INDIRECT)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) {
col = shr->indirect;
}
- else if(STREQ(rpass->name, RE_PASSNAME_REFLECT)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) {
col = shr->refl;
}
- else if(STREQ(rpass->name, RE_PASSNAME_REFRACT)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) {
col = shr->refr;
}
- else if(STREQ(rpass->name, RE_PASSNAME_NORMAL)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) {
col = shr->nor;
}
- else if(STREQ(rpass->name, RE_PASSNAME_UV)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_UV)) {
/* box filter only, gauss will screwup UV too much */
if (shi->totuv) {
float mult = (float)count_mask(curmask)/(float)R.osa;
@@ -515,7 +515,7 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
fp[2]+= mult;
}
}
- else if(STREQ(rpass->name, RE_PASSNAME_INDEXOB)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) {
/* no filter */
if (shi->vlr) {
fp = rpass->rect + offset;
@@ -523,7 +523,7 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
*fp = (float)shi->obr->ob->index;
}
}
- else if(STREQ(rpass->name, RE_PASSNAME_INDEXMA)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) {
/* no filter */
if (shi->vlr) {
fp = rpass->rect + offset;
@@ -531,12 +531,12 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
*fp = (float)shi->mat->index;
}
}
- else if(STREQ(rpass->name, RE_PASSNAME_MIST)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_MIST)) {
/* */
col = &shr->mist;
pixsize = 1;
}
- else if(STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
/* add minimum speed in pixel, no filter */
fp = rpass->rect + 4*offset;
if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
@@ -548,7 +548,7 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
fp[3] = shr->winspeed[3];
}
}
- else if(STREQ(rpass->name, RE_PASSNAME_RAYHITS)) {
+ else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) {
/* */
col = shr->rayhits;
pixsize= 4;
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 20602314526..b4ff5f52fcf 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -292,12 +292,8 @@ void shade_input_set_triangle_i(ShadeInput *shi, ObjectInstanceRen *obi, VlakRen
}
}
-/* note, facenr declared volatile due to over-eager -O2 optimization's
- * on cygwin (particularly -frerun-cse-after-loop)
- */
-
/* copy data from face to ShadeInput, scanline case */
-void shade_input_set_triangle(ShadeInput *shi, volatile int obi, volatile int facenr, int UNUSED(normal_flip))
+void shade_input_set_triangle(ShadeInput *shi, int obi, int facenr, int UNUSED(normal_flip))
{
if (facenr > 0) {
shi->obi = &R.objectinstance[obi];
diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c
index d4e53eb7305..f0cf29e98ca 100644
--- a/source/blender/render/intern/source/sunsky.c
+++ b/source/blender/render/intern/source/sunsky.c
@@ -398,7 +398,7 @@ void InitAtmosphere(struct SunSky *sunSky, float sun_intens, float mief, float r
vLambda2[0] = fLambda2[0];
vLambda2[1] = fLambda2[1];
vLambda2[2] = fLambda2[2];
-
+
vLambda4[0] = fLambda4[0];
vLambda4[1] = fLambda4[1];
vLambda4[2] = fLambda4[2];
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index e497ec1a870..68707f163af 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -1601,7 +1601,6 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
* Note: uses globals.
* \param v1 start coordinate s
* \param v2 target coordinate t
- * \param b1
* \param b2
* \param b3
* \param a index for coordinate (x, y, or z)
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 492dec2cc10..7c1c388bcba 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -103,6 +103,7 @@ enum {
struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect);
struct wmWindow *WM_window_open_temp(struct bContext *C, int x, int y, int sizex, int sizey, int type);
+void WM_window_set_dpi(wmWindow *win);
/* returns true if draw method is triple buffer */
bool WM_is_draw_triple(struct wmWindow *win);
@@ -186,8 +187,9 @@ struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase
/* mouse */
void WM_event_add_mousemove(struct bContext *C);
-bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
+bool WM_event_is_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
bool WM_event_is_absolute(const struct wmEvent *event);
+bool WM_event_is_last_mousemove(const struct wmEvent *event);
#ifdef WITH_INPUT_NDOF
/* 3D mouse */
@@ -352,6 +354,7 @@ bool WM_operator_pystring_abbreviate(char *str, int str_len_max);
char *WM_prop_pystring_assign(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
void WM_operator_bl_idname(char *to, const char *from);
void WM_operator_py_idname(char *to, const char *from);
+bool WM_operator_py_idname_ok_or_report(struct ReportList *reports, const char *classname, const char *idname);
/* *************** uilist types ******************** */
void WM_uilisttype_init(void);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index d0522fdd7d4..a09cc4aeb31 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -430,7 +430,7 @@ void wm_clear_default_size(bContext *C)
/* on startup, it adds all data, for matching */
void wm_add_default(bContext *C)
{
- wmWindowManager *wm = BKE_libblock_alloc(CTX_data_main(C), ID_WM, "WinMan");
+ wmWindowManager *wm = BKE_libblock_alloc(CTX_data_main(C), ID_WM, "WinMan", 0);
wmWindow *win;
bScreen *screen = CTX_wm_screen(C); /* XXX from file read hrmf */
@@ -483,19 +483,22 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
void wm_close_and_free_all(bContext *C, ListBase *wmlist)
{
- Main *bmain = CTX_data_main(C);
wmWindowManager *wm;
-
+
while ((wm = wmlist->first)) {
wm_close_and_free(C, wm);
BLI_remlink(wmlist, wm);
- BKE_libblock_free_data(bmain, &wm->id, true);
+ BKE_libblock_free_data(&wm->id, true);
MEM_freeN(wm);
}
}
void WM_main(bContext *C)
{
+ /* Single refresh before handling events.
+ * This ensures we don't run operators before the depsgraph has been evaluated. */
+ wm_event_do_refresh_wm_and_depsgraph(C);
+
while (1) {
/* get events from ghost, handle window events, add to window queues */
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 77ffa46b990..25c6980f58e 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -926,15 +926,14 @@ void wm_draw_update(bContext *C)
for (win = wm->windows.first; win; win = win->next) {
#ifdef WIN32
- if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
- GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
-
- if (state == GHOST_kWindowStateMinimized) {
- /* do not update minimized windows, it gives issues on intel drivers (see [#33223])
- * anyway, it seems logical to skip update for invisible windows
- */
- continue;
- }
+ GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
+
+ if (state == GHOST_kWindowStateMinimized) {
+ /* do not update minimized windows, gives issues on Intel (see T33223)
+ * and AMD (see T50856). it seems logical to skip update for invisible
+ * window anyway.
+ */
+ continue;
}
#endif
if (win->drawmethod != U.wmdrawmethod) {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index f26ee0e73ec..7e7314cc0c8 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -263,13 +263,56 @@ static void wm_notifier_clear(wmNotifier *note)
memset(((char *)note) + sizeof(Link), 0, sizeof(*note) - sizeof(Link));
}
+/**
+ * Was part of #wm_event_do_notifiers, split out so it can be called once before entering the #WM_main loop.
+ * This ensures operators don't run before the UI and depsgraph are initialized.
+ */
+void wm_event_do_refresh_wm_and_depsgraph(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ uint64_t win_combine_v3d_datamask = 0;
+
+ /* combine datamasks so 1 win doesn't disable UV's in another [#26448] */
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ win_combine_v3d_datamask |= ED_view3d_screen_datamask(win->screen);
+ }
+
+ /* cached: editor refresh callbacks now, they get context */
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ ScrArea *sa;
+
+ CTX_wm_window_set(C, win);
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (sa->do_refresh) {
+ CTX_wm_area_set(C, sa);
+ ED_area_do_refresh(C, sa);
+ }
+ }
+
+ /* XXX make lock in future, or separated derivedmesh users in scene */
+ if (G.is_rendering == false) {
+ /* depsgraph & animation: update tagged datablocks */
+ Main *bmain = CTX_data_main(C);
+
+ /* copied to set's in scene_update_tagged_recursive() */
+ win->screen->scene->customdata_mask = win_combine_v3d_datamask;
+
+ /* XXX, hack so operators can enforce datamasks [#26482], gl render */
+ win->screen->scene->customdata_mask |= win->screen->scene->customdata_mask_modal;
+
+ BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
+ }
+ }
+
+ CTX_wm_window_set(C, NULL);
+}
+
/* called in mainloop */
void wm_event_do_notifiers(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmNotifier *note, *next;
wmWindow *win;
- uint64_t win_combine_v3d_datamask = 0;
if (wm == NULL)
return;
@@ -373,39 +416,7 @@ void wm_event_do_notifiers(bContext *C)
MEM_freeN(note);
}
- /* combine datamasks so 1 win doesn't disable UV's in another [#26448] */
- for (win = wm->windows.first; win; win = win->next) {
- win_combine_v3d_datamask |= ED_view3d_screen_datamask(win->screen);
- }
-
- /* cached: editor refresh callbacks now, they get context */
- for (win = wm->windows.first; win; win = win->next) {
- ScrArea *sa;
-
- CTX_wm_window_set(C, win);
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (sa->do_refresh) {
- CTX_wm_area_set(C, sa);
- ED_area_do_refresh(C, sa);
- }
- }
-
- /* XXX make lock in future, or separated derivedmesh users in scene */
- if (G.is_rendering == false) {
- /* depsgraph & animation: update tagged datablocks */
- Main *bmain = CTX_data_main(C);
-
- /* copied to set's in scene_update_tagged_recursive() */
- win->screen->scene->customdata_mask = win_combine_v3d_datamask;
-
- /* XXX, hack so operators can enforce datamasks [#26482], gl render */
- win->screen->scene->customdata_mask |= win->screen->scene->customdata_mask_modal;
-
- BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
- }
- }
-
- CTX_wm_window_set(C, NULL);
+ wm_event_do_refresh_wm_and_depsgraph(C);
}
static int wm_event_always_pass(const wmEvent *event)
@@ -615,6 +626,16 @@ bool WM_event_is_absolute(const wmEvent *event)
return (event->tablet_data != NULL);
}
+bool WM_event_is_last_mousemove(const wmEvent *event)
+{
+ while ((event = event->next)) {
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ return false;
+ }
+ }
+ return true;
+}
+
#ifdef WITH_INPUT_NDOF
void WM_ndof_deadzone_set(float deadzone)
{
@@ -1079,6 +1100,9 @@ bool WM_operator_last_properties_store(wmOperator *UNUSED(op))
#endif
+/**
+ * Also used for exec when 'event' is NULL.
+ */
static int wm_operator_invoke(
bContext *C, wmOperatorType *ot, wmEvent *event,
PointerRNA *properties, ReportList *reports, const bool poll_only)
@@ -1094,7 +1118,9 @@ static int wm_operator_invoke(
wmOperator *op = wm_operator_create(wm, ot, properties, reports); /* if reports == NULL, they'll be initialized */
const bool is_nested_call = (wm->op_undo_depth != 0);
- op->flag |= OP_IS_INVOKE;
+ if (event != NULL) {
+ op->flag |= OP_IS_INVOKE;
+ }
/* initialize setting from previous run */
if (!is_nested_call) { /* not called by py script */
@@ -2852,7 +2878,7 @@ void WM_event_add_mousemove(bContext *C)
/* for modal callbacks, check configuration for how to interpret exit with tweaks */
-bool WM_modal_tweak_exit(const wmEvent *event, int tweak_event)
+bool WM_event_is_modal_tweak_exit(const wmEvent *event, int tweak_event)
{
/* if the release-confirm userpref setting is enabled,
* tweak events can be canceled when mouse is released
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 187c1193ec6..637ace9cd82 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -316,7 +316,7 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
}
/* in case UserDef was read, we re-initialize all, and do versioning */
-static void wm_init_userdef(bContext *C, const bool use_factory_settings)
+static void wm_init_userdef(bContext *C, const bool read_userdef_from_memory)
{
Main *bmain = CTX_data_main(C);
@@ -336,14 +336,12 @@ static void wm_init_userdef(bContext *C, const bool use_factory_settings)
}
/* avoid re-saving for every small change to our prefs, allow overrides */
- if (use_factory_settings) {
+ if (read_userdef_from_memory) {
BLO_update_defaults_userpref_blend();
}
/* update tempdir from user preferences */
BKE_tempdir_init(U.tempdir);
-
- BKE_blender_userdef_refresh();
}
@@ -451,7 +449,7 @@ void wm_file_read_report(bContext *C)
* Logic shared between #WM_file_read & #wm_homefile_read,
* updates to make after reading a file.
*/
-static void wm_file_read_post(bContext *C, bool is_startup_file)
+static void wm_file_read_post(bContext *C, const bool is_startup_file, const bool use_userdef)
{
bool addons_loaded = false;
wmWindowManager *wm = CTX_wm_manager(C);
@@ -470,13 +468,14 @@ static void wm_file_read_post(bContext *C, bool is_startup_file)
if (is_startup_file) {
/* possible python hasn't been initialized */
if (CTX_py_init_get(C)) {
- /* Only run when we have a template path found. */
- if (BKE_appdir_app_template_any()) {
- BPY_execute_string(C, "__import__('bl_app_template_utils').reset()");
+ if (use_userdef) {
+ /* Only run when we have a template path found. */
+ if (BKE_appdir_app_template_any()) {
+ BPY_execute_string(C, "__import__('bl_app_template_utils').reset()");
+ }
+ /* sync addons, these may have changed from the defaults */
+ BPY_execute_string(C, "__import__('addon_utils').reset_all()");
}
- /* sync addons, these may have changed from the defaults */
- BPY_execute_string(C, "__import__('addon_utils').reset_all()");
-
BPY_python_reset(C);
addons_loaded = true;
}
@@ -590,7 +589,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
}
- wm_file_read_post(C, false);
+ wm_file_read_post(C, false, false);
success = true;
}
@@ -638,13 +637,15 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
*
* \param use_factory_settings: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead.
* Used for "Restore Factory Settings".
+ * \param use_userdef: Load factory settings as well as startup file.
+ * Disabled for "File New" we don't want to reload preferences.
* \param filepath_startup_override: Optional path pointing to an alternative blend file (may be NULL).
* \param app_template_override: Template to use instead of the template defined in user-preferences.
* When not-null, this is written into the user preferences.
*/
int wm_homefile_read(
bContext *C, ReportList *reports,
- bool use_factory_settings, bool use_empty_data,
+ bool use_factory_settings, bool use_empty_data, bool use_userdef,
const char *filepath_startup_override, const char *app_template_override)
{
ListBase wmbase;
@@ -667,8 +668,8 @@ int wm_homefile_read(
*
* And in this case versioning code is to be run.
*/
- bool read_userdef_from_memory = true;
- eBLOReadSkip skip_flags = 0;
+ bool read_userdef_from_memory = false;
+ eBLOReadSkip skip_flags = use_userdef ? 0 : BLO_READ_SKIP_USERDEF;
/* options exclude eachother */
BLI_assert((use_factory_settings && filepath_startup_override) == 0);
@@ -695,7 +696,9 @@ int wm_homefile_read(
if (!use_factory_settings) {
if (cfgdir) {
BLI_path_join(filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL);
- BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ if (use_userdef) {
+ BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ }
}
else {
use_factory_settings = true;
@@ -707,15 +710,16 @@ int wm_homefile_read(
}
/* load preferences before startup.blend */
- if (!use_factory_settings && BLI_exists(filepath_userdef)) {
- UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL);
- if (userdef != NULL) {
- BKE_blender_userdef_set_data(userdef);
- MEM_freeN(userdef);
-
- read_userdef_from_memory = false;
- skip_flags |= BLO_READ_SKIP_USERDEF;
- printf("Read prefs: %s\n", filepath_userdef);
+ if (use_userdef) {
+ if (!use_factory_settings && BLI_exists(filepath_userdef)) {
+ UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL);
+ if (userdef != NULL) {
+ BKE_blender_userdef_set_data(userdef);
+ MEM_freeN(userdef);
+
+ skip_flags |= BLO_READ_SKIP_USERDEF;
+ printf("Read prefs: %s\n", filepath_userdef);
+ }
}
}
@@ -724,23 +728,23 @@ int wm_homefile_read(
if (filepath_startup_override != NULL) {
/* pass */
}
- else if (app_template_override && app_template_override[0]) {
+ else if (app_template_override) {
+ /* This may be clearing the current template by setting to an empty string. */
app_template = app_template_override;
}
else if (!use_factory_settings && U.app_template[0]) {
app_template = U.app_template;
}
- if (app_template != NULL) {
+ if ((app_template != NULL) && (app_template[0] != '\0')) {
BKE_appdir_app_template_id_search(app_template, app_template_system, sizeof(app_template_system));
- BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL);
- }
- /* insert template name into startup file */
- if (app_template != NULL) {
+ /* Insert template name into startup file. */
+
/* note that the path is being set even when 'use_factory_settings == true'
* this is done so we can load a templates factory-settings */
if (!use_factory_settings) {
+ BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL);
BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_config, BLENDER_STARTUP_FILE, NULL);
if (BLI_access(filepath_startup, R_OK) != 0) {
filepath_startup[0] = '\0';
@@ -775,6 +779,13 @@ int wm_homefile_read(
success = BKE_blendfile_read_from_memory(
C, datatoc_startup_blend, datatoc_startup_blend_size,
NULL, skip_flags, true);
+ if (success) {
+ if (use_userdef) {
+ if ((skip_flags & BLO_READ_SKIP_USERDEF) == 0) {
+ read_userdef_from_memory = true;
+ }
+ }
+ }
if (BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);
}
@@ -801,20 +812,23 @@ int wm_homefile_read(
BLI_path_join(temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL);
}
- UserDef *userdef_template = NULL;
- /* just avoids missing file warning */
- if (BLI_exists(temp_path)) {
- userdef_template = BKE_blendfile_userdef_read(temp_path, NULL);
- }
- if (userdef_template == NULL) {
- /* we need to have preferences load to overwrite preferences from previous template */
- userdef_template = BKE_blendfile_userdef_read_from_memory(
- datatoc_startup_blend, datatoc_startup_blend_size, NULL);
- }
- if (userdef_template) {
- BKE_blender_userdef_set_app_template(userdef_template);
- BKE_blender_userdef_free_data(userdef_template);
- MEM_freeN(userdef_template);
+ if (use_userdef) {
+ UserDef *userdef_template = NULL;
+ /* just avoids missing file warning */
+ if (BLI_exists(temp_path)) {
+ userdef_template = BKE_blendfile_userdef_read(temp_path, NULL);
+ }
+ if (userdef_template == NULL) {
+ /* we need to have preferences load to overwrite preferences from previous template */
+ userdef_template = BKE_blendfile_userdef_read_from_memory(
+ datatoc_startup_blend, datatoc_startup_blend_size, NULL);
+ read_userdef_from_memory = true;
+ }
+ if (userdef_template) {
+ BKE_blender_userdef_set_app_template(userdef_template);
+ BKE_blender_userdef_free_data(userdef_template);
+ MEM_freeN(userdef_template);
+ }
}
}
@@ -826,8 +840,10 @@ int wm_homefile_read(
* can remove this eventually, only in a 2.53 and older, now its not written */
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
- /* check userdef before open window, keymaps etc */
- wm_init_userdef(C, read_userdef_from_memory);
+ if (use_userdef) {
+ /* check userdef before open window, keymaps etc */
+ wm_init_userdef(C, read_userdef_from_memory);
+ }
/* match the read WM with current WM */
wm_window_match_do(C, &wmbase);
@@ -835,9 +851,11 @@ int wm_homefile_read(
G.main->name[0] = '\0';
- /* When loading factory settings, the reset solid OpenGL lights need to be applied. */
- if (!G.background) {
- GPU_default_lights();
+ if (use_userdef) {
+ /* When loading factory settings, the reset solid OpenGL lights need to be applied. */
+ if (!G.background) {
+ GPU_default_lights();
+ }
}
/* start with save preference untitled.blend */
@@ -845,7 +863,7 @@ int wm_homefile_read(
/* disable auto-play in startup.blend... */
G.fileflags &= ~G_FILE_AUTOPLAY;
- wm_file_read_post(C, true);
+ wm_file_read_post(C, true, use_userdef);
return true;
}
@@ -1093,7 +1111,7 @@ static int wm_file_write(bContext *C, const char *filepath, int fileflags, Repor
BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath);
return ret;
}
-
+
/* note: used to replace the file extension (to ensure '.blend'),
* no need to now because the operator ensures,
* its handy for scripts to save to a predefined name without blender editing it */
@@ -1527,6 +1545,7 @@ void WM_OT_read_history(wmOperatorType *ot)
static int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
+ bool use_userdef = false;
char filepath_buf[FILE_MAX];
const char *filepath = NULL;
@@ -1550,6 +1569,8 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
else {
/* always load UI for factory settings (prefs will re-init) */
G.fileflags &= ~G_FILE_NO_UI;
+ /* Always load preferences with factory settings. */
+ use_userdef = true;
}
char app_template_buf[sizeof(U.app_template)];
@@ -1561,17 +1582,15 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) {
RNA_property_string_get(op->ptr, prop_app_template, app_template_buf);
app_template = app_template_buf;
- }
- else if (!use_factory_settings) {
- /* TODO: dont reset prefs on 'New File' */
- BLI_strncpy(app_template_buf, U.app_template, sizeof(app_template_buf));
- app_template = app_template_buf;
+
+ /* Always load preferences when switching templates. */
+ use_userdef = true;
}
else {
app_template = NULL;
}
- if (wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, filepath, app_template)) {
+ if (wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, use_userdef, filepath, app_template)) {
if (use_splash) {
WM_init_splash(C);
}
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index 3b733f9558c..f19c999a4f1 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -608,7 +608,8 @@ static void lib_relocate_do(
}
/* Note that in reload case, we also want to replace indirect usages. */
- const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
+ const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE |
+ (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) {
WMLinkAppendDataItem *item = itemlink->link;
ID *old_id = item->customdata;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 9bafe72d805..e73ec2b081a 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -181,18 +181,15 @@ void WM_init(bContext *C, int argc, const char **argv)
ED_file_init(); /* for fsmenu */
ED_node_init_butfuncs();
- BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */
+ BLF_init(); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */
BLT_lang_init();
- /* Enforce loading the UI for the initial homefile */
- G.fileflags &= ~G_FILE_NO_UI;
-
/* reports cant be initialized before the wm,
* but keep before file reading, since that may report errors */
wm_init_reports(C);
/* get the default database, plus a wm */
- wm_homefile_read(C, NULL, G.factory_startup, false, NULL, NULL);
+ wm_homefile_read(C, NULL, G.factory_startup, false, true, NULL, NULL);
BLT_lang_set(NULL);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index d3ebd3e4d2c..51c551cd9a5 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -177,7 +177,7 @@ void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
/* XXX All ops should have a description but for now allow them not to. */
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
}
@@ -193,7 +193,7 @@ void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *
ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
opfunc(ot, userdata);
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
}
@@ -398,7 +398,7 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam
ot->description = UNDOCUMENTED_OPERATOR_TIP;
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
/* Use i18n context from ext.srna if possible (py operators). */
i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : BLT_I18NCONTEXT_OPERATOR_DEFAULT;
RNA_def_struct_translation_context(ot->srna, i18n_context);
@@ -432,7 +432,7 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *),
opfunc(ot, userdata);
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
- RNA_def_struct_identifier(ot->srna, ot->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
}
@@ -573,6 +573,46 @@ void WM_operator_bl_idname(char *to, const char *from)
}
/**
+ * Sanity check to ensure #WM_operator_bl_idname won't fail.
+ * \returns true when there are no problems with \a idname, otherwise report an error.
+ */
+bool WM_operator_py_idname_ok_or_report(ReportList *reports, const char *classname, const char *idname)
+{
+ const char *ch = idname;
+ int dot = 0;
+ int i;
+ for (i = 0; *ch; i++, ch++) {
+ if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
+ /* pass */
+ }
+ else if (*ch == '.') {
+ dot++;
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR,
+ "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
+ classname, idname, i);
+ return false;
+ }
+ }
+
+ if (i > (MAX_NAME - 3)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', "
+ "is too long, maximum length is %d", classname, idname,
+ MAX_NAME - 3);
+ return false;
+ }
+
+ if (dot != 1) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
+ classname, idname);
+ return false;
+ }
+ return true;
+}
+
+/**
* Print a string representation of the operator, with the args that it runs so python can run it again.
*
* When calling from an existing wmOperator, better to use simple version:
@@ -806,9 +846,19 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert
} \
} (void)0
+#define CTX_TEST_SPACE_TYPE(space_data_type, member_full, dataptr_cmp) \
+ { \
+ const char *ctx_member_full = member_full; \
+ if (space_data->spacetype == space_data_type && ptr->data == dataptr_cmp) { \
+ member_id = ctx_member_full; \
+ break; \
+ } \
+ } (void)0
+
switch (GS(((ID *)ptr->id.data)->name)) {
case ID_SCE:
{
+ CTX_TEST_PTR_DATA_TYPE(C, "active_gpencil_brush", RNA_GPencilBrush, ptr, CTX_data_active_gpencil_brush(C));
CTX_TEST_PTR_ID(C, "scene", ptr->id.data);
break;
}
@@ -843,12 +893,22 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert
{
CTX_TEST_PTR_ID(C, "screen", ptr->id.data);
- CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_Space, ptr, CTX_wm_space_data(C));
+ SpaceLink *space_data = CTX_wm_space_data(C);
+
+ CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_Space, ptr, space_data);
CTX_TEST_PTR_DATA_TYPE(C, "area", RNA_Area, ptr, CTX_wm_area(C));
CTX_TEST_PTR_DATA_TYPE(C, "region", RNA_Region, ptr, CTX_wm_region(C));
+ CTX_TEST_SPACE_TYPE(SPACE_IMAGE, "space_data.uv_editor", space_data);
+ CTX_TEST_SPACE_TYPE(SPACE_VIEW3D, "space_data.fx_settings", &(CTX_wm_view3d(C)->fx_settings));
+ CTX_TEST_SPACE_TYPE(SPACE_NLA, "space_data.dopesheet", CTX_wm_space_nla(C)->ads);
+ CTX_TEST_SPACE_TYPE(SPACE_IPO, "space_data.dopesheet", CTX_wm_space_graph(C)->ads);
+ CTX_TEST_SPACE_TYPE(SPACE_ACTION, "space_data.dopesheet", &(CTX_wm_space_action(C)->ads));
+ CTX_TEST_SPACE_TYPE(SPACE_FILE, "space_data.params", CTX_wm_space_file(C)->params);
break;
}
+ default:
+ break;
}
if (member_id) {
@@ -860,6 +920,7 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert
}
#undef CTX_TEST_PTR_ID
#undef CTX_TEST_PTR_ID_CAST
+#undef CTX_TEST_SPACE_TYPE
}
return ret;
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 6bf7bcc2934..77378cf8e0c 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -1256,7 +1256,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
//GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
/* initialize the font */
- BLF_init(11, 72);
+ BLF_init();
ps.fontid = BLF_load_mem("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
BLF_size(ps.fontid, 11, 72);
@@ -1428,8 +1428,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
ps.next_frame = ps.direction;
-
- while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0)) || ps.wait2) {
+ while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, ps.wait2))) {
if (hasevent) {
GHOST_DispatchEvents(g_WS.ghost_system);
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index de169881bc4..9fe215f7712 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -375,9 +375,14 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
}
}
-static void wm_window_set_dpi(wmWindow *win)
+void WM_window_set_dpi(wmWindow *win)
{
- int auto_dpi = GHOST_GetDPIHint(win->ghostwin);
+ float auto_dpi = GHOST_GetDPIHint(win->ghostwin);
+
+ /* Clamp auto DPI to 96, since our font/interface drawing does not work well
+ * with lower sizes. The main case we are interested in supporting is higher
+ * DPI. If a smaller UI is desired it is still possible to adjust UI scale. */
+ auto_dpi = max_ff(auto_dpi, 96.0f);
/* Lazily init UI scale size, preserving backwards compatibility by
* computing UI scale from ratio of previous DPI and auto DPI */
@@ -397,17 +402,22 @@ static void wm_window_set_dpi(wmWindow *win)
/* Blender's UI drawing assumes DPI 72 as a good default following macOS
* while Windows and Linux use DPI 96. GHOST assumes a default 96 so we
* remap the DPI to Blender's convention. */
+ auto_dpi *= GHOST_GetNativePixelSize(win->ghostwin);
int dpi = auto_dpi * U.ui_scale * (72.0 / 96.0f);
/* Automatically set larger pixel size for high DPI. */
- int pixelsize = MAX2(1, dpi / 54);
+ int pixelsize = max_ii(1, (int)(dpi / 64));
+ /* User adjustment for pixel size. */
+ pixelsize = max_ii(1, pixelsize + U.ui_line_width);
/* Set user preferences globals for drawing, and for forward compatibility. */
- U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin) * pixelsize;
+ U.pixelsize = pixelsize;
U.dpi = dpi / pixelsize;
U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE;
+ U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72;
- BKE_blender_userdef_refresh();
+ /* update font drawing */
+ BLF_default_dpi(U.pixelsize * U.dpi);
}
/* belongs to below */
@@ -483,7 +493,7 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
}
/* needed here, because it's used before it reads userdef */
- wm_window_set_dpi(win);
+ WM_window_set_dpi(win);
wm_window_swap_buffers(win);
@@ -870,7 +880,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
GHOST_ActivateWindowDrawingContext(win->ghostwin);
/* this can change per window */
- wm_window_set_dpi(win);
+ WM_window_set_dpi(win);
}
}
@@ -1070,7 +1080,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
WM_jobs_stop(wm, win->screen, NULL);
}
- wm_window_set_dpi(win);
+ WM_window_set_dpi(win);
/* win32: gives undefined window size when minimized */
if (state != GHOST_kWindowStateMinimized) {
@@ -1157,11 +1167,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
case GHOST_kEventWindowDPIHintChanged:
{
- wm_window_set_dpi(win);
+ WM_window_set_dpi(win);
/* font's are stored at each DPI level, without this we can easy load 100's of fonts */
BLF_cache_clear();
- BKE_blender_userdef_refresh();
WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
break;
@@ -1247,7 +1256,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
{
// only update if the actual pixel size changes
float prev_pixelsize = U.pixelsize;
- wm_window_set_dpi(win);
+ WM_window_set_dpi(win);
if (U.pixelsize != prev_pixelsize) {
// close all popups since they are positioned with the pixel
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index efc01b1f8a8..3fb9cd617bf 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -87,7 +87,8 @@ void wm_event_do_handlers (bContext *C);
void wm_event_add_ghostevent (wmWindowManager *wm, wmWindow *win, int type, int time, void *customdata);
-void wm_event_do_notifiers (bContext *C);
+void wm_event_do_refresh_wm_and_depsgraph(bContext *C);
+void wm_event_do_notifiers(bContext *C);
/* wm_keymap.c */
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 9a1518e15b0..b102b6c7cc7 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -37,7 +37,7 @@ struct wmOperatorType;
void wm_history_file_read(void);
int wm_homefile_read(
struct bContext *C, struct ReportList *reports,
- bool use_factory_settings, bool use_empty_data,
+ bool use_factory_settings, bool use_empty_data, bool use_userdef,
const char *filepath_startup_override, const char *app_template_override);
void wm_file_read_report(bContext *C);
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 82a3527a655..8bc3f709551 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -355,7 +355,7 @@ int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struc
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference) RET_NONE
void WM_main_add_notifier(unsigned int type, void *reference) RET_NONE
void ED_armature_bone_rename(struct bArmature *arm, const char *oldnamep, const char *newnamep) RET_NONE
-void ED_armature_transform(struct bArmature *arm, float mat[4][4]) RET_NONE
+void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do_props) RET_NONE
struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op) RET_NULL
struct wmTimer *WM_event_add_timer(struct wmWindowManager *wm, struct wmWindow *win, int event_type, double timestep) RET_NULL
void WM_event_remove_timer(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer) RET_NONE
@@ -553,7 +553,6 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) RET_NONE
bool ED_transform_snap_object_project_ray_ex(
struct SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3], float *ray_depth,
/* return args */
@@ -700,6 +699,7 @@ void WM_operatortype_append_ptr(void (*opfunc)(struct wmOperatorType *, void *),
void WM_operatortype_append_macro_ptr(void (*opfunc)(struct wmOperatorType *, void *), void *userdata) RET_NONE
void WM_operator_bl_idname(char *to, const char *from) RET_NONE
void WM_operator_py_idname(char *to, const char *from) RET_NONE
+bool WM_operator_py_idname_ok_or_report(struct ReportList *reports, const char *classname, const char *idname) RET_ZERO
int WM_operator_ui_popup(struct bContext *C, struct wmOperator *op, int width, int height) RET_ZERO
void update_autoflags_fcurve(struct FCurve *fcu, struct bContext *C, struct ReportList *reports, struct PointerRNA *ptr) RET_NONE
short insert_keyframe(struct ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, char keytype, short flag) RET_ZERO
@@ -721,7 +721,9 @@ struct uiLayout *uiLayoutRadial(struct uiLayout *layout) RET_NULL
int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, const char *opname,
const char *propname, const struct wmEvent *event) RET_ZERO
-/* RNA COLLADA dependency */
+/* RNA COLLADA dependency */
+/* XXX (gaia) Why do we need this declaration here? */
+/* The collada header is included anyways further up... */
int collada_export(struct Scene *sce,
const char *filepath,
int apply_modifiers,
@@ -734,8 +736,7 @@ int collada_export(struct Scene *sce,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ BC_export_texture_type export_texture_type,
int use_texture_copies,
int triangulate,
@@ -750,7 +751,10 @@ int collada_export(struct Scene *sce,
void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE
/* bpy/python internal api */
-void operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
+extern void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata);
+extern void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata);
+void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
+void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
void BPY_text_free_code(struct Text *text) RET_NONE
void BPY_id_release(struct ID *id) RET_NONE
int BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result) RET_ZERO
@@ -758,7 +762,6 @@ void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTa
float BPY_driver_exec(PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime) RET_ZERO /* might need this one! */
void BPY_DECREF(void *pyob_ptr) RET_NONE
void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets) RET_NONE
-void macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) RET_ZERO
struct PyObject *pyrna_id_CreatePyObject(struct ID *id) RET_NULL
bool pyrna_id_CheckPyObject(struct PyObject *obj) RET_ZERO
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 8f26e248424..98a5a6ce644 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -845,6 +845,13 @@ elseif(APPLE)
PATTERN "__MACOSX" EXCLUDE
PATTERN ".DS_Store" EXCLUDE
PATTERN "config-${PYTHON_VERSION}m/*.a" EXCLUDE # static lib
+ PATTERN "lib2to3" EXCLUDE # ./lib2to3
+ PATTERN "tkinter" EXCLUDE # ./tkinter
+ PATTERN "lib-dynload/_tkinter.*" EXCLUDE # ./lib-dynload/_tkinter.co
+ PATTERN "idlelib" EXCLUDE # ./idlelib
+ PATTERN "test" EXCLUDE # ./test
+ PATTERN "turtledemo" EXCLUDE # ./turtledemo
+ PATTERN "turtle.py" EXCLUDE # ./turtle.py
)
endmacro()
@@ -908,41 +915,49 @@ elseif(APPLE)
# python
if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
- # the python zip is first extracted as part of the build process,
- # and then later installed as part of make install. this is much
- # quicker, and means we can easily exclude files on copy
- # Not needed for PYTHON_MODULE or WEB_PLUGIN due uses Pyhon framework
- # use a hash of the .zip path to handle switching between different
- # lib directories without needing a clean build
- string(SHA1 PYTHON_ZIP_HASH ${LIBDIR}/release/${PYTHON_ZIP})
- set(PYTHON_EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PYTHON_ZIP_HASH}/python)
-
- add_custom_target(
- extractpyzip
- DEPENDS ${PYTHON_EXTRACT_DIR})
-
- set(PYTHON_ZIP "python_${CMAKE_OSX_ARCHITECTURES}.zip")
-
- add_custom_command(
- OUTPUT ${PYTHON_EXTRACT_DIR}
- COMMAND ${CMAKE_COMMAND} -E remove_directory "${PYTHON_EXTRACT_DIR}/"
- COMMAND ${CMAKE_COMMAND} -E make_directory "${PYTHON_EXTRACT_DIR}/"
- COMMAND ${CMAKE_COMMAND} -E chdir "${PYTHON_EXTRACT_DIR}/"
- ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}"
- DEPENDS ${LIBDIR}/release/${PYTHON_ZIP})
-
- add_dependencies(blender extractpyzip)
-
- # copy extracted python files
- install_dir(
- ${PYTHON_EXTRACT_DIR}
- \${TARGETDIR_VER}
- )
- # copy site-packages files
- install_dir(
- ${LIBDIR}/release/site-packages
- \${TARGETDIR_VER}/python/lib/python${PYTHON_VERSION}
- )
+ if(WITH_CXX11)
+ # Copy the python libs into the install directory
+ install_dir(
+ ${PYTHON_LIBPATH}
+ ${TARGETDIR_VER}/python/lib
+ )
+ else()
+ # the python zip is first extracted as part of the build process,
+ # and then later installed as part of make install. this is much
+ # quicker, and means we can easily exclude files on copy
+ # Not needed for PYTHON_MODULE or WEB_PLUGIN due uses Pyhon framework
+ # use a hash of the .zip path to handle switching between different
+ # lib directories without needing a clean build
+ string(SHA1 PYTHON_ZIP_HASH ${LIBDIR}/release/${PYTHON_ZIP})
+ set(PYTHON_EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PYTHON_ZIP_HASH}/python)
+
+ add_custom_target(
+ extractpyzip
+ DEPENDS ${PYTHON_EXTRACT_DIR})
+
+ set(PYTHON_ZIP "python_${CMAKE_OSX_ARCHITECTURES}.zip")
+
+ add_custom_command(
+ OUTPUT ${PYTHON_EXTRACT_DIR}
+ COMMAND ${CMAKE_COMMAND} -E remove_directory "${PYTHON_EXTRACT_DIR}/"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${PYTHON_EXTRACT_DIR}/"
+ COMMAND ${CMAKE_COMMAND} -E chdir "${PYTHON_EXTRACT_DIR}/"
+ ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}"
+ DEPENDS ${LIBDIR}/release/${PYTHON_ZIP})
+
+ add_dependencies(blender extractpyzip)
+
+ # copy extracted python files
+ install_dir(
+ ${PYTHON_EXTRACT_DIR}
+ \${TARGETDIR_VER}
+ )
+ # copy site-packages files
+ install_dir(
+ ${LIBDIR}/release/site-packages
+ \${TARGETDIR_VER}/python/lib/python${PYTHON_VERSION}
+ )
+ endif()
install(DIRECTORY ${LIBDIR}/python/bin
DESTINATION ${TARGETDIR_VER}/python
@@ -997,19 +1012,27 @@ elseif(APPLE)
# python
if(WITH_PYTHON AND NOT WITH_PYTHON_FRAMEWORK)
- add_custom_command(
- OUTPUT ${PYTHON_EXTRACT_DIR}
- COMMAND ${CMAKE_COMMAND} -E remove_directory "${PYTHON_EXTRACT_DIR}/"
- COMMAND ${CMAKE_COMMAND} -E make_directory "${PYTHON_EXTRACT_DIR}/"
- COMMAND ${CMAKE_COMMAND} -E chdir "${PYTHON_EXTRACT_DIR}/"
- ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}"
- DEPENDS ${LIBDIR}/release/${PYTHON_ZIP})
-
- # copy extracted python files
- install_dir(
- ${PYTHON_EXTRACT_DIR}
- \${PLAYER_TARGETDIR_VER}
- )
+ if(WITH_CXX11)
+ # Copy the python libs into the install directory
+ install_dir(
+ ${PYTHON_LIBPATH}
+ ${PLAYER_TARGETDIR_VER}/python/lib
+ )
+ else()
+ add_custom_command(
+ OUTPUT ${PYTHON_EXTRACT_DIR}
+ COMMAND ${CMAKE_COMMAND} -E remove_directory "${PYTHON_EXTRACT_DIR}/"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${PYTHON_EXTRACT_DIR}/"
+ COMMAND ${CMAKE_COMMAND} -E chdir "${PYTHON_EXTRACT_DIR}/"
+ ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}"
+ DEPENDS ${LIBDIR}/release/${PYTHON_ZIP})
+
+ # copy extracted python files
+ install_dir(
+ ${PYTHON_EXTRACT_DIR}
+ \${PLAYER_TARGETDIR_VER}
+ )
+ endif()
endif()
endif()
diff --git a/source/gameengine/GameLogic/CMakeLists.txt b/source/gameengine/GameLogic/CMakeLists.txt
index 05071f59707..b9eec74f6f4 100644
--- a/source/gameengine/GameLogic/CMakeLists.txt
+++ b/source/gameengine/GameLogic/CMakeLists.txt
@@ -139,6 +139,9 @@ if(WITH_SDL)
if(WITH_GHOST_SDL)
add_definitions(-DWITH_GHOST_SDL)
endif()
+ if(WITH_SDL_DYNLOAD)
+ add_definitions(-DWITH_SDL_DYNLOAD)
+ endif()
endif()
blender_add_lib(ge_logic "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index 1a66b2aee52..9f532527a80 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -38,7 +38,11 @@
#include "BLI_path_util.h"
#ifdef WITH_SDL
-# define SDL_CHECK(x) ((x) != (void *)0)
+# ifdef WITH_SDL_DYNLOAD
+# define SDL_CHECK(x) ((x) != (void *)0)
+# else
+# define SDL_CHECK(x) true
+# endif
#endif
SCA_Joystick::SCA_Joystick(short int index)
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
index fd3d713b3d2..1dee1de9de2 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
@@ -82,9 +82,11 @@ void SCA_Joystick::HandleEvents(void)
{
SDL_Event sdl_event;
+#ifdef WITH_SDL_DYNLOAD
if (SDL_PollEvent == (void*)0) {
return;
}
+#endif
int i;
for (i=0; i<m_joynum; i++) { /* could use JOYINDEX_MAX but no reason to */
diff --git a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h
index 504df2376bb..24922197723 100644
--- a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h
+++ b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h
@@ -67,8 +67,6 @@ public:
* Call this routine to update the mouse device when a button state changes.
* \param button Which button state changes.
* \param isDown The new state of the button.
- * \param x Position x-coordinate of the cursor at the time of the state change.
- * \param y Position y-coordinate of the cursor at the time of the state change.
* \return Indication as to whether the event was processed.
*/
virtual bool ConvertButtonEvent(TButtonId button, bool isDown);
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index 0c206dfce3d..906e9d9a821 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -516,7 +516,7 @@ int main(
#endif
// Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
- BLF_init(11, U.dpi);
+ BLF_init();
BLT_lang_init();
BLT_lang_set("");
diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp
index 364f8d4bfc6..91e8e4fd42b 100644
--- a/source/gameengine/Ketsji/KX_FontObject.cpp
+++ b/source/gameengine/Ketsji/KX_FontObject.cpp
@@ -281,7 +281,7 @@ int KX_FontObject::pyattr_set_text(void *self_v, const KX_PYATTRIBUTE_DEF *attrd
KX_FontObject* self = static_cast<KX_FontObject*>(self_v);
if (!PyUnicode_Check(value))
return PY_SET_ATTR_FAIL;
- char* chars = _PyUnicode_AsString(value);
+ const char *chars = _PyUnicode_AsString(value);
/* Allow for some logic brick control */
CValue* tprop = self->GetProperty("Text");
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 822f2e054f8..d858097abef 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -124,7 +124,7 @@ void KX_SoundActuator::play()
AUD_Device_free(device);
// in case of pingpong, we have to free the sound
- if(sound != m_sound)
+ if (sound != m_sound)
AUD_Sound_free(sound);
if (m_handle != NULL) {
diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp
index 5717a1edbcb..b41a2095890 100644
--- a/source/gameengine/VideoTexture/FilterBase.cpp
+++ b/source/gameengine/VideoTexture/FilterBase.cpp
@@ -114,6 +114,7 @@ void Filter_dealloc(PyFilter *self)
delete self->m_filter;
self->m_filter = NULL;
}
+ Py_TYPE((PyObject *)self)->tp_free((PyObject *)self);
}
diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp
index b91a312a5d7..a547d2a7a85 100644
--- a/source/gameengine/VideoTexture/ImageBase.cpp
+++ b/source/gameengine/VideoTexture/ImageBase.cpp
@@ -427,6 +427,7 @@ void Image_dealloc(PyImage *self)
delete self->m_image;
self->m_image = NULL;
}
+ Py_TYPE((PyObject *)self)->tp_free((PyObject *)self);
}
// get image data
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index fa0b86a2637..64326f34377 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,7 +1,8 @@
# Python CTests
-add_subdirectory(python)
+if(WITH_BLENDER)
+ add_subdirectory(python)
+endif()
# GTest
add_subdirectory(gtests)
-
diff --git a/tests/check_deprecated.py b/tests/check_deprecated.py
index cf8f8e0cc35..6e07f8fdb31 100644
--- a/tests/check_deprecated.py
+++ b/tests/check_deprecated.py
@@ -53,10 +53,8 @@ def is_source_any(filename):
def source_list(path, filename_check=None):
for dirpath, dirnames, filenames in os.walk(path):
-
- # skip '.svn'
- if dirpath.startswith("."):
- continue
+ # skip '.git'
+ dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
if filename_check is None or filename_check(filename):
diff --git a/tests/gtests/blenlib/BLI_kdopbvh_test.cc b/tests/gtests/blenlib/BLI_kdopbvh_test.cc
new file mode 100644
index 00000000000..74db7cf20a0
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_kdopbvh_test.cc
@@ -0,0 +1,97 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+/* TODO: ray intersection, overlap ... etc.*/
+
+extern "C" {
+#include "BLI_compiler_attrs.h"
+#include "BLI_kdopbvh.h"
+#include "BLI_rand.h"
+#include "BLI_math_vector.h"
+#include "MEM_guardedalloc.h"
+}
+
+#include "stubs/bf_intern_eigen_stubs.h"
+
+/* -------------------------------------------------------------------- */
+/* Helper Functions */
+
+static void rng_v3_round(
+ float *coords, int coords_len,
+ struct RNG *rng, int round, float scale)
+{
+ for (int i = 0; i < coords_len; i++) {
+ float f = BLI_rng_get_float(rng) * 2.0f - 1.0f;
+ coords[i] = ((float)((int)(f * round)) / (float)round) * scale;
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/* Tests */
+
+TEST(kdopbvh, Empty)
+{
+ BVHTree *tree = BLI_bvhtree_new(0, 0.0, 8, 8);
+ BLI_bvhtree_balance(tree);
+ EXPECT_EQ(0, BLI_bvhtree_get_size(tree));
+ BLI_bvhtree_free(tree);
+}
+
+TEST(kdopbvh, Single)
+{
+ BVHTree *tree = BLI_bvhtree_new(1, 0.0, 8, 8);
+ {
+ float co[3] = {0};
+ BLI_bvhtree_insert(tree, 0, co, 1);
+ }
+
+ EXPECT_EQ(BLI_bvhtree_get_size(tree), 1);
+
+ BLI_bvhtree_balance(tree);
+ BLI_bvhtree_free(tree);
+}
+
+/**
+ * Note that a small epsilon is added to the BVH nodes bounds, even if we pass in zero.
+ * Use rounding to ensure very close nodes don't cause the wrong node to be found as nearest.
+ */
+static void find_nearest_points_test(int points_len, float scale, int round, int random_seed)
+{
+ struct RNG *rng = BLI_rng_new(random_seed);
+ BVHTree *tree = BLI_bvhtree_new(points_len, 0.0, 8, 8);
+
+ void *mem = MEM_mallocN(sizeof(float[3]) * points_len, __func__);
+ float (*points)[3] = (float (*)[3])mem;
+
+ for (int i = 0; i < points_len; i++) {
+ rng_v3_round(points[i], 3, rng, round, scale);
+ BLI_bvhtree_insert(tree, i, points[i], 1);
+ }
+ BLI_bvhtree_balance(tree);
+ /* first find each point */
+ for (int i = 0; i < points_len; i++) {
+ const int j = BLI_bvhtree_find_nearest(tree, points[i], NULL, NULL, NULL);
+ if (j != i) {
+#if 0
+ const float dist = len_v3v3(points[i], points[j]);
+ if (dist > (1.0f / (float)round)) {
+ printf("%.15f (%d %d)\n", dist, i, j);
+ print_v3_id(points[i]);
+ print_v3_id(points[j]);
+ fflush(stdout);
+ }
+#endif
+ EXPECT_GE(j, 0);
+ EXPECT_LT(j, points_len);
+ EXPECT_EQ_ARRAY(points[i], points[j], 3);
+ }
+ }
+ BLI_bvhtree_free(tree);
+ BLI_rng_free(rng);
+ MEM_freeN(points);
+}
+
+TEST(kdopbvh, FindNearest_1) { find_nearest_points_test(1, 1.0, 1000, 1234); }
+TEST(kdopbvh, FindNearest_2) { find_nearest_points_test(2, 1.0, 1000, 123); }
+TEST(kdopbvh, FindNearest_500) { find_nearest_points_test(500, 1.0, 1000, 12); }
diff --git a/tests/gtests/blenlib/BLI_math_geom_test.cc b/tests/gtests/blenlib/BLI_math_geom_test.cc
index cd15a4eb8ff..92e2532392e 100644
--- a/tests/gtests/blenlib/BLI_math_geom_test.cc
+++ b/tests/gtests/blenlib/BLI_math_geom_test.cc
@@ -4,6 +4,8 @@
#include "BLI_math.h"
+#include "stubs/bf_intern_eigen_stubs.h"
+
TEST(math_geom, DistToLine2DSimple)
{
float p[2] = {5.0f, 1.0f},
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index ef469da50b2..41fad661ea9 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -41,7 +41,7 @@ const char *GHOST_getSystemDir(int version, const char *versionstr)
struct ImBuf;
void IMB_freeImBuf(struct ImBuf *ibuf) {}
-struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf) {return NULL;}
+struct ImBuf *IMB_dupImBuf(const ImBuf *ibuf) {return NULL;}
#ifdef __linux__
char *zLhm65070058860608_br_find_exe(const char *default_exe)
diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
index 5d112751fa0..eefcdd6e85e 100644
--- a/tests/gtests/blenlib/BLI_polyfill2d_test.cc
+++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
@@ -27,6 +27,8 @@ extern "C" {
#endif
}
+#include "stubs/bf_intern_eigen_stubs.h"
+
static void polyfill_to_obj(
const char *id,
const float poly[][2], const unsigned int poly_tot,
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index a190d9cd8c5..ffdb8d08d31 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -34,23 +34,27 @@ include_directories(${INC})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
+if(WIN32)
+ set(BLI_path_util_extra_libs "bf_blenlib;bf_intern_utfconv;extern_wcwidth;${ZLIB_LIBRARIES}")
+else()
+ set(BLI_path_util_extra_libs "bf_blenlib;extern_wcwidth;${ZLIB_LIBRARIES}")
+endif()
BLENDER_TEST(BLI_array_store "bf_blenlib")
BLENDER_TEST(BLI_array_utils "bf_blenlib")
-BLENDER_TEST(BLI_stack "bf_blenlib")
-BLENDER_TEST(BLI_math_color "bf_blenlib")
-BLENDER_TEST(BLI_math_geom "bf_blenlib;bf_intern_eigen")
+BLENDER_TEST(BLI_ghash "bf_blenlib")
+BLENDER_TEST(BLI_hash_mm2a "bf_blenlib")
+BLENDER_TEST(BLI_kdopbvh "bf_blenlib")
+BLENDER_TEST(BLI_listbase "bf_blenlib")
BLENDER_TEST(BLI_math_base "bf_blenlib")
+BLENDER_TEST(BLI_math_color "bf_blenlib")
+BLENDER_TEST(BLI_math_geom "bf_blenlib")
+BLENDER_TEST(BLI_path_util "${BLI_path_util_extra_libs}")
+BLENDER_TEST(BLI_polyfill2d "bf_blenlib")
+BLENDER_TEST(BLI_stack "bf_blenlib")
BLENDER_TEST(BLI_string "bf_blenlib")
BLENDER_TEST(BLI_string_utf8 "bf_blenlib")
-if(WIN32)
- BLENDER_TEST(BLI_path_util "bf_blenlib;bf_intern_utfconv;extern_wcwidth;${ZLIB_LIBRARIES}")
-else()
- BLENDER_TEST(BLI_path_util "bf_blenlib;extern_wcwidth;${ZLIB_LIBRARIES}")
-endif()
-BLENDER_TEST(BLI_polyfill2d "bf_blenlib;bf_intern_eigen")
-BLENDER_TEST(BLI_listbase "bf_blenlib")
-BLENDER_TEST(BLI_hash_mm2a "bf_blenlib")
-BLENDER_TEST(BLI_ghash "bf_blenlib")
BLENDER_TEST_PERFORMANCE(BLI_ghash_performance "bf_blenlib")
+
+unset(BLI_path_util_extra_libs)
diff --git a/tests/gtests/blenlib/stubs/bf_intern_eigen_stubs.h b/tests/gtests/blenlib/stubs/bf_intern_eigen_stubs.h
new file mode 100644
index 00000000000..dad77a257d5
--- /dev/null
+++ b/tests/gtests/blenlib/stubs/bf_intern_eigen_stubs.h
@@ -0,0 +1,18 @@
+/* Apache License, Version 2.0 */
+
+extern "C" {
+
+bool EIG_self_adjoint_eigen_solve(const int size, const float *matrix, float *r_eigen_values, float *r_eigen_vectors)
+{
+ BLI_assert(0);
+ UNUSED_VARS(size, matrix, r_eigen_values, r_eigen_vectors);
+ return false;
+}
+
+void EIG_svd_square_matrix(const int size, const float *matrix, float *r_U, float *r_S, float *r_V)
+{
+ BLI_assert(0);
+ UNUSED_VARS(size, matrix, r_U, r_S, r_V);
+}
+
+}
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index ac480f4d58c..516284178a5 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -39,79 +39,103 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_OUT_DIR})
# all calls to blender use this
if(APPLE)
if(${CMAKE_GENERATOR} MATCHES "Xcode")
- set(TEST_BLENDER_EXE ${EXECUTABLE_OUTPUT_PATH}/Debug/blender.app/Contents/MacOS/blender)
+ set(TEST_BLENDER_EXE_PARAMS --background -noaudio --factory-startup)
else()
- set(TEST_BLENDER_EXE ${EXECUTABLE_OUTPUT_PATH}/blender.app/Contents/MacOS/blender)
+ set(TEST_BLENDER_EXE_PARAMS --background -noaudio --factory-startup --env-system-scripts ${CMAKE_SOURCE_DIR}/release/scripts)
endif()
else()
- set(TEST_BLENDER_EXE ${EXECUTABLE_OUTPUT_PATH}/blender)
+ set(TEST_BLENDER_EXE_PARAMS --background -noaudio --factory-startup --env-system-scripts ${CMAKE_SOURCE_DIR}/release/scripts)
endif()
# for testing with valgrind prefix: valgrind --track-origins=yes --error-limit=no
-set(TEST_BLENDER_EXE_BARE ${TEST_BLENDER_EXE})
-set(TEST_BLENDER_EXE ${TEST_BLENDER_EXE} --background -noaudio --factory-startup --env-system-scripts ${CMAKE_SOURCE_DIR}/release/scripts)
+# set(TEST_BLENDER_EXE_BARE ${TEST_BLENDER_EXE})
+# set(TEST_BLENDER_EXE ${TEST_BLENDER_EXE} ${TEST_BLENDER_EXE_PARAMS} )
# ------------------------------------------------------------------------------
# GENERAL PYTHON CORRECTNESS TESTS
-add_test(script_load_keymap ${TEST_BLENDER_EXE}
+add_test(
+ NAME script_load_keymap
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_keymap_completeness.py
)
-add_test(script_load_addons ${TEST_BLENDER_EXE}
+add_test(
+ NAME script_load_addons
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_load_addons.py
)
-add_test(script_load_modules ${TEST_BLENDER_EXE}
+add_test(
+ NAME script_load_modules
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_load_py_modules.py
)
# test running operators doesn't segfault under various conditions
if(USE_EXPERIMENTAL_TESTS)
- add_test(script_run_operators ${TEST_BLENDER_EXE}
+ add_test(
+ NAME script_run_operators
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_run_operators.py
)
endif()
# ------------------------------------------------------------------------------
# PY API TESTS
-add_test(script_pyapi_bpy_path ${TEST_BLENDER_EXE}
+add_test(
+ NAME script_pyapi_bpy_path
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_bpy_path.py
)
-add_test(script_pyapi_bpy_utils_units ${TEST_BLENDER_EXE}
+add_test(
+ NAME script_pyapi_bpy_utils_units
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_bpy_utils_units.py
)
-add_test(script_pyapi_mathutils ${TEST_BLENDER_EXE}
+add_test(
+ NAME script_pyapi_mathutils
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_mathutils.py
)
-add_test(script_pyapi_idprop ${TEST_BLENDER_EXE}
+add_test(
+ NAME script_pyapi_idprop
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_idprop.py
)
-add_test(script_pyapi_idprop_datablock ${TEST_BLENDER_EXE}
+add_test(
+ NAME script_pyapi_idprop_datablock
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_idprop_datablock.py
)
# ------------------------------------------------------------------------------
# MODELING TESTS
-add_test(bevel ${TEST_BLENDER_EXE}
+add_test(
+ NAME bevel
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/modeling/bevel_regression.blend
--python-text run_tests
)
-add_test(split_faces ${TEST_BLENDER_EXE}
- ${TEST_SRC_DIR}/modeling/split_faces_test.blend
- --python-text run_tests
+add_test(
+ NAME split_faces
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
+ ${TEST_SRC_DIR}/modeling/split_faces_test.blend
+ --python-text run_tests
)
# ------------------------------------------------------------------------------
# MODIFIERS TESTS
-add_test(modifier_array ${TEST_BLENDER_EXE}
- ${TEST_SRC_DIR}/modifier_stack/array_test.blend
- --python-text run_tests
+add_test(
+ NAME modifier_array
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
+ ${TEST_SRC_DIR}/modifier_stack/array_test.blend
+ --python-text run_tests
)
# ------------------------------------------------------------------------------
@@ -120,21 +144,27 @@ add_test(modifier_array ${TEST_BLENDER_EXE}
# OBJ Import tests
# disabled until updated & working
if(FALSE)
-add_test(import_obj_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_obj_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.obj\(filepath='${TEST_SRC_DIR}/io_tests/obj/cube.obj'\)
--md5=39cce4bacac2d1b18fc470380279bc15 --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_obj_cube.blend
)
-add_test(import_obj_nurbs_cyclic ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_obj_nurbs_cyclic
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.obj\(filepath='${TEST_SRC_DIR}/io_tests/obj/nurbs_cyclic.obj'\)
--md5=ad3c307e5883224a0492378cd32691ab --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_obj_nurbs_cyclic.blend
)
-add_test(import_obj_makehuman ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_obj_makehuman
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.obj\(filepath='${TEST_SRC_DIR}/io_tests/obj/makehuman.obj'\)
--md5=c9f78b185e58358daa4ecaecfa75464e --md5_method=SCENE
@@ -143,7 +173,9 @@ add_test(import_obj_makehuman ${TEST_BLENDER_EXE}
endif()
# OBJ Export tests
-add_test(export_obj_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_obj_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_cube.obj',use_selection=False\)
@@ -152,7 +184,9 @@ add_test(export_obj_cube ${TEST_BLENDER_EXE}
--md5=e80660437ad9bfe082849641c361a233 --md5_method=FILE
)
-add_test(export_obj_nurbs ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_obj_nurbs
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/nurbs.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_nurbs.obj',use_selection=False,use_nurbs=True\)
@@ -163,7 +197,9 @@ add_test(export_obj_nurbs ${TEST_BLENDER_EXE}
# disabled until updated & working
if(FALSE)
-add_test(export_obj_all_objects ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_obj_all_objects
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_all_objects.obj',use_selection=False,use_nurbs=True\)
@@ -176,21 +212,27 @@ endif()
# PLY Import tests
-add_test(import_ply_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_ply_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_mesh.ply\(filepath='${TEST_SRC_DIR}/io_tests/ply/cube_ascii.ply'\)
--md5=527134343c27fc0ea73115b85fbfd3ac --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_ply_cube.blend
)
-add_test(import_ply_bunny ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_ply_bunny
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_mesh.ply\(filepath='${TEST_SRC_DIR}/io_tests/ply/bunny2.ply'\)
--md5=6ea5b8533400a17accf928b8fd024eaa --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_ply_bunny.blend
)
-add_test(import_ply_small_holes ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_ply_small_holes
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_mesh.ply\(filepath='${TEST_SRC_DIR}/io_tests/ply/many_small_holes.ply'\)
--md5=c3093e26ecae5b6d59fbbcf2a0d0b39f --md5_method=SCENE
@@ -200,7 +242,9 @@ add_test(import_ply_small_holes ${TEST_BLENDER_EXE}
# PLY Export
# disabled until updated & working
if(FALSE)
-add_test(export_ply_cube_all_data ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_ply_cube_all_data
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/cube_all_data.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_mesh.ply\(filepath='${TEST_OUT_DIR}/export_ply_cube_all_data.ply'\)
@@ -208,7 +252,9 @@ add_test(export_ply_cube_all_data ${TEST_BLENDER_EXE}
--md5=6adc3748ceae8298496f99d0e7e76c15 --md5_method=FILE
)
-add_test(export_ply_suzanne_all_data ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_ply_suzanne_all_data
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/suzanne_all_data.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_mesh.ply\(filepath='${TEST_OUT_DIR}/export_ply_suzanne_all_data.ply'\)
@@ -217,7 +263,9 @@ add_test(export_ply_suzanne_all_data ${TEST_BLENDER_EXE}
)
endif()
-add_test(export_ply_vertices ${TEST_BLENDER_EXE} # lame, add a better one
+add_test(
+ NAME export_ply_vertices # lame, add a better one
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/vertices.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_mesh.ply\(filepath='${TEST_OUT_DIR}/export_ply_vertices.ply'\)
@@ -229,21 +277,27 @@ add_test(export_ply_vertices ${TEST_BLENDER_EXE} # lame, add a better one
# STL Import tests
# disabled until updated & working
if(FALSE)
-add_test(import_stl_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_stl_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_mesh.stl\(filepath='${TEST_SRC_DIR}/io_tests/stl/cube.stl'\)
--md5=8ceb5bb7e1cb5f4342fa1669988c66b4 --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_stl_cube.blend
)
-add_test(import_stl_conrod ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_stl_conrod
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_mesh.stl\(filepath='${TEST_SRC_DIR}/io_tests/stl/conrod.stl'\)
--md5=690a4b8eb9002dcd8631c5a575ea7348 --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_stl_conrod.blend
)
-add_test(import_stl_knot_max_simplified ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_stl_knot_max_simplified
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_mesh.stl\(filepath='${TEST_SRC_DIR}/io_tests/stl/knot_max_simplified.stl'\)
--md5=baf82803f45a84ec4ddbad9cef57dd3e --md5_method=SCENE
@@ -254,7 +308,9 @@ endif()
# STL Export
# disabled until updated & working
if(FALSE)
-add_test(export_stl_cube_all_data ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_stl_cube_all_data
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/cube_all_data.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_mesh.stl\(filepath='${TEST_OUT_DIR}/export_stl_cube_all_data.stl'\)
@@ -262,7 +318,9 @@ add_test(export_stl_cube_all_data ${TEST_BLENDER_EXE}
--md5=64cb97c0cabb015e1c3f76369835075a --md5_method=FILE
)
-add_test(export_stl_suzanne_all_data ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_stl_suzanne_all_data
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/suzanne_all_data.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_mesh.stl\(filepath='${TEST_OUT_DIR}/export_stl_suzanne_all_data.stl'\)
@@ -270,7 +328,9 @@ add_test(export_stl_suzanne_all_data ${TEST_BLENDER_EXE}
--md5=e9b23c97c139ad64961c635105bb9192 --md5_method=FILE
)
-add_test(export_stl_vertices ${TEST_BLENDER_EXE} # lame, add a better one
+add_test(
+ NAME export_stl_vertices # lame, add a better one
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/vertices.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_mesh.stl\(filepath='${TEST_OUT_DIR}/export_stl_vertices.stl'\)
@@ -283,21 +343,27 @@ endif()
# X3D Import
# disabled until updated & working
if(FALSE)
-add_test(import_x3d_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_x3d_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.x3d\(filepath='${TEST_SRC_DIR}/io_tests/x3d/color_cube.x3d'\)
--md5=3fae9be004199c145941cd3f9f80ad7b --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_x3d_cube.blend
)
-add_test(import_x3d_teapot ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_x3d_teapot
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.x3d\(filepath='${TEST_SRC_DIR}/io_tests/x3d/teapot.x3d'\)
--md5=8ee196c71947dce4199d55698501691e --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_x3d_teapot.blend
)
-add_test(import_x3d_suzanne_material ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_x3d_suzanne_material
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.x3d\(filepath='${TEST_SRC_DIR}/io_tests/x3d/suzanne_material.x3d'\)
--md5=3edea1353257d8b5a5f071942f417be6 --md5_method=SCENE
@@ -305,7 +371,9 @@ add_test(import_x3d_suzanne_material ${TEST_BLENDER_EXE}
)
# X3D Export
-add_test(export_x3d_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_x3d_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_cube.x3d',use_selection=False\)
@@ -313,7 +381,9 @@ add_test(export_x3d_cube ${TEST_BLENDER_EXE}
--md5=05312d278fe41da33560fdfb9bdb268f --md5_method=FILE
)
-add_test(export_x3d_nurbs ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_x3d_nurbs
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/nurbs.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_nurbs.x3d',use_selection=False\)
@@ -321,7 +391,9 @@ add_test(export_x3d_nurbs ${TEST_BLENDER_EXE}
--md5=4286d4a2aa507ef78b22ddcbdcc88481 --md5_method=FILE
)
-add_test(export_x3d_all_objects ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_x3d_all_objects
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_all_objects.x3d',use_selection=False\)
@@ -335,21 +407,27 @@ endif()
# 3DS Import
# disabled until updated & working
if(FALSE)
-add_test(import_3ds_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_3ds_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.autodesk_3ds\(filepath='${TEST_SRC_DIR}/io_tests/3ds/cube.3ds'\)
--md5=cb5a45c35a343c3f5beca2a918472951 --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_3ds_cube.blend
)
-add_test(import_3ds_hierarchy_lara ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_3ds_hierarchy_lara
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.autodesk_3ds\(filepath='${TEST_SRC_DIR}/io_tests/3ds/hierarchy_lara.3ds'\)
--md5=766c873d9fdb5f190e43796cfbae63b6 --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_3ds_hierarchy_lara.blend
)
-add_test(import_3ds_hierarchy_greek_trireme ${TEST_BLENDER_EXE}
+add_test(
+ NAME import_3ds_hierarchy_greek_trireme
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.autodesk_3ds\(filepath='${TEST_SRC_DIR}/io_tests/3ds/hierarchy_greek_trireme.3ds'\)
--md5=b62ee30101e8999cb91ef4f8a8760056 --md5_method=SCENE
@@ -360,7 +438,9 @@ endif()
# 3DS Export
# disabled until updated & working
if(FALSE)
-add_test(export_3ds_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_3ds_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.autodesk_3ds\(filepath='${TEST_OUT_DIR}/export_3ds_cube.3ds',use_selection=False\)
@@ -368,7 +448,9 @@ add_test(export_3ds_cube ${TEST_BLENDER_EXE}
--md5=a31f5071b6c6dc7445b9099cdc7f63b3 --md5_method=FILE
)
-add_test(export_3ds_nurbs ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_3ds_nurbs
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/nurbs.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.autodesk_3ds\(filepath='${TEST_OUT_DIR}/export_3ds_nurbs.3ds',use_selection=False\)
@@ -376,7 +458,9 @@ add_test(export_3ds_nurbs ${TEST_BLENDER_EXE}
--md5=5bdd21be3c80d814fbc83cb25edb08c2 --md5_method=FILE
)
-add_test(export_3ds_all_objects ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_3ds_all_objects
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.autodesk_3ds\(filepath='${TEST_OUT_DIR}/export_3ds_all_objects.3ds',use_selection=False\)
@@ -391,7 +475,9 @@ endif()
# 'use_metadata=False' for reliable md5's
# disabled until updated & working
if(FALSE)
-add_test(export_fbx_cube ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_fbx_cube
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_cube.fbx',use_selection=False,use_metadata=False\)
@@ -399,7 +485,9 @@ add_test(export_fbx_cube ${TEST_BLENDER_EXE}
--md5=59a35577462f95f9a0b4e6035226ce9b --md5_method=FILE
)
-add_test(export_fbx_nurbs ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_fbx_nurbs
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_geometry/nurbs.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_nurbs.fbx',use_selection=False,use_metadata=False\)
@@ -407,7 +495,9 @@ add_test(export_fbx_nurbs ${TEST_BLENDER_EXE}
--md5=d31875f18f613fa0c3b16e978f87f6f8 --md5_method=FILE
)
-add_test(export_fbx_all_objects ${TEST_BLENDER_EXE}
+add_test(
+ NAME export_fbx_all_objects
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_all_objects.fbx',use_selection=False,use_metadata=False\)
@@ -420,31 +510,43 @@ if(WITH_CYCLES)
if(OPENIMAGEIO_IDIFF AND EXISTS "${TEST_SRC_DIR}/cycles/ctests/shader")
macro(add_cycles_render_test subject)
if(MSVC)
- add_test(NAME cycles_${subject}_test
+ add_test(
+ NAME cycles_${subject}_test
COMMAND
"$<TARGET_FILE_DIR:blender>/${BLENDER_VERSION_MAJOR}.${BLENDER_VERSION_MINOR}/python/bin/python$<$<CONFIG:Debug>:_d>"
${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
-blender "$<TARGET_FILE:blender>"
-testdir "${TEST_SRC_DIR}/cycles/ctests/${subject}"
-idiff "${OPENIMAGEIO_IDIFF}"
+ -outdir "${TEST_OUT_DIR}/cycles"
)
else()
- add_test(cycles_${subject}_test
- ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
- -blender "${TEST_BLENDER_EXE_BARE}"
+ add_test(
+ NAME cycles_${subject}_test
+ COMMAND ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
+ -blender "$<TARGET_FILE:blender>"
-testdir "${TEST_SRC_DIR}/cycles/ctests/${subject}"
-idiff "${OPENIMAGEIO_IDIFF}"
+ -outdir "${TEST_OUT_DIR}/cycles"
)
endif()
endmacro()
if(WITH_OPENGL_TESTS)
add_cycles_render_test(opengl)
endif()
- add_cycles_render_test(image)
+ add_cycles_render_test(denoise)
+ add_cycles_render_test(displacement)
+ add_cycles_render_test(image_data_types)
+ add_cycles_render_test(image_mapping)
+ add_cycles_render_test(image_texture_limit)
+ add_cycles_render_test(light)
add_cycles_render_test(mblur)
add_cycles_render_test(reports)
add_cycles_render_test(render)
add_cycles_render_test(shader)
+ add_cycles_render_test(shader_tangent)
+ add_cycles_render_test(shadow_catcher)
+ add_cycles_render_test(volume)
else()
MESSAGE(STATUS "Disabling Cycles tests because tests folder does not exist")
endif()
@@ -458,14 +560,10 @@ if(WITH_ALEMBIC)
get_filename_component(real_include_dir ${ALEMBIC_INCLUDE_DIR} REALPATH)
get_filename_component(ALEMBIC_ROOT_DIR ${real_include_dir} DIRECTORY)
- add_test(script_alembic_import ${TEST_BLENDER_EXE}
- --python ${CMAKE_CURRENT_LIST_DIR}/bl_alembic_import_test.py
- --
- --testdir "${TEST_SRC_DIR}/alembic"
- )
-
if(MSVC)
- add_test(NAME alembic_tests
+ # FIXME, de-duplicate.
+ add_test(
+ NAME alembic_tests
COMMAND
"$<TARGET_FILE_DIR:blender>/${BLENDER_VERSION_MAJOR}.${BLENDER_VERSION_MINOR}/python/bin/python$<$<CONFIG:Debug>:_d>"
${CMAKE_CURRENT_LIST_DIR}/alembic_tests.py
@@ -474,11 +572,21 @@ if(WITH_ALEMBIC)
--alembic-root "${ALEMBIC_ROOT_DIR}"
)
else()
- add_test(alembic_tests
- ${CMAKE_CURRENT_LIST_DIR}/alembic_tests.py
- --blender "${TEST_BLENDER_EXE_BARE}"
+ add_test(
+ NAME alembic_tests
+ COMMAND ${CMAKE_CURRENT_LIST_DIR}/alembic_tests.py
+ --blender "$<TARGET_FILE:blender>"
--testdir "${TEST_SRC_DIR}/alembic"
--alembic-root "${ALEMBIC_ROOT_DIR}"
)
endif()
+
+ add_test(
+ NAME script_alembic_import
+ COMMAND "$<TARGET_FILE:blender>" ${TEST_BLENDER_EXE_PARAMS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_alembic_import_test.py
+ --
+ --testdir "${TEST_SRC_DIR}/alembic"
+ --with-legacy-depsgraph=${WITH_LEGACY_DEPSGRAPH}
+ )
endif()
diff --git a/tests/python/alembic_tests.py b/tests/python/alembic_tests.py
index e36a6391298..96a68de9801 100755
--- a/tests/python/alembic_tests.py
+++ b/tests/python/alembic_tests.py
@@ -157,6 +157,8 @@ class AbstractAlembicTest(unittest.TestCase):
if proptype == 'CompoundProperty':
# To read those, call self.abcprop() on it.
continue
+ if len(parts) < 2:
+ raise ValueError('Error parsing result from abcprop: %s', info.strip())
valtype_and_arrsize, name_and_extent = parts[1:]
# Parse name and extent
diff --git a/tests/python/batch_import.py b/tests/python/batch_import.py
index bbe3a70327f..a6e2469349b 100644
--- a/tests/python/batch_import.py
+++ b/tests/python/batch_import.py
@@ -72,10 +72,8 @@ def batch_import(
def file_generator(path):
for dirpath, dirnames, filenames in os.walk(path):
-
- # skip '.svn'
- if dirpath.startswith("."):
- continue
+ # skip '.git'
+ dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
if pattern_match(filename):
diff --git a/tests/python/bl_alembic_import_test.py b/tests/python/bl_alembic_import_test.py
index 358b8a3c758..c3a4af26e11 100644
--- a/tests/python/bl_alembic_import_test.py
+++ b/tests/python/bl_alembic_import_test.py
@@ -75,6 +75,39 @@ class SimpleImportTest(AbstractAlembicTest):
self.assertEqual(objects['Cube_003'], objects['Cube_005'].parent)
self.assertEqual(objects['Cube_003'], objects['Cube_006'].parent)
+ def test_inherit_or_not(self):
+ res = bpy.ops.wm.alembic_import(
+ filepath=str(self.testdir / "T52022-inheritance.abc"),
+ as_background_job=False)
+ self.assertEqual({'FINISHED'}, res)
+
+ # The objects should be linked to scene_collection in Blender 2.8,
+ # and to scene in Blender 2.7x.
+ objects = bpy.context.scene.objects
+
+ # ABC parent is top-level object, which translates to nothing in Blender
+ self.assertIsNone(objects['locator1'].parent)
+
+ # ABC parent is locator1, but locator2 has "inherits Xforms" = false, which
+ # translates to "no parent" in Blender.
+ self.assertIsNone(objects['locator2'].parent)
+
+ # Shouldn't have inherited the ABC parent's transform.
+ x, y, z = objects['locator2'].matrix_world.to_translation()
+ self.assertAlmostEqual(0, x)
+ self.assertAlmostEqual(0, y)
+ self.assertAlmostEqual(2, z)
+
+ # ABC parent is inherited and translates to normal parent in Blender.
+ self.assertEqual(objects['locator2'], objects['locatorShape2'].parent)
+
+ # Should have inherited its ABC parent's transform.
+ x, y, z = objects['locatorShape2'].matrix_world.to_translation()
+ self.assertAlmostEqual(0, x)
+ self.assertAlmostEqual(0, y)
+ self.assertAlmostEqual(2, z)
+
+
def test_select_after_import(self):
# Add a sphere, so that there is something in the scene, selected, and active,
# before we do the Alembic import.
@@ -129,6 +162,9 @@ class SimpleImportTest(AbstractAlembicTest):
bpy.data.cache_files[fname].filepath = relpath.replace('1.abc', '2.abc')
bpy.context.scene.update()
+ if args.with_legacy_depsgraph:
+ bpy.context.scene.frame_set(10)
+
x, y, z = cube.matrix_world.to_euler('XYZ')
self.assertAlmostEqual(x, math.pi / 2, places=5)
self.assertAlmostEqual(y, 0)
@@ -143,22 +179,24 @@ class SimpleImportTest(AbstractAlembicTest):
res = bpy.ops.wm.alembic_import(filepath=str(abc), as_background_job=False)
self.assertEqual({'FINISHED'}, res)
- cube = bpy.context.active_object
+ plane = bpy.context.active_object
# Check that the file loaded ok.
bpy.context.scene.frame_set(6)
- self.assertAlmostEqual(-1, cube.data.vertices[0].co.x)
- self.assertAlmostEqual(-1, cube.data.vertices[0].co.y)
- self.assertAlmostEqual(0.5905638933181763, cube.data.vertices[0].co.z)
+ mesh = plane.to_mesh(bpy.context.scene, True, 'RENDER')
+ self.assertAlmostEqual(-1, mesh.vertices[0].co.x)
+ self.assertAlmostEqual(-1, mesh.vertices[0].co.y)
+ self.assertAlmostEqual(0.5905638933181763, mesh.vertices[0].co.z)
# Change path from absolute to relative. This should not break the animation.
bpy.context.scene.frame_set(1)
bpy.data.cache_files[fname].filepath = relpath
bpy.context.scene.frame_set(6)
- self.assertAlmostEqual(1, cube.data.vertices[3].co.x)
- self.assertAlmostEqual(1, cube.data.vertices[3].co.y)
- self.assertAlmostEqual(0.5905638933181763, cube.data.vertices[3].co.z)
+ mesh = plane.to_mesh(bpy.context.scene, True, 'RENDER')
+ self.assertAlmostEqual(1, mesh.vertices[3].co.x)
+ self.assertAlmostEqual(1, mesh.vertices[3].co.y)
+ self.assertAlmostEqual(0.5905638933181763, mesh.vertices[3].co.z)
def test_import_long_names(self):
# This file contains very long names. The longest name is 4047 chars.
@@ -207,12 +245,14 @@ def main():
import argparse
if '--' in sys.argv:
- argv = [sys.argv[0]] + sys.argv[sys.argv.index('--')+1:]
+ argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:]
else:
argv = sys.argv
parser = argparse.ArgumentParser()
parser.add_argument('--testdir', required=True, type=pathlib.Path)
+ parser.add_argument('--with-legacy-depsgraph', default=False,
+ type=lambda v: v in {'ON', 'YES', 'TRUE'})
args, remaining = parser.parse_known_args(argv)
unittest.main(argv=remaining)
diff --git a/tests/python/bl_keymap_completeness.py b/tests/python/bl_keymap_completeness.py
index 00322907f69..652ed449a3c 100644
--- a/tests/python/bl_keymap_completeness.py
+++ b/tests/python/bl_keymap_completeness.py
@@ -80,5 +80,6 @@ def main():
import sys
sys.exit(1)
+
if __name__ == "__main__":
main()
diff --git a/tests/python/bl_load_py_modules.py b/tests/python/bl_load_py_modules.py
index c13679d16f0..39e7bd33d44 100644
--- a/tests/python/bl_load_py_modules.py
+++ b/tests/python/bl_load_py_modules.py
@@ -36,6 +36,9 @@ BLACKLIST = {
"cycles",
"io_export_dxf", # TODO, check on why this fails
'io_import_dxf', # Because of cydxfentity.so dependency
+
+ # The unpacked wheel is only loaded when actually used, not directly on import:
+ os.path.join("io_blend_utils", "blender_bam-unpacked.whl"),
}
# Some modules need to add to the `sys.path`.
@@ -90,9 +93,8 @@ def addon_modules_sorted():
def source_list(path, filename_check=None):
from os.path import join
for dirpath, dirnames, filenames in os.walk(path):
- # skip '.svn'
- if dirpath.startswith("."):
- continue
+ # skip '.git'
+ dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
filepath = join(dirpath, filename)
@@ -120,6 +122,8 @@ def load_addons():
def load_modules():
+ VERBOSE = os.environ.get("BLENDER_VERBOSE") is not None
+
modules = []
module_paths = []
@@ -159,6 +163,14 @@ def load_modules():
del module_names
#
+ # test we tested all files except for presets and templates
+ ignore_paths = [
+ os.sep + "presets" + os.sep,
+ os.sep + "templates" + os.sep,
+ ] + ([(os.sep + f + os.sep) for f in BLACKLIST] +
+ [(os.sep + f + ".py") for f in BLACKLIST])
+
+ #
# now submodules
for m in modules:
filepath = m.__file__
@@ -175,15 +187,35 @@ def load_modules():
for f in MODULE_SYS_PATHS.get(mod_name_full, ())
])
- __import__(mod_name_full)
- mod_imp = sys.modules[mod_name_full]
-
- sys.path[:] = sys_path_back
-
- # check we load what we ask for.
- assert(os.path.samefile(mod_imp.__file__, submod_full))
-
- modules.append(mod_imp)
+ try:
+ __import__(mod_name_full)
+ mod_imp = sys.modules[mod_name_full]
+
+ sys.path[:] = sys_path_back
+
+ # check we load what we ask for.
+ assert(os.path.samefile(mod_imp.__file__, submod_full))
+
+ modules.append(mod_imp)
+ except Exception as e:
+ import traceback
+ # Module might fail to import, but we don't want whole test to fail here.
+ # Reasoning:
+ # - This module might be in ignored list (for example, preset or template),
+ # so failing here will cause false-positive test failure.
+ # - If this is module which should not be ignored, it is not added to list
+ # of successfully loaded modules, meaning the test will catch this
+ # import failure.
+ # - We want to catch all failures of this script instead of stopping on
+ # a first big failure.
+ do_print = True
+ if not VERBOSE:
+ for ignore in ignore_paths:
+ if ignore in submod_full:
+ do_print = False
+ break
+ if do_print:
+ traceback.print_exc()
#
# check which filepaths we didn't load
@@ -202,20 +234,11 @@ def load_modules():
for f in loaded_files:
source_files.remove(f)
- #
- # test we tested all files except for presets and templates
- ignore_paths = [
- os.sep + "presets" + os.sep,
- os.sep + "templates" + os.sep,
- ] + ([(os.sep + f + os.sep) for f in BLACKLIST] +
- [(os.sep + f + ".py") for f in BLACKLIST])
-
for f in source_files:
- ok = False
for ignore in ignore_paths:
if ignore in f:
- ok = True
- if not ok:
+ break
+ else:
raise Exception("Source file %r not loaded in test" % f)
print("loaded %d modules" % len(loaded_files))
diff --git a/tests/python/bl_pyapi_bpy_utils_units.py b/tests/python/bl_pyapi_bpy_utils_units.py
index f40dab4b5eb..251419cb9ef 100644
--- a/tests/python/bl_pyapi_bpy_utils_units.py
+++ b/tests/python/bl_pyapi_bpy_utils_units.py
@@ -32,18 +32,17 @@ class UnitsTesting(unittest.TestCase):
OUTPUT_TESTS = (
# system, type, prec, sep, compat, value, output
##### LENGTH
+ # Note: precision handling is a bit complicated when using multi-units...
('IMPERIAL', 'LENGTH', 3, False, False, 0.3048, "1'"),
('IMPERIAL', 'LENGTH', 3, False, True, 0.3048, "1ft"),
- ('IMPERIAL', 'LENGTH', 3, True, False, 0.3048 * 2 + 0.0254 * 5.5, "2' 5.5\""),
- # Those next two fail, here again because precision ignores order magnitude :/
- #('IMPERIAL', 'LENGTH', 3, False, False, 1609.344 * 1e6, "1000000mi"), # == 1000000.004mi!!!
- #('IMPERIAL', 'LENGTH', 6, False, False, 1609.344 * 1e6, "1000000mi"), # == 1000000.003641mi!!!
- ('METRIC', 'LENGTH', 3, True, False, 1000 * 2 + 0.001 * 15, "2km 1.5cm"),
- ('METRIC', 'LENGTH', 3, True, False, 1234.56789, "1km 234.6m"),
- # Note: precision seems basically unused when using multi units!
- ('METRIC', 'LENGTH', 9, True, False, 1234.56789, "1km 234.6m"),
- ('METRIC', 'LENGTH', 9, False, False, 1234.56789, "1.23456789km"),
- ('METRIC', 'LENGTH', 9, True, False, 1000.000123456789, "1km 0.1mm"),
+ ('IMPERIAL', 'LENGTH', 4, True, False, 0.3048 * 2 + 0.0254 * 5.5, "2' 5.5\""),
+ ('IMPERIAL', 'LENGTH', 3, False, False, 1609.344 * 1e6, "1000000mi"),
+ ('IMPERIAL', 'LENGTH', 6, False, False, 1609.344 * 1e6, "1000000mi"),
+ ('METRIC', 'LENGTH', 3, True, False, 1000 * 2 + 0.001 * 15, "2km 2cm"),
+ ('METRIC', 'LENGTH', 5, True, False, 1234.56789, "1km 234.6m"),
+ ('METRIC', 'LENGTH', 6, True, False, 1234.56789, "1km 234.57m"),
+ ('METRIC', 'LENGTH', 9, False, False, 1234.56789, "1.234568km"),
+ ('METRIC', 'LENGTH', 9, True, False, 1000.000123456789, "1km 0.123mm"),
)
def test_units_inputs(self):
diff --git a/tests/python/bl_run_operators.py b/tests/python/bl_run_operators.py
index 7d5f4127378..7b6b97e5ad1 100644
--- a/tests/python/bl_run_operators.py
+++ b/tests/python/bl_run_operators.py
@@ -100,10 +100,8 @@ def blend_list(mainpath):
def file_list(path, filename_check=None):
for dirpath, dirnames, filenames in os.walk(path):
-
- # skip '.svn'
- if dirpath.startswith("."):
- continue
+ # skip '.git'
+ dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
filepath = join(dirpath, filename)
diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py
index a030cc5e0de..ba4c04f7cf3 100755
--- a/tests/python/cycles_render_tests.py
+++ b/tests/python/cycles_render_tests.py
@@ -2,7 +2,10 @@
# Apache License, Version 2.0
import argparse
+import glob
import os
+import pathlib
+import shlex
import shutil
import subprocess
import sys
@@ -24,7 +27,7 @@ class COLORS_DUMMY:
COLORS = COLORS_DUMMY
-def printMessage(type, status, message):
+def print_message(message, type=None, status=''):
if type == 'SUCCESS':
print(COLORS.GREEN, end="")
elif type == 'FAILURE':
@@ -50,38 +53,44 @@ def render_file(filepath):
dirname = os.path.dirname(filepath)
basedir = os.path.dirname(dirname)
subject = os.path.basename(dirname)
+
+ custom_args = os.getenv('CYCLESTEST_ARGS')
+ custom_args = shlex.split(custom_args) if custom_args else []
+
+ # OSL and GPU examples
+ # custom_args += ["--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True"]
+ # custom_args += ["--python-expr", "import bpy; bpy.context.scene.cycles.device = 'GPU'"]
+
if subject == 'opengl':
- command = (
+ command = [
BLENDER,
"--window-geometry", "0", "0", "1", "1",
"-noaudio",
"--factory-startup",
"--enable-autoexec",
filepath,
- "-E", "CYCLES",
- # Run with OSL enabled
- # "--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True",
+ "-E", "CYCLES"]
+ command += custom_args
+ command += [
"-o", TEMP_FILE_MASK,
"-F", "PNG",
'--python', os.path.join(basedir,
"util",
- "render_opengl.py")
- )
+ "render_opengl.py")]
else:
- command = (
+ command = [
BLENDER,
"--background",
"-noaudio",
"--factory-startup",
"--enable-autoexec",
filepath,
- "-E", "CYCLES",
- # Run with OSL enabled
- # "--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True",
+ "-E", "CYCLES"]
+ command += custom_args
+ command += [
"-o", TEMP_FILE_MASK,
"-F", "PNG",
- "-f", "1",
- )
+ "-f", "1"]
try:
output = subprocess.check_output(command)
if VERBOSE:
@@ -109,20 +118,172 @@ def test_get_name(filepath):
filename = os.path.basename(filepath)
return os.path.splitext(filename)[0]
-
-def verify_output(filepath):
+def test_get_images(filepath):
testname = test_get_name(filepath)
dirpath = os.path.dirname(filepath)
- reference_dirpath = os.path.join(dirpath, "reference_renders")
- reference_image = os.path.join(reference_dirpath, testname + ".png")
- failed_image = os.path.join(reference_dirpath, testname + ".fail.png")
- if not os.path.exists(reference_image):
+
+ old_dirpath = os.path.join(dirpath, "reference_renders")
+ old_img = os.path.join(old_dirpath, testname + ".png")
+
+ ref_dirpath = os.path.join(OUTDIR, os.path.basename(dirpath), "ref")
+ ref_img = os.path.join(ref_dirpath, testname + ".png")
+ if not os.path.exists(ref_dirpath):
+ os.makedirs(ref_dirpath)
+ if os.path.exists(old_img):
+ shutil.copy(old_img, ref_img)
+
+ new_dirpath = os.path.join(OUTDIR, os.path.basename(dirpath))
+ if not os.path.exists(new_dirpath):
+ os.makedirs(new_dirpath)
+ new_img = os.path.join(new_dirpath, testname + ".png")
+
+ diff_dirpath = os.path.join(OUTDIR, os.path.basename(dirpath), "diff")
+ if not os.path.exists(diff_dirpath):
+ os.makedirs(diff_dirpath)
+ diff_img = os.path.join(diff_dirpath, testname + ".diff.png")
+
+ return ref_img, new_img, diff_img
+
+
+class Report:
+ def __init__(self, testname):
+ self.failed_tests = ""
+ self.passed_tests = ""
+ self.testname = testname
+
+ def output(self):
+ # write intermediate data for single test
+ outdir = os.path.join(OUTDIR, self.testname)
+ if not os.path.exists(outdir):
+ os.makedirs(outdir)
+
+ f = open(os.path.join(outdir, "failed.data"), "w")
+ f.write(self.failed_tests)
+ f.close()
+
+ f = open(os.path.join(outdir, "passed.data"), "w")
+ f.write(self.passed_tests)
+ f.close()
+
+ # gather intermediate data for all tests
+ failed_data = sorted(glob.glob(os.path.join(OUTDIR, "*/failed.data")))
+ passed_data = sorted(glob.glob(os.path.join(OUTDIR, "*/passed.data")))
+
+ failed_tests = ""
+ passed_tests = ""
+
+ for filename in failed_data:
+ failed_tests += open(os.path.join(OUTDIR, filename), "r").read()
+ for filename in passed_data:
+ passed_tests += open(os.path.join(OUTDIR, filename), "r").read()
+
+ # write html for all tests
+ self.html = """
+<html>
+<head>
+ <title>Cycles Test Report</title>
+ <style>
+ img {{ image-rendering: pixelated; width: 256px; background-color: #000; }}
+ img.render {{
+ background-color: #fff;
+ background-image:
+ -moz-linear-gradient(45deg, #eee 25%, transparent 25%),
+ -moz-linear-gradient(-45deg, #eee 25%, transparent 25%),
+ -moz-linear-gradient(45deg, transparent 75%, #eee 75%),
+ -moz-linear-gradient(-45deg, transparent 75%, #eee 75%);
+ background-image:
+ -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #eee), color-stop(.25, transparent)),
+ -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #eee), color-stop(.25, transparent)),
+ -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #eee)),
+ -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #eee));
+
+ -moz-background-size:50px 50px;
+ background-size:50px 50px;
+ -webkit-background-size:50px 51px; /* override value for shitty webkit */
+
+ background-position:0 0, 25px 0, 25px -25px, 0px 25px;
+ }}
+ table td:first-child {{ width: 256px; }}
+ </style>
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css">
+</head>
+<body>
+ <div class="container">
+ <br/>
+ <h1>Cycles Test Report</h1>
+ <br/>
+ <table class="table table-striped">
+ <thead class="thead-default">
+ <tr><th>Name</th><th>New</th><th>Reference</th><th>Diff</th>
+ </thead>
+ {}{}
+ </table>
+ <br/>
+ </div>
+</body>
+</html>
+ """ . format(failed_tests, passed_tests)
+
+ filepath = os.path.join(OUTDIR, "report.html")
+ f = open(filepath, "w")
+ f.write(self.html)
+ f.close()
+
+ print_message("Report saved to: " + pathlib.Path(filepath).as_uri())
+
+ def relative_url(self, filepath):
+ relpath = os.path.relpath(filepath, OUTDIR)
+ return pathlib.Path(relpath).as_posix()
+
+ def add_test(self, filepath, error):
+ name = test_get_name(filepath)
+ name = name.replace('_', ' ')
+
+ ref_img, new_img, diff_img = test_get_images(filepath)
+
+ status = error if error else ""
+ style = """ style="background-color: #f99;" """ if error else ""
+
+ new_url = self.relative_url(new_img)
+ ref_url = self.relative_url(ref_img)
+ diff_url = self.relative_url(diff_img)
+
+ test_html = """
+ <tr{}>
+ <td><b>{}</b><br/>{}<br/>{}</td>
+ <td><img src="{}" onmouseover="this.src='{}';" onmouseout="this.src='{}';" class="render"></td>
+ <td><img src="{}" onmouseover="this.src='{}';" onmouseout="this.src='{}';" class="render"></td>
+ <td><img src="{}"></td>
+ </tr>""" . format(style, name, self.testname, status,
+ new_url, ref_url, new_url,
+ ref_url, new_url, ref_url,
+ diff_url)
+
+ if error:
+ self.failed_tests += test_html
+ else:
+ self.passed_tests += test_html
+
+
+def verify_output(report, filepath):
+ ref_img, new_img, diff_img = test_get_images(filepath)
+
+ # copy new image
+ if os.path.exists(new_img):
+ os.remove(new_img)
+ if os.path.exists(TEMP_FILE):
+ shutil.copy(TEMP_FILE, new_img)
+
+
+ if not os.path.exists(ref_img):
return False
+
+ # diff test with threshold
command = (
IDIFF,
- "-fail", "0.015",
+ "-fail", "0.016",
"-failpercent", "1",
- reference_image,
+ ref_img,
TEMP_FILE,
)
try:
@@ -130,47 +291,60 @@ def verify_output(filepath):
failed = False
except subprocess.CalledProcessError as e:
if VERBOSE:
- print(e.output.decode("utf-8"))
+ print_message(e.output.decode("utf-8"))
failed = e.returncode != 1
- if failed:
- shutil.copy(TEMP_FILE, failed_image)
- elif os.path.exists(failed_image):
- os.remove(failed_image)
+
+ # generate diff image
+ command = (
+ IDIFF,
+ "-o", diff_img,
+ "-abs", "-scale", "16",
+ ref_img,
+ TEMP_FILE
+ )
+
+ try:
+ subprocess.check_output(command)
+ except subprocess.CalledProcessError as e:
+ if VERBOSE:
+ print_message(e.output.decode("utf-8"))
+
return not failed
-def run_test(filepath):
+def run_test(report, filepath):
testname = test_get_name(filepath)
spacer = "." * (32 - len(testname))
- printMessage('SUCCESS', 'RUN', testname)
+ print_message(testname, 'SUCCESS', 'RUN')
time_start = time.time()
error = render_file(filepath)
status = "FAIL"
if not error:
- if not verify_output(filepath):
+ if not verify_output(report, filepath):
error = "VERIFY"
time_end = time.time()
elapsed_ms = int((time_end - time_start) * 1000)
if not error:
- printMessage('SUCCESS', 'OK', "{} ({} ms)" .
- format(testname, elapsed_ms))
+ print_message("{} ({} ms)" . format(testname, elapsed_ms),
+ 'SUCCESS', 'OK')
else:
if error == "NO_CYCLES":
- print("Can't perform tests because Cycles failed to load!")
- return False
+ print_message("Can't perform tests because Cycles failed to load!")
+ return error
elif error == "NO_START":
- print('Can not perform tests because blender fails to start.',
+ print_message('Can not perform tests because blender fails to start.',
'Make sure INSTALL target was run.')
- return False
+ return error
elif error == 'VERIFY':
- print("Rendered result is different from reference image")
+ print_message("Rendered result is different from reference image")
else:
- print("Unknown error %r" % error)
- printMessage('FAILURE', 'FAILED', "{} ({} ms)" .
- format(testname, elapsed_ms))
+ print_message("Unknown error %r" % error)
+ print_message("{} ({} ms)" . format(testname, elapsed_ms),
+ 'FAILURE', 'FAILED')
return error
+
def blend_list(path):
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
@@ -178,17 +352,18 @@ def blend_list(path):
filepath = os.path.join(dirpath, filename)
yield filepath
-
def run_all_tests(dirpath):
passed_tests = []
failed_tests = []
all_files = list(blend_list(dirpath))
all_files.sort()
- printMessage('SUCCESS', "==========",
- "Running {} tests from 1 test case." . format(len(all_files)))
+ report = Report(os.path.basename(dirpath))
+ print_message("Running {} tests from 1 test case." .
+ format(len(all_files)),
+ 'SUCCESS', "==========")
time_start = time.time()
for filepath in all_files:
- error = run_test(filepath)
+ error = run_test(report, filepath)
testname = test_get_name(filepath)
if error:
if error == "NO_CYCLES":
@@ -198,28 +373,33 @@ def run_all_tests(dirpath):
failed_tests.append(testname)
else:
passed_tests.append(testname)
+ report.add_test(filepath, error)
time_end = time.time()
elapsed_ms = int((time_end - time_start) * 1000)
- print("")
- printMessage('SUCCESS', "==========",
- "{} tests from 1 test case ran. ({} ms total)" .
- format(len(all_files), elapsed_ms))
- printMessage('SUCCESS', 'PASSED', "{} tests." .
- format(len(passed_tests)))
+ print_message("")
+ print_message("{} tests from 1 test case ran. ({} ms total)" .
+ format(len(all_files), elapsed_ms),
+ 'SUCCESS', "==========")
+ print_message("{} tests." .
+ format(len(passed_tests)),
+ 'SUCCESS', 'PASSED')
if failed_tests:
- printMessage('FAILURE', 'FAILED', "{} tests, listed below:" .
- format(len(failed_tests)))
+ print_message("{} tests, listed below:" .
+ format(len(failed_tests)),
+ 'FAILURE', 'FAILED')
failed_tests.sort()
for test in failed_tests:
- printMessage('FAILURE', "FAILED", "{}" . format(test))
- return False
- return True
+ print_message("{}" . format(test), 'FAILURE', "FAILED")
+
+ report.output()
+ return not bool(failed_tests)
def create_argparse():
parser = argparse.ArgumentParser()
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
+ parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
return parser
@@ -229,7 +409,7 @@ def main():
args = parser.parse_args()
global COLORS
- global BLENDER, ROOT, IDIFF
+ global BLENDER, TESTDIR, IDIFF, OUTDIR
global TEMP_FILE, TEMP_FILE_MASK, TEST_SCRIPT
global VERBOSE
@@ -237,8 +417,12 @@ def main():
COLORS = COLORS_ANSI
BLENDER = args.blender[0]
- ROOT = args.testdir[0]
+ TESTDIR = args.testdir[0]
IDIFF = args.idiff[0]
+ OUTDIR = args.outdir[0]
+
+ if not os.path.exists(OUTDIR):
+ os.makedirs(OUTDIR)
TEMP = tempfile.mkdtemp()
TEMP_FILE_MASK = os.path.join(TEMP, "test")
@@ -248,7 +432,7 @@ def main():
VERBOSE = os.environ.get("BLENDER_VERBOSE") is not None
- ok = run_all_tests(ROOT)
+ ok = run_all_tests(TESTDIR)
# Cleanup temp files and folders
if os.path.exists(TEMP_FILE):
diff --git a/tests/python/pep8.py b/tests/python/pep8.py
index 0e6250f534b..dde4250f6aa 100644
--- a/tests/python/pep8.py
+++ b/tests/python/pep8.py
@@ -178,5 +178,6 @@ def main():
"--max-line-length=1000"
" '%s'" % f)
+
if __name__ == "__main__":
main()
diff --git a/tests/python/rna_info_dump.py b/tests/python/rna_info_dump.py
index c26d94a1246..da228e52652 100644
--- a/tests/python/rna_info_dump.py
+++ b/tests/python/rna_info_dump.py
@@ -127,5 +127,6 @@ def api_dump(use_properties=True, use_functions=True):
print("END")
+
if __name__ == "__main__":
api_dump()